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. diff -ruN linux-mm-original/drivers/net/pcmcia/3c574_cs.c linux-mm/drivers/net/pcmcia/3c574_cs.c --- linux-mm-original/drivers/net/pcmcia/3c574_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/3c574_cs.c 2004-10-28 22:53:07.719338040 +0200 @@ -519,6 +519,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/3c589_cs.c linux-mm/drivers/net/pcmcia/3c589_cs.c --- linux-mm-original/drivers/net/pcmcia/3c589_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/3c589_cs.c 2004-10-28 22:53:07.720337888 +0200 @@ -391,6 +391,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/axnet_cs.c linux-mm/drivers/net/pcmcia/axnet_cs.c --- linux-mm-original/drivers/net/pcmcia/axnet_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/axnet_cs.c 2004-10-28 22:53:07.722337584 +0200 @@ -458,6 +458,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/com20020_cs.c linux-mm/drivers/net/pcmcia/com20020_cs.c --- linux-mm-original/drivers/net/pcmcia/com20020_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/com20020_cs.c 2004-10-28 22:53:07.722337584 +0200 @@ -394,6 +394,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/fmvj18x_cs.c linux-mm/drivers/net/pcmcia/fmvj18x_cs.c --- linux-mm-original/drivers/net/pcmcia/fmvj18x_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/fmvj18x_cs.c 2004-10-28 22:53:07.723337432 +0200 @@ -591,6 +591,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/ibmtr_cs.c linux-mm/drivers/net/pcmcia/ibmtr_cs.c --- linux-mm-original/drivers/net/pcmcia/ibmtr_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/ibmtr_cs.c 2004-10-28 22:53:07.725337128 +0200 @@ -367,6 +367,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/nmclan_cs.c linux-mm/drivers/net/pcmcia/nmclan_cs.c --- linux-mm-original/drivers/net/pcmcia/nmclan_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/nmclan_cs.c 2004-10-28 22:53:07.726336976 +0200 @@ -775,6 +775,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/pcnet_cs.c linux-mm/drivers/net/pcmcia/pcnet_cs.c --- linux-mm-original/drivers/net/pcmcia/pcnet_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/pcnet_cs.c 2004-10-28 22:53:07.728336672 +0200 @@ -722,6 +722,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/smc91c92_cs.c linux-mm/drivers/net/pcmcia/smc91c92_cs.c --- linux-mm-original/drivers/net/pcmcia/smc91c92_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/smc91c92_cs.c 2004-10-28 22:53:07.729336520 +0200 @@ -1024,6 +1024,7 @@ 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 -ruN linux-mm-original/drivers/net/pcmcia/xirc2ps_cs.c linux-mm/drivers/net/pcmcia/xirc2ps_cs.c --- linux-mm-original/drivers/net/pcmcia/xirc2ps_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/pcmcia/xirc2ps_cs.c 2004-10-28 22:53:07.731336216 +0200 @@ -1121,6 +1121,7 @@ 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 -ruN linux-mm-original/drivers/net/wireless/airo.c linux-mm/drivers/net/wireless/airo.c --- linux-mm-original/drivers/net/wireless/airo.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/wireless/airo.c 2004-10-28 22:53:10.482917912 +0200 @@ -2697,7 +2697,8 @@ } 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; @@ -2759,10 +2760,8 @@ 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); @@ -2844,9 +2843,10 @@ 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); @@ -5455,9 +5455,9 @@ 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; @@ -5559,7 +5559,7 @@ 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 -ruN linux-mm-original/drivers/net/wireless/airo_cs.c linux-mm/drivers/net/wireless/airo_cs.c --- linux-mm-original/drivers/net/wireless/airo_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/wireless/airo_cs.c 2004-10-28 22:53:10.483917760 +0200 @@ -89,7 +89,7 @@ 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 @@ 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 -ruN linux-mm-original/drivers/net/wireless/atmel_cs.c linux-mm/drivers/net/wireless/atmel_cs.c --- linux-mm-original/drivers/net/wireless/atmel_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/wireless/atmel_cs.c 2004-10-28 22:53:10.484917608 +0200 @@ -347,21 +347,6 @@ { 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 @@ 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 -ruN linux-mm-original/drivers/net/wireless/netwave_cs.c linux-mm/drivers/net/wireless/netwave_cs.c --- linux-mm-original/drivers/net/wireless/netwave_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/wireless/netwave_cs.c 2004-10-28 22:53:10.485917456 +0200 @@ -1073,6 +1073,8 @@ 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 -ruN linux-mm-original/drivers/net/wireless/orinoco_cs.c linux-mm/drivers/net/wireless/orinoco_cs.c --- linux-mm-original/drivers/net/wireless/orinoco_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/wireless/orinoco_cs.c 2004-10-28 22:53:10.487917152 +0200 @@ -458,6 +458,7 @@ /* 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 -ruN linux-mm-original/drivers/net/wireless/ray_cs.c linux-mm/drivers/net/wireless/ray_cs.c --- linux-mm-original/drivers/net/wireless/ray_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/wireless/ray_cs.c 2004-10-28 22:53:10.489916848 +0200 @@ -564,6 +564,7 @@ return; } + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); i = register_netdev(dev); if (i != 0) { printk("ray_config register_netdev() failed\n"); diff -ruN linux-mm-original/drivers/net/wireless/wavelan_cs.c linux-mm/drivers/net/wireless/wavelan_cs.c --- linux-mm-original/drivers/net/wireless/wavelan_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/wireless/wavelan_cs.c 2004-10-28 22:53:10.503914720 +0200 @@ -4068,6 +4068,7 @@ 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 -ruN linux-mm-original/drivers/net/wireless/wl3501_cs.c linux-mm/drivers/net/wireless/wl3501_cs.c --- linux-mm-original/drivers/net/wireless/wl3501_cs.c 2004-10-28 22:44:02.000000000 +0200 +++ linux-mm/drivers/net/wireless/wl3501_cs.c 2004-10-28 22:53:10.505914416 +0200 @@ -2105,6 +2105,7 @@ 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 -ruN linux-mm-original/drivers/pcmcia/ds.c linux-mm/drivers/pcmcia/ds.c --- linux-mm-original/drivers/pcmcia/ds.c 2004-10-28 22:44:04.467924808 +0200 +++ linux-mm/drivers/pcmcia/ds.c 2004-10-28 22:53:13.050527576 +0200 @@ -565,9 +565,14 @@ (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 @@ 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 @@ /* 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 -ruN linux-mm-original/include/pcmcia/ds.h linux-mm/include/pcmcia/ds.h --- linux-mm-original/include/pcmcia/ds.h 2004-10-28 22:44:08.259348424 +0200 +++ linux-mm/include/pcmcia/ds.h 2004-10-28 22:53:07.732336064 +0200 @@ -173,6 +173,7 @@ #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);