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 Index: 2.6.10-rc3/drivers/pcmcia/bulkmem.c =================================================================== --- 2.6.10-rc3.orig/drivers/pcmcia/bulkmem.c 2004-12-13 15:59:18.255715770 +0100 +++ 2.6.10-rc3/drivers/pcmcia/bulkmem.c 2004-12-13 16:00:01.584684281 +0100 @@ -27,6 +27,7 @@ #include #include #include +#include #include "cs_internal.h" #ifdef DEBUG Index: 2.6.10-rc3/drivers/pcmcia/cs.c =================================================================== --- 2.6.10-rc3.orig/drivers/pcmcia/cs.c 2004-12-13 15:59:50.042291008 +0100 +++ 2.6.10-rc3/drivers/pcmcia/cs.c 2004-12-13 16:00:01.585684142 +0100 @@ -41,6 +41,7 @@ #include #include #include +#include #include "cs_internal.h" #ifdef CONFIG_PCI @@ -199,8 +200,6 @@ { struct pcmcia_socket *socket = class_get_devdata(class_dev); - BUG_ON(socket->clients); - complete(&socket->socket_released); } @@ -369,7 +368,6 @@ kfree(s->config); s->config = NULL; } - BUG_ON(s->clients); free_regions(&s->a_region); free_regions(&s->c_region); Index: 2.6.10-rc3/drivers/pcmcia/cs_internal.h =================================================================== --- 2.6.10-rc3.orig/drivers/pcmcia/cs_internal.h 2004-12-13 15:59:18.273713265 +0100 +++ 2.6.10-rc3/drivers/pcmcia/cs_internal.h 2004-12-13 16:00:01.586684003 +0100 @@ -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 Index: 2.6.10-rc3/drivers/pcmcia/ds.c =================================================================== --- 2.6.10-rc3.orig/drivers/pcmcia/ds.c 2004-12-13 15:59:50.044290730 +0100 +++ 2.6.10-rc3/drivers/pcmcia/ds.c 2004-12-13 16:00:29.145847706 +0100 @@ -356,6 +356,7 @@ 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 @@ 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 @@ { 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 @@ (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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } up(&s->skt_sem); - pcmcia_put_dev(p_dev); /* FIXME: put in deregister_client. */ return CS_SUCCESS; out_no_resource: @@ -877,7 +859,7 @@ } 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 @@ 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 @@ 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; Index: 2.6.10-rc3/include/pcmcia/ds.h =================================================================== --- 2.6.10-rc3.orig/include/pcmcia/ds.h 2004-12-13 15:59:36.571166219 +0100 +++ 2.6.10-rc3/include/pcmcia/ds.h 2004-12-13 16:00:01.601681915 +0100 @@ -128,7 +128,6 @@ struct pcmcia_socket; -struct client_t; extern struct bus_type pcmcia_bus_type; @@ -159,7 +158,18 @@ /* 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; }; @@ -167,6 +177,7 @@ #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); Index: 2.6.10-rc3/include/pcmcia/ss.h =================================================================== --- 2.6.10-rc3.orig/include/pcmcia/ss.h 2004-12-13 15:59:18.279712430 +0100 +++ 2.6.10-rc3/include/pcmcia/ss.h 2004-12-13 16:00:01.601681915 +0100 @@ -153,7 +153,6 @@ 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;