
From: Dominik Brodowski <linux@dominikbrodowski.de>

01-update-network-drivers

This patch updates pcmcia network drivers so that their class devices are
linked to the correct physical device.  Based on an patch by Adam Belay,
but adapted to a different pcmcia driver model implementation.

02-update-wireless-drivers

This patch updates pcmcia wireless drivers so that their class devices are
linked to the correct physical device.  Based on an patch by Adam Belay,
but adapted to a different pcmcia driver model implementation.

03-driver-find:

Use driver_find() in ds.c instead of legacy implementation, and make use of
its reference counting awareness.

Signed-off-by: Dominik Brodowski <linux@brodo.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/net/pcmcia/3c574_cs.c     |    1 
 25-akpm/drivers/net/pcmcia/3c589_cs.c     |    1 
 25-akpm/drivers/net/pcmcia/axnet_cs.c     |    1 
 25-akpm/drivers/net/pcmcia/com20020_cs.c  |    1 
 25-akpm/drivers/net/pcmcia/fmvj18x_cs.c   |    1 
 25-akpm/drivers/net/pcmcia/ibmtr_cs.c     |    1 
 25-akpm/drivers/net/pcmcia/nmclan_cs.c    |    1 
 25-akpm/drivers/net/pcmcia/pcnet_cs.c     |    1 
 25-akpm/drivers/net/pcmcia/smc91c92_cs.c  |    1 
 25-akpm/drivers/net/pcmcia/xirc2ps_cs.c   |    1 
 25-akpm/drivers/net/wireless/airo.c       |   20 ++++++------
 25-akpm/drivers/net/wireless/airo_cs.c    |    4 +-
 25-akpm/drivers/net/wireless/atmel_cs.c   |   17 ----------
 25-akpm/drivers/net/wireless/netwave_cs.c |    2 +
 25-akpm/drivers/net/wireless/orinoco_cs.c |    1 
 25-akpm/drivers/net/wireless/ray_cs.c     |    1 
 25-akpm/drivers/net/wireless/wavelan_cs.c |    1 
 25-akpm/drivers/net/wireless/wl3501_cs.c  |    1 
 25-akpm/drivers/pcmcia/ds.c               |   50 +++++++++++++-----------------
 25-akpm/include/pcmcia/ds.h               |    1 
 20 files changed, 53 insertions(+), 55 deletions(-)

