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);
/*====================================================================*/
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 */
#define MAX_EVENTS 32
#define USER_MAGIC 0x7ea4
......@@ -99,7 +92,6 @@ struct pcmcia_bus_socket {
user_info_t *user;
int req_pending, req_result;
wait_queue_head_t queue, request;
socket_bind_t *bind;
struct pcmcia_socket *parent;
/* 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,
/* 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)
{
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)
static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{
struct pcmcia_driver *driver;
struct pcmcia_device *p_dev;
socket_bind_t *b;
struct pcmcia_driver *p_drv;
struct pcmcia_device *p_dev, *tmp_dev;
client_t *client;
unsigned long flags;
int ret = 0;
if (!s)
return -EINVAL;
ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock,
(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)
if ((driver == b->driver) &&
(bind_info->function == b->function))
break;
if (b != NULL) {
bind_info->instance = b->instance;
return -EBUSY;
}
p_drv = get_pcmcia_driver(&bind_info->dev_info);
if (!p_drv)
return -EINVAL;
if (!try_module_get(driver->owner))
if (!try_module_get(p_drv->owner))
return -EINVAL;
client = (client_t *) kmalloc(sizeof(client_t), GFP_KERNEL);
if (!client) {
module_put(driver->owner);
return -ENOMEM;
ret = -ENOMEM;
goto err_put;
}
memset(client, 0, sizeof(client_t));
......@@ -547,21 +545,7 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
client->Function = bind_info->function;
client->state = CLIENT_UNBOUND;
client->next = s->parent->clients;
strlcpy(client->dev_info, driver->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;
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
......@@ -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);
if (!p_dev) {
/* FIXME: client isn't freed here */
goto no_p_dev;
ret = -ENOMEM;
goto err_free_client;
}
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)
p_dev->dev.parent = s->parent->dev.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);
p_dev->dev.driver = &driver->drv;
if (device_register(&p_dev->dev)) {
/* FIXME: client isn't freed here */
p_dev->dev.driver = &p_drv->drv;
ret = device_register(&p_dev->dev);
if (ret) {
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);
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);
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++;
if (driver->attach) {
b->instance = driver->attach();
if (b->instance == NULL) {
p_drv->use_count++;
if (p_drv->attach) {
p_dev->instance = p_drv->attach();
if (!p_dev->instance) {
printk(KERN_NOTICE "ds: unable to create instance "
"of '%s'!\n", (char *)bind_info->dev_info);
module_put(driver->owner);
/* FIXME: client isn't freed here */
return -ENODEV;
ret = -ENODEV;
goto err_unregister;
}
}
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 */
/*====================================================================*/
......@@ -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)
{
socket_bind_t *b;
dev_node_t *node;
struct pcmcia_device *p_dev;
unsigned long flags;
int ret = 0;
#ifdef CONFIG_CARDBUS
/*
......@@ -655,57 +663,58 @@ static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info,
}
#endif
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;
if ((b->instance == NULL) ||
(b->instance->state & DEV_CONFIG_PENDING))
return -EAGAIN;
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
if (p_dev->func == bind_info->function) {
p_dev = pcmcia_get_dev(p_dev);
if (!p_dev)
continue;
goto found;
}
}
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)
node = b->instance->dev;
node = p_dev->instance->dev;
else
for (node = b->instance->dev; node; node = node->next)
if (node == bind_info->next) break;
if (node == NULL) return -ENODEV;
for (node = p_dev->instance->dev; node; node = node->next)
if (node == bind_info->next)
break;
if (!node) {
ret = -ENODEV;
goto err_put;
}
strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN);
bind_info->major = node->major;
bind_info->minor = node->minor;
bind_info->next = node->next;
return 0;
err_put:
pcmcia_put_dev(p_dev);
return (ret);
} /* get_device_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_driver *p_drv;
unsigned long flags;
ds_dbg(2, "unbind_request(%d, '%s')\n", s->parent->sock,
(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:
/* unregister the pcmcia_device */
......@@ -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);
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);
/* multiple devices may be registered to this "function" */
......
......@@ -156,6 +156,10 @@ struct pcmcia_device {
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;
};
......
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