aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.de>2005-01-11 03:24:11 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-11 03:24:11 -0800
commitd56666b522432b244f38f52f89a3ccf275c4e41d (patch)
treef42e6907284bde3d0dd993a6ec37293c3423827e /drivers
parent127faf9ab34df6f5ea874df72388409b14b171b5 (diff)
downloadhistory-d56666b522432b244f38f52f89a3ccf275c4e41d.tar.gz
[PATCH] pcmcia: move struct client_t inside struct pcmcia_device
Move the struct client_t inside struct pcmcia_device. This means it gets proper reference counting as well. The clients list inside struct pcmcia_socket can be removed now. Signed-off-by: Dominik Brodowski <linux@brodo.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pcmcia/bulkmem.c1
-rw-r--r--drivers/pcmcia/cs.c4
-rw-r--r--drivers/pcmcia/cs_internal.h14
-rw-r--r--drivers/pcmcia/ds.c88
4 files changed, 33 insertions, 74 deletions
diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c
index 1be40034acd432..8997b5c04a9e51 100644
--- a/drivers/pcmcia/bulkmem.c
+++ b/drivers/pcmcia/bulkmem.c
@@ -27,6 +27,7 @@
#include <pcmcia/cs.h>
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
#include "cs_internal.h"
#ifdef DEBUG
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index b93ec422c78aad..e875cb399ffbfc 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -41,6 +41,7 @@
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
#include "cs_internal.h"
#ifdef CONFIG_PCI
@@ -199,8 +200,6 @@ static void pcmcia_release_socket(struct class_device *class_dev)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
- BUG_ON(socket->clients);
-
complete(&socket->socket_released);
}
@@ -369,7 +368,6 @@ static void shutdown_socket(struct pcmcia_socket *s)
kfree(s->config);
s->config = NULL;
}
- BUG_ON(s->clients);
free_regions(&s->a_region);
free_regions(&s->c_region);
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 67f85f56fe9d7d..6d441e178f63ff 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -18,19 +18,7 @@
#include <linux/config.h>
#define CLIENT_MAGIC 0x51E6
-typedef struct client_t {
- u_short client_magic;
- struct pcmcia_socket *Socket;
- u_char Function;
- dev_info_t dev_info;
- u_int Attributes;
- u_int state;
- event_t EventMask, PendingEvents;
- int (*event_handler)(event_t event, int priority,
- event_callback_args_t *);
- event_callback_args_t event_callback_args;
- struct client_t *next;
-} client_t;
+typedef struct client_t client_t;
/* Flags in client state */
#define CLIENT_CONFIG_LOCKED 0x0001
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 059f02471b627d..f6609d8f463921 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -356,6 +356,7 @@ static void pcmcia_put_dev(struct pcmcia_device *p_dev)
static void pcmcia_release_dev(struct device *dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ ds_dbg(1, "releasing dev %p\n", p_dev);
pcmcia_put_bus_socket(p_dev->socket->pcmcia);
kfree(p_dev);
}
@@ -430,11 +431,11 @@ static int send_event_callback(struct device *dev, void * _data)
if (p_dev->socket != data->skt)
return 0;
- if (p_dev->client->state & (CLIENT_UNBOUND|CLIENT_STALE))
+ if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE))
return 0;
- if (p_dev->client->EventMask & data->event)
- return EVENT(p_dev->client, data->event, data->priority);
+ if (p_dev->client.EventMask & data->event)
+ return EVENT(&p_dev->client, data->event, data->priority);
return 0;
}
@@ -559,10 +560,10 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{
struct pcmcia_driver *p_drv;
struct pcmcia_device *p_dev, *tmp_dev;
- client_t *client;
unsigned long flags;
int ret = 0;
+ s = pcmcia_get_bus_socket(s);
if (!s)
return -EINVAL;
@@ -570,25 +571,10 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
(char *)bind_info->dev_info);
p_drv = get_pcmcia_driver(&bind_info->dev_info);
- if (!p_drv)
- return -EINVAL;
-
- if (!try_module_get(p_drv->owner))
- return -EINVAL;
-
- client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL);
- if (!client) {
- ret = -ENOMEM;
+ if ((!p_drv) || (!try_module_get(p_drv->owner))) {
+ ret = -EINVAL;
goto err_put;
}
- memset(client, 0, sizeof(client_t));
-
- client->client_magic = CLIENT_MAGIC;
- client->Socket = s->parent;
- client->Function = bind_info->function;
- client->state = CLIENT_UNBOUND;
- client->next = s->parent->clients;
- strlcpy(client->dev_info, p_drv->drv.name, DEV_NAME_LEN);
/* Currently, the userspace pcmcia cardmgr detects pcmcia devices.
* Here this information is translated into a kernel
@@ -598,21 +584,13 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
if (!p_dev) {
ret = -ENOMEM;
- goto err_free_client;
+ goto err_put_module;
}
memset(p_dev, 0, sizeof(struct pcmcia_device));
- s = pcmcia_get_bus_socket(s);
- if (!s) {
- ret = -ENODEV;
- kfree(p_dev);
- goto err_free_client;
- }
-
p_dev->socket = s->parent;
p_dev->device_no = (s->device_count++);
p_dev->func = bind_info->function;
- p_dev->client = client;
p_dev->dev.bus = &pcmcia_bus_type;
p_dev->dev.parent = s->parent->dev.dev;
@@ -620,11 +598,17 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
sprintf (p_dev->dev.bus_id, "pcmcia%d.%d", p_dev->socket->sock, p_dev->device_no);
p_dev->dev.driver = &p_drv->drv;
+ /* compat */
+ p_dev->client.client_magic = CLIENT_MAGIC;
+ p_dev->client.Socket = s->parent;
+ p_dev->client.Function = bind_info->function;
+ p_dev->client.state = CLIENT_UNBOUND;
+ strlcpy(p_dev->client.dev_info, p_drv->drv.name, DEV_NAME_LEN);
+
ret = device_register(&p_dev->dev);
if (ret) {
kfree(p_dev);
- pcmcia_put_bus_socket(s);
- goto err_free_client;
+ goto err_put_module;
}
/* Add to the list in pcmcia_bus_socket, but only if no device
@@ -642,15 +626,11 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
list_add_tail(&p_dev->socket_device_list, &s->devices_list);
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- /* finally here the parent client is registered */
- s->parent->clients = client;
-
if (p_drv->attach) {
p_dev->instance = p_drv->attach();
- if (!p_dev->instance) {
+ if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) {
printk(KERN_NOTICE "ds: unable to create instance "
"of '%s'!\n", (char *)bind_info->dev_info);
- /* FIXME: client isn't freed here */
ret = -ENODEV;
goto err_unregister;
}
@@ -660,11 +640,14 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
err_unregister:
device_unregister(&p_dev->dev);
- err_free_client:
- kfree(client);
- err_put:
module_put(p_drv->owner);
return (ret);
+
+ err_put_module:
+ module_put(p_drv->owner);
+ err_put:
+ pcmcia_put_bus_socket(s);
+ return (ret);
} /* bind_request */
int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
@@ -690,11 +673,11 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
continue;
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) {
- if ((p_dev->client->state & CLIENT_UNBOUND) &&
- (!strcmp(p_dev->client->dev_info, (char *)req->dev_info))) {
+ if ((p_dev->client.state & CLIENT_UNBOUND) &&
+ (!strcmp(p_dev->client.dev_info, (char *)req->dev_info))) {
p_dev = pcmcia_get_dev(p_dev);
if (p_dev)
- client = p_dev->client;
+ client = &p_dev->client;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
goto found;
}
@@ -753,7 +736,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
}
up(&s->skt_sem);
- pcmcia_put_dev(p_dev); /* FIXME: put in deregister_client. */
return CS_SUCCESS;
out_no_resource:
@@ -877,7 +859,7 @@ static int unbind_request(struct pcmcia_bus_socket *s)
}
p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
list_del(&p_dev->socket_device_list);
- p_dev->client->state |= CLIENT_STALE;
+ p_dev->client.state |= CLIENT_STALE;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
/* detach the "instance" */
@@ -896,10 +878,9 @@ static int unbind_request(struct pcmcia_bus_socket *s)
int pcmcia_deregister_client(client_handle_t handle)
{
- client_t **client;
struct pcmcia_socket *s;
- u_long flags;
int i;
+ struct pcmcia_device *p_dev = handle_to_pdev(handle);
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
@@ -914,18 +895,9 @@ int pcmcia_deregister_client(client_handle_t handle)
goto warn_out;
if (handle->state & CLIENT_STALE) {
- spin_lock_irqsave(&s->lock, flags);
- client = &s->clients;
- while ((*client) && ((*client) != handle))
- client = &(*client)->next;
- if (*client == NULL) {
- spin_unlock_irqrestore(&s->lock, flags);
- return CS_BAD_HANDLE;
- }
- *client = handle->next;
handle->client_magic = 0;
- kfree(handle);
- spin_unlock_irqrestore(&s->lock, flags);
+ handle->state &= ~CLIENT_STALE;
+ pcmcia_put_dev(p_dev);
} else {
handle->state = CLIENT_UNBOUND;
handle->event_handler = NULL;