diff -puN drivers/net/pcmcia/3c574_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/3c574_cs.c
--- 25/drivers/net/pcmcia/3c574_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.333506680 -0800
+++ 25-akpm/drivers/net/pcmcia/3c574_cs.c	2004-11-07 22:37:13.368501360 -0800
@@ -519,6 +519,7 @@ static void tc574_config(dev_link_t *lin
 
 	link->state &= ~DEV_CONFIG_PENDING;
 	link->dev = &lp->node;
+	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
 	if (register_netdev(dev) != 0) {
 		printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
diff -puN drivers/net/pcmcia/3c589_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/3c589_cs.c
--- 25/drivers/net/pcmcia/3c589_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.334506528 -0800
+++ 25-akpm/drivers/net/pcmcia/3c589_cs.c	2004-11-07 22:37:13.369501208 -0800
@@ -391,6 +391,7 @@ static void tc589_config(dev_link_t *lin
     
     link->dev = &lp->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
diff -puN drivers/net/pcmcia/axnet_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/axnet_cs.c
--- 25/drivers/net/pcmcia/axnet_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.336506224 -0800
+++ 25-akpm/drivers/net/pcmcia/axnet_cs.c	2004-11-07 22:37:13.370501056 -0800
@@ -458,6 +458,7 @@ static void axnet_config(dev_link_t *lin
     info->phy_id = (i < 32) ? i : -1;
     link->dev = &info->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
diff -puN drivers/net/pcmcia/com20020_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/com20020_cs.c
--- 25/drivers/net/pcmcia/com20020_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.337506072 -0800
+++ 25-akpm/drivers/net/pcmcia/com20020_cs.c	2004-11-07 22:37:13.371500904 -0800
@@ -394,6 +394,7 @@ static void com20020_config(dev_link_t *
 
     link->dev = &info->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
     i = com20020_found(dev, 0);	/* calls register_netdev */
     
diff -puN drivers/net/pcmcia/fmvj18x_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/fmvj18x_cs.c
--- 25/drivers/net/pcmcia/fmvj18x_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.339505768 -0800
+++ 25-akpm/drivers/net/pcmcia/fmvj18x_cs.c	2004-11-07 22:37:13.372500752 -0800
@@ -591,6 +591,7 @@ static void fmvj18x_config(dev_link_t *l
     lp->cardtype = cardtype;
     link->dev = &lp->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
diff -puN drivers/net/pcmcia/ibmtr_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/ibmtr_cs.c
--- 25/drivers/net/pcmcia/ibmtr_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.340505616 -0800
+++ 25-akpm/drivers/net/pcmcia/ibmtr_cs.c	2004-11-07 22:37:13.373500600 -0800
@@ -367,6 +367,7 @@ static void ibmtr_config(dev_link_t *lin
 
     link->dev = &info->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
     i = ibmtr_probe_card(dev);
     if (i != 0) {
diff -puN drivers/net/pcmcia/nmclan_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/nmclan_cs.c
--- 25/drivers/net/pcmcia/nmclan_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.342505312 -0800
+++ 25-akpm/drivers/net/pcmcia/nmclan_cs.c	2004-11-07 22:37:13.374500448 -0800
@@ -775,6 +775,7 @@ static void nmclan_config(dev_link_t *li
 
   link->dev = &lp->node;
   link->state &= ~DEV_CONFIG_PENDING;
+  SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
   i = register_netdev(dev);
   if (i != 0) {
diff -puN drivers/net/pcmcia/pcnet_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/pcnet_cs.c
--- 25/drivers/net/pcmcia/pcnet_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.343505160 -0800
+++ 25-akpm/drivers/net/pcmcia/pcnet_cs.c	2004-11-07 22:37:13.375500296 -0800
@@ -722,6 +722,7 @@ static void pcnet_config(dev_link_t *lin
 
     link->dev = &info->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
     dev->poll_controller = ei_poll;
diff -puN drivers/net/pcmcia/smc91c92_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/smc91c92_cs.c
--- 25/drivers/net/pcmcia/smc91c92_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.346504704 -0800
+++ 25-akpm/drivers/net/pcmcia/smc91c92_cs.c	2004-11-07 22:37:13.377499992 -0800
@@ -1024,6 +1024,7 @@ static void smc91c92_config(dev_link_t *
 
     link->dev = &smc->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
diff -puN drivers/net/pcmcia/xirc2ps_cs.c~pcmcia-19-netdevice-integration drivers/net/pcmcia/xirc2ps_cs.c
--- 25/drivers/net/pcmcia/xirc2ps_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.347504552 -0800
+++ 25-akpm/drivers/net/pcmcia/xirc2ps_cs.c	2004-11-07 22:37:13.379499688 -0800
@@ -1121,6 +1121,7 @@ xirc2ps_config(dev_link_t * link)
 
     link->dev = &local->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
     if ((err=register_netdev(dev))) {
 	printk(KNOT_XIRC "register_netdev() failed\n");
diff -puN drivers/net/wireless/airo.c~pcmcia-19-netdevice-integration drivers/net/wireless/airo.c
--- 25/drivers/net/wireless/airo.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.350504096 -0800
+++ 25-akpm/drivers/net/wireless/airo.c	2004-11-07 22:37:13.385498776 -0800
@@ -2694,7 +2694,8 @@ int reset_card( struct net_device *dev ,
 }
 
 struct net_device *_init_airo_card( unsigned short irq, int port,
-				    int is_pcmcia, struct pci_dev *pci )
+				    int is_pcmcia, struct pci_dev *pci,
+				    struct device *dmdev )
 {
 	struct net_device *dev;
 	struct airo_info *ai;
@@ -2756,10 +2757,8 @@ struct net_device *_init_airo_card( unsi
 	dev->irq = irq;
 	dev->base_addr = port;
 
-	/* what is with PCMCIA ??? */
-	if (pci) {
-		SET_NETDEV_DEV(dev, &pci->dev);
-	}
+	SET_NETDEV_DEV(dev, dmdev);
+
 
 	if (test_bit(FLAG_MPI,&ai->flags))
 		reset_card (dev, 1);
@@ -2841,9 +2840,10 @@ err_out_free:
 	return NULL;
 }
 
-struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia )
+struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia,
+				  struct device *dmdev)
 {
-	return _init_airo_card ( irq, port, is_pcmcia, NULL);
+	return _init_airo_card ( irq, port, is_pcmcia, NULL, dmdev);
 }
 
 EXPORT_SYMBOL(init_airo_card);
@@ -5452,9 +5452,9 @@ static int __devinit airo_pci_probe(stru
 	pci_set_master(pdev);
 
 	if (pdev->device == 0x5000 || pdev->device == 0xa504)
-			dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev);
+			dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
 	else
-			dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev);
+			dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
 	if (!dev)
 		return -ENODEV;
 
@@ -5556,7 +5556,7 @@ static int __init airo_init_module( void
 		printk( KERN_INFO
 			"airo:  Trying to configure ISA adapter at irq=%d io=0x%x\n",
 			irq[i], io[i] );
-		if (init_airo_card( irq[i], io[i], 0 ))
+		if (init_airo_card( irq[i], io[i], 0, NULL ))
 			have_isa_dev = 1;
 	}
 
diff -puN drivers/net/wireless/airo_cs.c~pcmcia-19-netdevice-integration drivers/net/wireless/airo_cs.c
--- 25/drivers/net/wireless/airo_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.351503944 -0800
+++ 25-akpm/drivers/net/wireless/airo_cs.c	2004-11-07 22:37:13.386498624 -0800
@@ -89,7 +89,7 @@ MODULE_PARM(irq_list, "1-4i");
    event handler. 
 */
 
-struct net_device *init_airo_card( int, int, int );
+struct net_device *init_airo_card( int, int, int, struct device * );
 void stop_airo_card( struct net_device *, int );
 int reset_airo_card( struct net_device * );
 
@@ -450,7 +450,7 @@ static void airo_config(dev_link_t *link
 	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
 	((local_info_t*)link->priv)->eth_dev = 
 		init_airo_card( link->irq.AssignedIRQ,
-				link->io.BasePort1, 1 );
+				link->io.BasePort1, 1, &handle_to_dev(handle) );
 	if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
 	
 	/*
diff -puN drivers/net/wireless/atmel_cs.c~pcmcia-19-netdevice-integration drivers/net/wireless/atmel_cs.c
--- 25/drivers/net/wireless/atmel_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.353503640 -0800
+++ 25-akpm/drivers/net/wireless/atmel_cs.c	2004-11-07 22:37:13.387498472 -0800
@@ -347,21 +347,6 @@ static struct { 
 	{ 0, 0, "11WAVE/11WP611AL-E", "atmel_at76c502e%s.bin", "11WAVE WaveBuddy" } 
 };
 
-/* This is strictly temporary, until PCMCIA devices get integrated into the device model. */
-static struct device *atmel_device(void)
-{
-	static char *kobj_name = "atmel_cs";
-
-	static struct device dev = {
-		.bus_id    = "pcmcia",
-	};
-	dev.kobj.k_name = kmalloc(strlen(kobj_name)+1, GFP_KERNEL);
-	strcpy(dev.kobj.k_name, kobj_name);
-	kobject_init(&dev.kobj);
-	
-	return &dev;
-}
-
 static void atmel_config(dev_link_t *link)
 {
 	client_handle_t handle;
@@ -552,7 +537,7 @@ static void atmel_config(dev_link_t *lin
 		init_atmel_card(link->irq.AssignedIRQ,
 				link->io.BasePort1,
 				card_index == -1 ? NULL :  card_table[card_index].firmware,
-				atmel_device(),
+				&handle_to_dev(handle),
 				card_present, 
 				link);
 	if (!((local_info_t*)link->priv)->eth_dev) 
diff -puN drivers/net/wireless/netwave_cs.c~pcmcia-19-netdevice-integration drivers/net/wireless/netwave_cs.c
--- 25/drivers/net/wireless/netwave_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.354503488 -0800
+++ 25-akpm/drivers/net/wireless/netwave_cs.c	2004-11-07 22:37:13.389498168 -0800
@@ -1073,6 +1073,8 @@ static void netwave_pcmcia_config(dev_li
 
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+
     if (register_netdev(dev) != 0) {
 	printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
 	goto failed;
diff -puN drivers/net/wireless/orinoco_cs.c~pcmcia-19-netdevice-integration drivers/net/wireless/orinoco_cs.c
--- 25/drivers/net/wireless/orinoco_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.355503336 -0800
+++ 25-akpm/drivers/net/wireless/orinoco_cs.c	2004-11-07 22:37:13.390498016 -0800
@@ -458,6 +458,7 @@ orinoco_cs_config(dev_link_t *link)
 
 	/* register_netdev will give us an ethX name */
 	dev->name[0] = '\0';
+	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 	/* Tell the stack we exist */
 	if (register_netdev(dev) != 0) {
 		printk(KERN_ERR PFX "register_netdev() failed\n");
diff -puN drivers/net/wireless/ray_cs.c~pcmcia-19-netdevice-integration drivers/net/wireless/ray_cs.c
--- 25/drivers/net/wireless/ray_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.357503032 -0800
+++ 25-akpm/drivers/net/wireless/ray_cs.c	2004-11-07 22:37:13.393497560 -0800
@@ -564,6 +564,7 @@ static void ray_config(dev_link_t *link)
         return;
     }
 
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
     i = register_netdev(dev);
     if (i != 0) {
         printk("ray_config register_netdev() failed\n");
diff -puN drivers/net/wireless/wavelan_cs.c~pcmcia-19-netdevice-integration drivers/net/wireless/wavelan_cs.c
--- 25/drivers/net/wireless/wavelan_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.359502728 -0800
+++ 25-akpm/drivers/net/wireless/wavelan_cs.c	2004-11-07 22:37:13.396497104 -0800
@@ -4068,6 +4068,7 @@ wv_pcmcia_config(dev_link_t *	link)
 	     lp->mem, dev->irq, (u_int) dev->base_addr);
 #endif
 
+      SET_NETDEV_DEV(dev, &handle_to_dev(handle));
       i = register_netdev(dev);
       if(i != 0)
 	{
diff -puN drivers/net/wireless/wl3501_cs.c~pcmcia-19-netdevice-integration drivers/net/wireless/wl3501_cs.c
--- 25/drivers/net/wireless/wl3501_cs.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.361502424 -0800
+++ 25-akpm/drivers/net/wireless/wl3501_cs.c	2004-11-07 22:37:13.398496800 -0800
@@ -2105,6 +2105,7 @@ static void wl3501_config(dev_link_t *li
 
 	dev->irq = link->irq.AssignedIRQ;
 	dev->base_addr = link->io.BasePort1;
+	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 	if (register_netdev(dev)) {
 		printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
 		goto failed;
diff -puN drivers/pcmcia/ds.c~pcmcia-19-netdevice-integration drivers/pcmcia/ds.c
--- 25/drivers/pcmcia/ds.c~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.363502120 -0800
+++ 25-akpm/drivers/pcmcia/ds.c	2004-11-07 22:37:13.400496496 -0800
@@ -565,9 +565,14 @@ static int bind_request(struct pcmcia_bu
 	       (char *)bind_info->dev_info);
 
 	p_drv = get_pcmcia_driver(&bind_info->dev_info);
-	if ((!p_drv) || (!try_module_get(p_drv->owner)))
+	if (!p_drv)
 		return -EINVAL;
 
+	if (!try_module_get(p_drv->owner)) {
+		put_driver(&p_drv->drv);
+		return -EINVAL;
+	}
+
 	/* Currently, the userspace pcmcia cardmgr detects pcmcia devices.
 	 * Here this information is translated into a kernel
 	 * struct pcmcia_device.
@@ -630,13 +635,19 @@ static int bind_request(struct pcmcia_bu
 			goto err_unregister;
 		}
 	}
-    
+
+	put_driver(&p_drv->drv); /* we can safely put the reference we got
+				  * in get_pcmcia_device here, as the device
+				  * got added in between and holds a reference
+				  * for us. */
+
 	return 0;
 
  err_unregister:
 	device_unregister(&p_dev->dev);
  err_put:
 	module_put(p_drv->owner);
+	put_driver(&p_drv->drv);
 	return (ret);
 } /* bind_request */
 
@@ -1416,33 +1427,18 @@ static struct pcmcia_bus_socket * get_so
 
 /* backwards-compatible accessing of driver --- by name! */
 
-struct cmp_data {
-	void *dev_info;
-	struct pcmcia_driver *drv;
-};
-
-static int cmp_drv_callback(struct device_driver *drv, void *data)
-{
-	struct cmp_data *cmp = data;
-	if (strncmp((char *)cmp->dev_info, (char *)drv->name,
-		    DEV_NAME_LEN) == 0) {
-		cmp->drv = container_of(drv, struct pcmcia_driver, drv);
-		return -EINVAL;
-	}
-	return 0;
-}
-
 static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
 {
-	int ret;
-	struct cmp_data cmp = {
-		.dev_info = dev_info,
-	};
-	
-	ret = bus_for_each_drv(&pcmcia_bus_type, NULL, &cmp, cmp_drv_callback);
-	if (ret)
-		return cmp.drv;
-	return NULL;
+	struct device_driver *drv;
+	struct pcmcia_driver *p_drv;
+
+	drv = driver_find((char *) dev_info, &pcmcia_bus_type);
+	if (!drv)
+		return NULL;
+
+	p_drv = container_of(drv, struct pcmcia_driver, drv);
+
+	return (p_drv);
 }
 
 MODULE_ALIAS("ds");
diff -puN include/pcmcia/ds.h~pcmcia-19-netdevice-integration include/pcmcia/ds.h
--- 25/include/pcmcia/ds.h~pcmcia-19-netdevice-integration	2004-11-07 22:37:13.364501968 -0800
+++ 25-akpm/include/pcmcia/ds.h	2004-11-07 22:37:13.400496496 -0800
@@ -173,6 +173,7 @@ struct pcmcia_device {
 #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv)
 
 #define handle_to_pdev(handle) container_of(handle, struct pcmcia_device, client);
+#define handle_to_dev(handle) ((container_of(handle, struct pcmcia_device, client))->dev)
 
 /* error reporting */
 void cs_error(client_handle_t handle, int func, int ret);
_
