[PATCHES] replace socket_bind_t with struct pcmcia_device

Larry W. Finger Larry.Finger at lwfinger.net
Tue Sep 30 23:00:50 BST 2003


At 12:55 AM 9/30/2003, Dominik Brodowski wrote:
>Hi,
>
>These three patches replace struct socket_bind_t with a new
>struct pcmcia_device and register it with the device core.
>
>Please consider applying,
>
>         Dominik
>
>--snip--

>pcmcia-device
>         Introduce a new struct pcmcia_device. So far it doesn't do anything
>         useful besides showing up in the sysfs tree, but this will change 
> soon.
>
>         The device registration is only done after the userspace carmgr
>         detected a pcmcia card, found it in its database, and then tries 
> to bind
>         a driver for this device. This can only properly be moved up if 
> the PCMCIA
>         socket resource management is done within the kernel. And this 
> still has
>         to wait for other changes...

As distributed, this patch will not compile. The first argument to 
spin_lock_irqsave and spin_unlock_irqrestore must be passed by reference, 
not by value. A corrected patch is attached.

Larry 
-------------- next part --------------
Introduce a new struct pcmcia_device. So far it doesn't do anything 
useful besides showing up in the sysfs tree, but this will change soon.

The device registration is only done after the userspace carmgr 
detected a pcmcia card, found it in its database, and then tries to bind
a driver for this device. This can only properly be moved up if the PCMCIA
socket resource management is done within the kernel. And this still has
to wait for other changes...

 drivers/pcmcia/ds.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 
 include/pcmcia/ds.h |   16 ++++++++++++
 2 files changed, 82 insertions(+), 2 deletions(-)

diff -ruN linux-original/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux-original/drivers/pcmcia/ds.c	2003-09-29 22:49:49.528375792 +0200
+++ linux/drivers/pcmcia/ds.c	2003-09-29 23:50:33.033478824 +0200
@@ -87,7 +87,12 @@
 	socket_bind_t		*bind;
 	struct device		*socket_dev;
 	struct pcmcia_socket	*parent;
+
+	/* the PCMCIA devices connected to this socket (normally one, more
+	 * for multifunction devices: */
+	struct list_head	devices_list;
 };
+static spinlock_t pcmcia_dev_list_lock = SPIN_LOCK_UNLOCKED;
 
 #define SOCKET_PRESENT		0x01
 #define SOCKET_BUSY		0x02
@@ -169,6 +174,15 @@
 }
 #endif
 
+/* pcmcia_device handling */
+
+static void pcmcia_release_dev(struct device *dev)
+{
+	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+	kfree(p_dev);
+}
+
+
 /*======================================================================
 
     These manage a ring buffer of events pending for one user process
@@ -306,9 +320,11 @@
 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;
     bind_req_t bind_req;
     int ret;
+    unsigned long flags;
 
     if (!s)
 	    return -EINVAL;
@@ -357,7 +373,36 @@
     b->instance = NULL;
     b->next = s->bind;
     s->bind = b;
-    
+
+    /* Currently, the userspace pcmcia cardmgr detects pcmcia devices. 
+     * Here this information is translated into a kernel
+     * struct pcmcia_device.
+     */
+
+    p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
+    if (!p_dev)
+	    goto no_p_dev;
+    memset(p_dev, 0, sizeof(struct pcmcia_device));
+
+    p_dev->socket = s->parent;
+    p_dev->func   = bind_info->function;
+
+    p_dev->dev.bus = &pcmcia_bus_type;
+    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->func);
+    p_dev->dev.driver = &driver->drv;
+    ret = device_register(&p_dev->dev);
+    if (ret) {
+	    kfree(p_dev);
+	    goto no_p_dev;
+    }
+    spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+    list_add_tail(&p_dev->socket_device_list, &s->devices_list);
+    spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ no_p_dev:
+
     if (driver->attach) {
 	b->instance = driver->attach();
 	if (b->instance == NULL) {
@@ -367,7 +412,7 @@
 	    return -ENODEV;
 	}
     }
-    
+
     return 0;
 } /* bind_request */
 
@@ -443,6 +488,8 @@
 static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
 {
     socket_bind_t **b, *c;
+    struct pcmcia_device *p_dev;
+    unsigned long flags;
 
     DEBUG(2, "unbind_request(%d, '%s')\n", s->parent->sock,
 	  (char *)bind_info->dev_info);
@@ -463,6 +510,22 @@
     module_put(c->driver->owner);
     *b = c->next;
     kfree(c);
+
+    /* unregister the pcmcia_device */
+    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)
+		    goto found;
+    }
+    spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+    return 0;
+
+ found:
+    list_del(&p_dev->socket_device_list);
+    spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+    device_unregister(&p_dev->dev);
+   
     return 0;
 } /* unbind_request */
 
@@ -822,6 +885,7 @@
 
 	init_waitqueue_head(&s->queue);
 	init_waitqueue_head(&s->request);
+	INIT_LIST_HEAD(&s->devices_list);
 
 	/* initialize data */
 	s->socket_dev = socket->dev.dev;
diff -ruN linux-original/include/pcmcia/ds.h linux/include/pcmcia/ds.h
--- linux-original/include/pcmcia/ds.h	2003-09-29 22:49:49.000000000 +0200
+++ linux/include/pcmcia/ds.h	2003-09-29 23:27:12.000000000 +0200
@@ -137,5 +137,21 @@
 /* error reporting */
 void cs_error(client_handle_t handle, int func, int ret);
 
+struct pcmcia_socket;
+
+struct pcmcia_device {
+	/* the socket and the function no [for multifunction devices]
+	   uniquely define a pcmcia_device */
+	struct pcmcia_socket	*socket;
+	u8			func; 
+
+	struct list_head	socket_device_list;
+
+	struct 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)
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_DS_H */


More information about the linux-pcmcia mailing list