Commit d56666b5 authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Linus Torvalds

[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: default avatarDominik Brodowski <linux@brodo.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 127faf9a
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <pcmcia/cs.h> #include <pcmcia/cs.h>
#include <pcmcia/bulkmem.h> #include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h> #include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include "cs_internal.h" #include "cs_internal.h"
#ifdef DEBUG #ifdef DEBUG
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <pcmcia/bulkmem.h> #include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h> #include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h> #include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
#include "cs_internal.h" #include "cs_internal.h"
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -199,8 +200,6 @@ static void pcmcia_release_socket(struct class_device *class_dev) ...@@ -199,8 +200,6 @@ static void pcmcia_release_socket(struct class_device *class_dev)
{ {
struct pcmcia_socket *socket = class_get_devdata(class_dev); struct pcmcia_socket *socket = class_get_devdata(class_dev);
BUG_ON(socket->clients);
complete(&socket->socket_released); complete(&socket->socket_released);
} }
...@@ -369,7 +368,6 @@ static void shutdown_socket(struct pcmcia_socket *s) ...@@ -369,7 +368,6 @@ static void shutdown_socket(struct pcmcia_socket *s)
kfree(s->config); kfree(s->config);
s->config = NULL; s->config = NULL;
} }
BUG_ON(s->clients);
free_regions(&s->a_region); free_regions(&s->a_region);
free_regions(&s->c_region); free_regions(&s->c_region);
......
...@@ -18,19 +18,7 @@ ...@@ -18,19 +18,7 @@
#include <linux/config.h> #include <linux/config.h>
#define CLIENT_MAGIC 0x51E6 #define CLIENT_MAGIC 0x51E6
typedef struct client_t { typedef struct client_t 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;
/* Flags in client state */ /* Flags in client state */
#define CLIENT_CONFIG_LOCKED 0x0001 #define CLIENT_CONFIG_LOCKED 0x0001
......
...@@ -356,6 +356,7 @@ static void pcmcia_put_dev(struct pcmcia_device *p_dev) ...@@ -356,6 +356,7 @@ static void pcmcia_put_dev(struct pcmcia_device *p_dev)
static void pcmcia_release_dev(struct device *dev) static void pcmcia_release_dev(struct device *dev)
{ {
struct pcmcia_device *p_dev = to_pcmcia_dev(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); pcmcia_put_bus_socket(p_dev->socket->pcmcia);
kfree(p_dev); kfree(p_dev);
} }
...@@ -430,11 +431,11 @@ static int send_event_callback(struct device *dev, void * _data) ...@@ -430,11 +431,11 @@ static int send_event_callback(struct device *dev, void * _data)
if (p_dev->socket != data->skt) if (p_dev->socket != data->skt)
return 0; return 0;
if (p_dev->client->state & (CLIENT_UNBOUND|CLIENT_STALE)) if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE))
return 0; return 0;
if (p_dev->client->EventMask & data->event) if (p_dev->client.EventMask & data->event)
return EVENT(p_dev->client, data->event, data->priority); return EVENT(&p_dev->client, data->event, data->priority);
return 0; return 0;
} }
...@@ -559,10 +560,10 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) ...@@ -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_driver *p_drv;
struct pcmcia_device *p_dev, *tmp_dev; struct pcmcia_device *p_dev, *tmp_dev;
client_t *client;
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
s = pcmcia_get_bus_socket(s);
if (!s) if (!s)
return -EINVAL; return -EINVAL;
...@@ -570,25 +571,10 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) ...@@ -570,25 +571,10 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
(char *)bind_info->dev_info); (char *)bind_info->dev_info);
p_drv = get_pcmcia_driver(&bind_info->dev_info); p_drv = get_pcmcia_driver(&bind_info->dev_info);
if (!p_drv) if ((!p_drv) || (!try_module_get(p_drv->owner))) {
return -EINVAL; ret = -EINVAL;
if (!try_module_get(p_drv->owner))
return -EINVAL;
client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL);
if (!client) {
ret = -ENOMEM;
goto err_put; 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. /* Currently, the userspace pcmcia cardmgr detects pcmcia devices.
* Here this information is translated into a kernel * 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) ...@@ -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); p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
if (!p_dev) { if (!p_dev) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_free_client; goto err_put_module;
} }
memset(p_dev, 0, sizeof(struct pcmcia_device)); 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->socket = s->parent;
p_dev->device_no = (s->device_count++); p_dev->device_no = (s->device_count++);
p_dev->func = bind_info->function; p_dev->func = bind_info->function;
p_dev->client = client;
p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.bus = &pcmcia_bus_type;
p_dev->dev.parent = s->parent->dev.dev; 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) ...@@ -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); sprintf (p_dev->dev.bus_id, "pcmcia%d.%d", p_dev->socket->sock, p_dev->device_no);
p_dev->dev.driver = &p_drv->drv; 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); ret = device_register(&p_dev->dev);
if (ret) { if (ret) {
kfree(p_dev); kfree(p_dev);
pcmcia_put_bus_socket(s); goto err_put_module;
goto err_free_client;
} }
/* Add to the list in pcmcia_bus_socket, but only if no device /* 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) ...@@ -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); list_add_tail(&p_dev->socket_device_list, &s->devices_list);
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
/* finally here the parent client is registered */
s->parent->clients = client;
if (p_drv->attach) { if (p_drv->attach) {
p_dev->instance = 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 " printk(KERN_NOTICE "ds: unable to create instance "
"of '%s'!\n", (char *)bind_info->dev_info); "of '%s'!\n", (char *)bind_info->dev_info);
/* FIXME: client isn't freed here */
ret = -ENODEV; ret = -ENODEV;
goto err_unregister; goto err_unregister;
} }
...@@ -660,11 +640,14 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) ...@@ -660,11 +640,14 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
err_unregister: err_unregister:
device_unregister(&p_dev->dev); device_unregister(&p_dev->dev);
err_free_client:
kfree(client);
err_put:
module_put(p_drv->owner); module_put(p_drv->owner);
return (ret); return (ret);
err_put_module:
module_put(p_drv->owner);
err_put:
pcmcia_put_bus_socket(s);
return (ret);
} /* bind_request */ } /* bind_request */
int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) 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) ...@@ -690,11 +673,11 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
continue; continue;
spin_lock_irqsave(&pcmcia_dev_list_lock, flags); spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) { list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) {
if ((p_dev->client->state & CLIENT_UNBOUND) && if ((p_dev->client.state & CLIENT_UNBOUND) &&
(!strcmp(p_dev->client->dev_info, (char *)req->dev_info))) { (!strcmp(p_dev->client.dev_info, (char *)req->dev_info))) {
p_dev = pcmcia_get_dev(p_dev); p_dev = pcmcia_get_dev(p_dev);
if (p_dev) if (p_dev)
client = p_dev->client; client = &p_dev->client;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
goto found; goto found;
} }
...@@ -753,7 +736,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) ...@@ -753,7 +736,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
} }
up(&s->skt_sem); up(&s->skt_sem);
pcmcia_put_dev(p_dev); /* FIXME: put in deregister_client. */
return CS_SUCCESS; return CS_SUCCESS;
out_no_resource: out_no_resource:
...@@ -877,7 +859,7 @@ static int unbind_request(struct pcmcia_bus_socket *s) ...@@ -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); p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
list_del(&p_dev->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); spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
/* detach the "instance" */ /* detach the "instance" */
...@@ -896,10 +878,9 @@ static int unbind_request(struct pcmcia_bus_socket *s) ...@@ -896,10 +878,9 @@ static int unbind_request(struct pcmcia_bus_socket *s)
int pcmcia_deregister_client(client_handle_t handle) int pcmcia_deregister_client(client_handle_t handle)
{ {
client_t **client;
struct pcmcia_socket *s; struct pcmcia_socket *s;
u_long flags;
int i; int i;
struct pcmcia_device *p_dev = handle_to_pdev(handle);
if (CHECK_HANDLE(handle)) if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE; return CS_BAD_HANDLE;
...@@ -914,18 +895,9 @@ int pcmcia_deregister_client(client_handle_t handle) ...@@ -914,18 +895,9 @@ int pcmcia_deregister_client(client_handle_t handle)
goto warn_out; goto warn_out;
if (handle->state & CLIENT_STALE) { 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; handle->client_magic = 0;
kfree(handle); handle->state &= ~CLIENT_STALE;
spin_unlock_irqrestore(&s->lock, flags); pcmcia_put_dev(p_dev);
} else { } else {
handle->state = CLIENT_UNBOUND; handle->state = CLIENT_UNBOUND;
handle->event_handler = NULL; handle->event_handler = NULL;
......
...@@ -128,7 +128,6 @@ typedef struct dev_link_t { ...@@ -128,7 +128,6 @@ typedef struct dev_link_t {
struct pcmcia_socket; struct pcmcia_socket;
struct client_t;
extern struct bus_type pcmcia_bus_type; extern struct bus_type pcmcia_bus_type;
...@@ -159,7 +158,18 @@ struct pcmcia_device { ...@@ -159,7 +158,18 @@ struct pcmcia_device {
/* deprecated, a cleaned up version will be moved into this /* deprecated, a cleaned up version will be moved into this
struct soon */ struct soon */
dev_link_t *instance; 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; struct device dev;
}; };
...@@ -167,6 +177,7 @@ struct pcmcia_device { ...@@ -167,6 +177,7 @@ struct pcmcia_device {
#define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev) #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 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 */ /* error reporting */
void cs_error(client_handle_t handle, int func, int ret); void cs_error(client_handle_t handle, int func, int ret);
......
...@@ -153,7 +153,6 @@ struct pcmcia_socket { ...@@ -153,7 +153,6 @@ struct pcmcia_socket {
u_int state; u_int state;
u_short functions; u_short functions;
u_short lock_count; u_short lock_count;
client_handle_t clients;
pccard_mem_map cis_mem; pccard_mem_map cis_mem;
void __iomem *cis_virt; void __iomem *cis_virt;
struct config_t *config; struct config_t *config;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment