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

[PATCH] pcmcia: remove socket_bind_t, use pcmcia_devices instead

Remove struct socket_bind_t by moving "dev_link_t *instance" to struct
pcmcia_device, and transforming all users of socket_bind_t to use struct
pcmcia_device instead.  Also, CodingStyle updates for get_device_info and
unbind_request.
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 eac81ddc
...@@ -71,13 +71,6 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644); ...@@ -71,13 +71,6 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644);
/*====================================================================*/ /*====================================================================*/
typedef struct socket_bind_t {
struct pcmcia_driver *driver;
u_char function;
dev_link_t *instance;
struct socket_bind_t *next;
} socket_bind_t;
/* Device user information */ /* Device user information */
#define MAX_EVENTS 32 #define MAX_EVENTS 32
#define USER_MAGIC 0x7ea4 #define USER_MAGIC 0x7ea4
...@@ -99,7 +92,6 @@ struct pcmcia_bus_socket { ...@@ -99,7 +92,6 @@ struct pcmcia_bus_socket {
user_info_t *user; user_info_t *user;
int req_pending, req_result; int req_pending, req_result;
wait_queue_head_t queue, request; wait_queue_head_t queue, request;
socket_bind_t *bind;
struct pcmcia_socket *parent; struct pcmcia_socket *parent;
/* the PCMCIA devices connected to this socket (normally one, more /* the PCMCIA devices connected to this socket (normally one, more
...@@ -338,6 +330,20 @@ static int proc_read_drivers(char *buf, char **start, off_t pos, ...@@ -338,6 +330,20 @@ static int proc_read_drivers(char *buf, char **start, off_t pos,
/* pcmcia_device handling */ /* pcmcia_device handling */
static struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev)
{
struct device *tmp_dev;
tmp_dev = get_device(&p_dev->dev);
if (!tmp_dev)
return NULL;
return to_pcmcia_dev(tmp_dev);
}
static void pcmcia_put_dev(struct pcmcia_device *p_dev)
{
put_device(&p_dev->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);
...@@ -508,37 +514,29 @@ static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info) ...@@ -508,37 +514,29 @@ static int bind_mtd(struct pcmcia_bus_socket *bus_sock, mtd_info_t *mtd_info)
static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{ {
struct pcmcia_driver *driver; struct pcmcia_driver *p_drv;
struct pcmcia_device *p_dev; struct pcmcia_device *p_dev, *tmp_dev;
socket_bind_t *b;
client_t *client; client_t *client;
unsigned long flags; unsigned long flags;
int ret = 0;
if (!s) if (!s)
return -EINVAL; return -EINVAL;
ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock, ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock,
(char *)bind_info->dev_info); (char *)bind_info->dev_info);
driver = get_pcmcia_driver(&bind_info->dev_info);
if (!driver)
return -EINVAL;
for (b = s->bind; b; b = b->next) p_drv = get_pcmcia_driver(&bind_info->dev_info);
if ((driver == b->driver) && if (!p_drv)
(bind_info->function == b->function)) return -EINVAL;
break;
if (b != NULL) {
bind_info->instance = b->instance;
return -EBUSY;
}
if (!try_module_get(driver->owner)) if (!try_module_get(p_drv->owner))
return -EINVAL; return -EINVAL;
client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL); client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL);
if (!client) { if (!client) {
module_put(driver->owner); ret = -ENOMEM;
return -ENOMEM; goto err_put;
} }
memset(client, 0, sizeof(client_t)); memset(client, 0, sizeof(client_t));
...@@ -547,21 +545,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) ...@@ -547,21 +545,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
client->Function = bind_info->function; client->Function = bind_info->function;
client->state = CLIENT_UNBOUND; client->state = CLIENT_UNBOUND;
client->next = s->parent->clients; client->next = s->parent->clients;
strlcpy(client->dev_info, driver->drv.name, DEV_NAME_LEN); strlcpy(client->dev_info, p_drv->drv.name, DEV_NAME_LEN);
s->parent->clients = client;
/* Add binding to list for this socket */
b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
if (!b)
{
module_put(driver->owner);
return -ENOMEM;
}
b->driver = driver;
b->function = bind_info->function;
b->instance = NULL;
b->next = s->bind;
s->bind = b;
/* 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
...@@ -570,8 +554,8 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) ...@@ -570,8 +554,8 @@ 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) {
/* FIXME: client isn't freed here */ ret = -ENOMEM;
goto no_p_dev; goto err_free_client;
} }
memset(p_dev, 0, sizeof(struct pcmcia_device)); memset(p_dev, 0, sizeof(struct pcmcia_device));
...@@ -583,31 +567,53 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) ...@@ -583,31 +567,53 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
p_dev->dev.parent = s->parent->dev.dev; p_dev->dev.parent = s->parent->dev.dev;
p_dev->dev.release = pcmcia_release_dev; p_dev->dev.release = pcmcia_release_dev;
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 = &driver->drv; p_dev->dev.driver = &p_drv->drv;
if (device_register(&p_dev->dev)) {
/* FIXME: client isn't freed here */ ret = device_register(&p_dev->dev);
if (ret) {
kfree(p_dev); kfree(p_dev);
goto no_p_dev; goto err_free_client;
} }
/* Add to the list in pcmcia_bus_socket, but only if no device
* with the same func _and_ driver exists */
spin_lock_irqsave(&pcmcia_dev_list_lock, flags); spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) {
if ((tmp_dev->func == bind_info->function) &&
(tmp_dev->dev.driver == p_dev->dev.driver)){
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
bind_info->instance = tmp_dev->instance;
ret = -EBUSY;
goto err_unregister;
}
}
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);
no_p_dev: /* finally here the parent client is registered */
s->parent->clients = client;
driver->use_count++; p_drv->use_count++;
if (driver->attach) { if (p_drv->attach) {
b->instance = driver->attach(); p_dev->instance = p_drv->attach();
if (b->instance == NULL) { if (!p_dev->instance) {
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);
module_put(driver->owner);
/* FIXME: client isn't freed here */ /* FIXME: client isn't freed here */
return -ENODEV; ret = -ENODEV;
goto err_unregister;
} }
} }
return 0; return 0;
err_unregister:
device_unregister(&p_dev->dev);
err_free_client:
kfree(client);
err_put:
module_put(p_drv->owner);
return (ret);
} /* bind_request */ } /* bind_request */
/*====================================================================*/ /*====================================================================*/
...@@ -616,8 +622,10 @@ extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s); ...@@ -616,8 +622,10 @@ extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s);
static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first) static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first)
{ {
socket_bind_t *b;
dev_node_t *node; dev_node_t *node;
struct pcmcia_device *p_dev;
unsigned long flags;
int ret = 0;
#ifdef CONFIG_CARDBUS #ifdef CONFIG_CARDBUS
/* /*
...@@ -655,57 +663,58 @@ static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, ...@@ -655,57 +663,58 @@ static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info,
} }
#endif #endif
for (b = s->bind; b; b = b->next) spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if ((strcmp((char *)b->driver->drv.name, list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
(char *)bind_info->dev_info) == 0) && if (p_dev->func == bind_info->function) {
(b->function == bind_info->function)) p_dev = pcmcia_get_dev(p_dev);
break; if (!p_dev)
if (b == NULL) return -ENODEV; continue;
if ((b->instance == NULL) || goto found;
(b->instance->state & DEV_CONFIG_PENDING)) }
return -EAGAIN; }
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
return -ENODEV;
found:
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
if ((!p_dev->instance) ||
(p_dev->instance->state & DEV_CONFIG_PENDING)) {
ret = -EAGAIN;
goto err_put;
}
if (first) if (first)
node = b->instance->dev; node = p_dev->instance->dev;
else else
for (node = b->instance->dev; node; node = node->next) for (node = p_dev->instance->dev; node; node = node->next)
if (node == bind_info->next) break; if (node == bind_info->next)
if (node == NULL) return -ENODEV; break;
if (!node) {
ret = -ENODEV;
goto err_put;
}
strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN); strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
bind_info->major = node->major; bind_info->major = node->major;
bind_info->minor = node->minor; bind_info->minor = node->minor;
bind_info->next = node->next; bind_info->next = node->next;
return 0; err_put:
pcmcia_put_dev(p_dev);
return (ret);
} /* get_device_info */ } /* get_device_info */
/*====================================================================*/ /*====================================================================*/
static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{ {
socket_bind_t **b, *c;
struct pcmcia_device *p_dev; struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
unsigned long flags; unsigned long flags;
ds_dbg(2, "unbind_request(%d, '%s')\n", s->parent->sock, ds_dbg(2, "unbind_request(%d, '%s')\n", s->parent->sock,
(char *)bind_info->dev_info); (char *)bind_info->dev_info);
for (b = &s->bind; *b; b = &(*b)->next)
if ((strcmp((char *)(*b)->driver->drv.name,
(char *)bind_info->dev_info) == 0) &&
((*b)->function == bind_info->function))
break;
if (*b == NULL)
return -ENODEV;
c = *b;
c->driver->use_count--;
if (c->driver->detach) {
if (c->instance)
c->driver->detach(c->instance);
}
module_put(c->driver->owner);
*b = c->next;
kfree(c);
restart: restart:
/* unregister the pcmcia_device */ /* unregister the pcmcia_device */
...@@ -715,6 +724,15 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) ...@@ -715,6 +724,15 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
list_del(&p_dev->socket_device_list); list_del(&p_dev->socket_device_list);
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
/* detach the "instance" */
p_drv = to_pcmcia_drv(p_dev->dev.driver);
if (p_drv) {
p_drv->use_count--;
if ((p_drv->detach) && (p_dev->instance))
p_drv->detach(p_dev->instance);
module_put(p_drv->owner);
}
device_unregister(&p_dev->dev); device_unregister(&p_dev->dev);
/* multiple devices may be registered to this "function" */ /* multiple devices may be registered to this "function" */
......
...@@ -156,6 +156,10 @@ struct pcmcia_device { ...@@ -156,6 +156,10 @@ struct pcmcia_device {
struct list_head socket_device_list; struct list_head socket_device_list;
/* deprecated, a cleaned up version will be moved into this
struct soon */
dev_link_t *instance;
struct device dev; struct device dev;
}; };
......
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