From: Dominik Brodowski 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 Signed-off-by: Andrew Morton --- 25-akpm/drivers/pcmcia/bulkmem.c | 1 25-akpm/drivers/pcmcia/cs.c | 4 - 25-akpm/drivers/pcmcia/cs_internal.h | 14 ----- 25-akpm/drivers/pcmcia/ds.c | 88 +++++++++++------------------------ 25-akpm/include/pcmcia/ds.h | 15 +++++ 25-akpm/include/pcmcia/ss.h | 1 6 files changed, 46 insertions(+), 77 deletions(-) diff -puN drivers/pcmcia/bulkmem.c~pcmcia-move-struct-client_t-inside-struct-pcmcia_device drivers/pcmcia/bulkmem.c --- 25/drivers/pcmcia/bulkmem.c~pcmcia-move-struct-client_t-inside-struct-pcmcia_device 2004-12-03 18:44:45.109925448 -0800 +++ 25-akpm/drivers/pcmcia/bulkmem.c 2004-12-03 18:44:45.120923776 -0800 @@ -27,6 +27,7 @@ #include #include #include +#include #include "cs_internal.h" #ifdef DEBUG diff -puN drivers/pcmcia/cs.c~pcmcia-move-struct-client_t-inside-struct-pcmcia_device drivers/pcmcia/cs.c --- 25/drivers/pcmcia/cs.c~pcmcia-move-struct-client_t-inside-struct-pcmcia_device 2004-12-03 18:44:45.111925144 -0800 +++ 25-akpm/drivers/pcmcia/cs.c 2004-12-03 18:44:45.122923472 -0800 @@ -41,6 +41,7 @@ #include #include #include +#include #include "cs_internal.h" #ifdef CONFIG_PCI @@ -199,8 +200,6 @@ static void pcmcia_release_socket(struct { 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 pcmci kfree(s->config); s->config = NULL; } - BUG_ON(s->clients); free_regions(&s->a_region); free_regions(&s->c_region); diff -puN drivers/pcmcia/cs_internal.h~pcmcia-move-struct-client_t-inside-struct-pcmcia_device drivers/pcmcia/cs_internal.h --- 25/drivers/pcmcia/cs_internal.h~pcmcia-move-struct-client_t-inside-struct-pcmcia_device 2004-12-03 18:44:45.112924992 -0800 +++ 25-akpm/drivers/pcmcia/cs_internal.h 2004-12-03 18:44:45.123923320 -0800 @@ -18,19 +18,7 @@ #include #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 -puN drivers/pcmcia/ds.c~pcmcia-move-struct-client_t-inside-struct-pcmcia_device drivers/pcmcia/ds.c --- 25/drivers/pcmcia/ds.c~pcmcia-move-struct-client_t-inside-struct-pcmcia_device 2004-12-03 18:44:45.114924688 -0800 +++ 25-akpm/drivers/pcmcia/ds.c 2004-12-03 18:44:45.125923016 -0800 @@ -353,6 +353,7 @@ static void pcmcia_put_dev(struct pcmcia 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); } @@ -427,11 +428,11 @@ static int send_event_callback(struct de 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; } @@ -556,10 +557,10 @@ static int bind_request(struct pcmcia_bu { 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; @@ -567,25 +568,10 @@ static int bind_request(struct pcmcia_bu (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 @@ -595,20 +581,12 @@ static int bind_request(struct pcmcia_bu 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->func = bind_info->function; - p_dev->client = client; p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.parent = s->parent->dev.dev; @@ -616,11 +594,17 @@ static int bind_request(struct pcmcia_bu sprintf (p_dev->dev.bus_id, "pcmcia%d.%d", p_dev->socket->sock, p_dev->func); 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; } /* @@ -640,15 +624,11 @@ static int bind_request(struct pcmcia_bu 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; } @@ -658,11 +638,14 @@ static int bind_request(struct pcmcia_bu 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) @@ -688,11 +671,11 @@ int pcmcia_register_client(client_handle 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; } @@ -751,7 +734,6 @@ int pcmcia_register_client(client_handle } up(&s->skt_sem); - pcmcia_put_dev(p_dev); /* FIXME: put in deregister_client. */ return CS_SUCCESS; out_no_resource: @@ -873,7 +855,7 @@ static int unbind_request(struct pcmcia_ } 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" */ @@ -892,10 +874,9 @@ static int unbind_request(struct pcmcia_ 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; @@ -910,18 +891,9 @@ int pcmcia_deregister_client(client_hand 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; diff -puN include/pcmcia/ds.h~pcmcia-move-struct-client_t-inside-struct-pcmcia_device include/pcmcia/ds.h --- 25/include/pcmcia/ds.h~pcmcia-move-struct-client_t-inside-struct-pcmcia_device 2004-12-03 18:44:45.115924536 -0800 +++ 25-akpm/include/pcmcia/ds.h 2004-12-03 18:44:45.125923016 -0800 @@ -128,7 +128,6 @@ typedef struct dev_link_t { struct pcmcia_socket; -struct client_t; extern struct bus_type pcmcia_bus_type; @@ -154,7 +153,18 @@ struct pcmcia_device { /* deprecated, a cleaned up version will be moved into this struct soon */ dev_link_t *instance; - struct client_t *client; + 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; + } client; struct device dev; }; @@ -162,6 +172,7 @@ struct pcmcia_device { #define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev) #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv) +#define handle_to_pdev(handle) container_of(handle, struct pcmcia_device, client); /* error reporting */ void cs_error(client_handle_t handle, int func, int ret); diff -puN include/pcmcia/ss.h~pcmcia-move-struct-client_t-inside-struct-pcmcia_device include/pcmcia/ss.h --- 25/include/pcmcia/ss.h~pcmcia-move-struct-client_t-inside-struct-pcmcia_device 2004-12-03 18:44:45.117924232 -0800 +++ 25-akpm/include/pcmcia/ss.h 2004-12-03 18:44:45.126922864 -0800 @@ -153,7 +153,6 @@ struct pcmcia_socket { u_int state; u_short functions; u_short lock_count; - client_handle_t clients; pccard_mem_map cis_mem; void __iomem *cis_virt; struct config_t *config; _