X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fsunhme.c;h=9f046cae2f71627baefd9fc7644952854d148c9d;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=3bbf0c80b079b6345d14b49e4ca8e39306fc0b0e;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 3bbf0c80b..9f046cae2 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1,9 +1,9 @@ -/* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, +/* $Id: sunhme.c,v 1.124 2002/01/15 06:25:51 davem Exp $ + * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, * auto carrier detecting ethernet driver. Also known as the * "Happy Meal Ethernet" found on SunSwift SBUS cards. * - * Copyright (C) 1996, 1998, 1999, 2002, 2003, - 2006 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996, 1998, 1999, 2002, 2003 David S. Miller (davem@redhat.com) * * Changes : * 2000/11/11 Willy Tarreau @@ -13,6 +13,7 @@ * argument : macaddr=0x00,0x10,0x20,0x30,0x40,0x50 */ +#include #include #include #include @@ -39,13 +40,15 @@ #include #include -#ifdef CONFIG_SPARC +#ifdef __sparc__ #include #include #include #include -#include #include +#ifndef __sparc_v9__ +#include +#endif #endif #include @@ -54,7 +57,7 @@ #ifdef CONFIG_PCI #include -#ifdef CONFIG_SPARC +#ifdef __sparc__ #include #endif #endif @@ -62,9 +65,9 @@ #include "sunhme.h" #define DRV_NAME "sunhme" -#define DRV_VERSION "3.00" -#define DRV_RELDATE "June 23, 2006" -#define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" +#define DRV_VERSION "2.02" +#define DRV_RELDATE "8/24/03" +#define DRV_AUTHOR "David S. Miller (davem@redhat.com)" static char version[] = DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; @@ -80,6 +83,8 @@ static int macaddr[6]; module_param_array(macaddr, int, NULL, 0); MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set"); +static struct happy_meal *root_happy_dev; + #ifdef CONFIG_SBUS static struct quattro *qfe_sbus_list; #endif @@ -176,6 +181,26 @@ static __inline__ void tx_dump_ring(struct happy_meal *hp) #define DEFAULT_IPG2 4 /* For all modes */ #define DEFAULT_JAMSIZE 4 /* Toe jam */ +#if defined(CONFIG_PCI) && defined(MODULE) +/* This happy_pci_ids is declared __initdata because it is only used + as an advisory to depmod. If this is ported to the new PCI interface + where it could be referenced at any time due to hot plugging, + the __initdata reference should be removed. */ + +static struct pci_device_id happymeal_pci_ids[] = { + { + .vendor = PCI_VENDOR_ID_SUN, + .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); + +#endif + /* NOTE: In the descriptor writes one _must_ write the address * member _first_. The card must not be allowed to see * the updated descriptor flags until the address is @@ -1585,7 +1610,7 @@ static int happy_meal_init(struct happy_meal *hp) HMD(("happy_meal_init: old[%08x] bursts<", hme_read32(hp, gregs + GREG_CFG))); -#ifndef CONFIG_SPARC +#ifndef __sparc__ /* It is always PCI and can handle 64byte bursts. */ hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST64); #else @@ -1622,7 +1647,7 @@ static int happy_meal_init(struct happy_meal *hp) HMD(("XXX>")); hme_write32(hp, gregs + GREG_CFG, 0); } -#endif /* CONFIG_SPARC */ +#endif /* __sparc__ */ /* Turn off interrupts we do not want to hear. */ HMD((", enable global interrupts, ")); @@ -2194,10 +2219,15 @@ static int happy_meal_open(struct net_device *dev) */ if ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO) { if (request_irq(dev->irq, &happy_meal_interrupt, - IRQF_SHARED, dev->name, (void *)dev)) { + SA_SHIRQ, dev->name, (void *)dev)) { HMD(("EAGAIN\n")); +#ifdef __sparc__ + printk(KERN_ERR "happy_meal(SBUS): Can't order irq %s to go.\n", + __irq_itoa(dev->irq)); +#else printk(KERN_ERR "happy_meal(SBUS): Can't order irq %d to go.\n", dev->irq); +#endif return -EAGAIN; } @@ -2522,7 +2552,7 @@ static struct ethtool_ops hme_ethtool_ops = { static int hme_version_printed; #ifdef CONFIG_SBUS -void __devinit quattro_get_ranges(struct quattro *qp) +void __init quattro_get_ranges(struct quattro *qp) { struct sbus_dev *sdev = qp->quattro_dev; int err; @@ -2538,7 +2568,7 @@ void __devinit quattro_get_ranges(struct quattro *qp) qp->nranges = (err / sizeof(struct linux_prom_ranges)); } -static void __devinit quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp) +static void __init quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp) { struct sbus_dev *sdev = hp->happy_dev; int rng; @@ -2565,12 +2595,16 @@ static void __devinit quattro_apply_ranges(struct quattro *qp, struct happy_meal * * Return NULL on failure. */ -static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev) +static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev) { + struct sbus_bus *sbus; struct sbus_dev *sdev; struct quattro *qp; int i; + if (qfe_sbus_list == NULL) + goto found; + for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { for (i = 0, sdev = qp->quattro_dev; (sdev != NULL) && (i < 4); @@ -2579,7 +2613,17 @@ static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev) return qp; } } + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if (sdev == goal_sdev) + goto found; + } + } + /* Cannot find quattro parent, fail. */ + return NULL; + +found: qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); if (qp != NULL) { int i; @@ -2608,7 +2652,7 @@ static void __init quattro_sbus_register_irqs(void) err = request_irq(sdev->irqs[0], quattro_sbus_interrupt, - IRQF_SHARED, "Quattro", + SA_SHIRQ, "Quattro", qp); if (err != 0) { printk(KERN_ERR "Quattro: Fatal IRQ registery error %d.\n", err); @@ -2616,17 +2660,6 @@ static void __init quattro_sbus_register_irqs(void) } } } - -static void quattro_sbus_free_irqs(void) -{ - struct quattro *qp; - - for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { - struct sbus_dev *sdev = qp->quattro_dev; - - free_irq(sdev->irqs[0], qp); - } -} #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI @@ -2661,9 +2694,8 @@ static struct quattro * __init quattro_pci_find(struct pci_dev *pdev) #endif /* CONFIG_PCI */ #ifdef CONFIG_SBUS -static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) +static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) { - struct device_node *dp = sdev->ofdev.node; struct quattro *qp = NULL; struct happy_meal *hp; struct net_device *dev; @@ -2686,7 +2718,6 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe if (!dev) goto err_out; SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &sdev->ofdev.dev); if (hme_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -2702,16 +2733,13 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe for (i = 0; i < 6; i++) dev->dev_addr[i] = macaddr[i]; macaddr[5]++; + } else if (qfe_slot != -1 && + prom_getproplen(sdev->prom_node, + "local-mac-address") == 6) { + prom_getproperty(sdev->prom_node, "local-mac-address", + dev->dev_addr, 6); } else { - unsigned char *addr; - int len; - - addr = of_get_property(dp, "local-mac-address", &len); - - if (qfe_slot != -1 && addr && len == 6) - memcpy(dev->dev_addr, addr, 6); - else - memcpy(dev->dev_addr, idprom->id_ethaddr, 6); + memcpy(dev->dev_addr, idprom->id_ethaddr, 6); } hp = dev->priv; @@ -2722,8 +2750,9 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe err = -ENODEV; if (sdev->num_registers != 5) { - printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n", + printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n", sdev->num_registers); + printk(KERN_ERR "happymeal: Would you like that for here or to go?\n"); goto err_out_free_netdev; } @@ -2737,39 +2766,39 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe hp->gregs = sbus_ioremap(&sdev->resource[0], 0, GREG_REG_SIZE, "HME Global Regs"); if (!hp->gregs) { - printk(KERN_ERR "happymeal: Cannot map global registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n"); goto err_out_free_netdev; } hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, ETX_REG_SIZE, "HME TX Regs"); if (!hp->etxregs) { - printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Transmit registers.\n"); goto err_out_iounmap; } hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, ERX_REG_SIZE, "HME RX Regs"); if (!hp->erxregs) { - printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Receive registers.\n"); goto err_out_iounmap; } hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, BMAC_REG_SIZE, "HME BIGMAC Regs"); if (!hp->bigmacregs) { - printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal BIGMAC registers.\n"); goto err_out_iounmap; } hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, TCVR_REG_SIZE, "HME Tranceiver Regs"); if (!hp->tcvregs) { - printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); + printk(KERN_ERR "happymeal: Cannot map Happy Meal Tranceiver registers.\n"); goto err_out_iounmap; } - hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff); + hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff); if (hp->hm_revision == 0xff) hp->hm_revision = 0xa0; @@ -2783,8 +2812,8 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe hp->happy_flags |= HFLAG_QUATTRO; /* Get the supported DVMA burst sizes from our Happy SBUS. */ - hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node, - "burst-sizes", 0x00); + hp->happy_bursts = prom_getintdefault(sdev->bus->prom_node, + "burst-sizes", 0x00); hp->happy_block = sbus_alloc_consistent(hp->happy_dev, PAGE_SIZE, @@ -2847,8 +2876,6 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe goto err_out_free_consistent; } - dev_set_drvdata(&sdev->ofdev.dev, hp); - if (qfe_slot != -1) printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", dev->name, qfe_slot); @@ -2861,6 +2888,12 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe dev->dev_addr[i], i == 5 ? ' ' : ':'); printk("\n"); + /* We are home free at this point, link us in to the happy + * device list. + */ + hp->next_module = root_happy_dev; + root_happy_dev = hp; + return 0; err_out_free_consistent: @@ -2890,7 +2923,7 @@ err_out: #endif #ifdef CONFIG_PCI -#ifndef CONFIG_SPARC +#ifndef __sparc__ static int is_quattro_p(struct pci_dev *pdev) { struct pci_dev *busdev = pdev->bus->self; @@ -2978,14 +3011,14 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr) get_random_bytes(&dev_addr[3], 3); return; } -#endif /* !(CONFIG_SPARC) */ +#endif /* !(__sparc__) */ -static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __init happy_meal_pci_init(struct pci_dev *pdev) { struct quattro *qp = NULL; -#ifdef CONFIG_SPARC +#ifdef __sparc__ struct pcidev_cookie *pcp; + int node; #endif struct happy_meal *hp; struct net_device *dev; @@ -2996,14 +3029,15 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, int err; /* Now make sure pci_dev cookie is there. */ -#ifdef CONFIG_SPARC +#ifdef __sparc__ pcp = pdev->sysdata; - if (pcp == NULL) { + if (pcp == NULL || pcp->prom_node == -1) { printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n"); return -ENODEV; } + node = pcp->prom_node; - strcpy(prom_name, pcp->prom_node->name); + prom_getstring(node, "name", prom_name, sizeof(prom_name)); #else if (is_quattro_p(pdev)) strcpy(prom_name, "SUNW,qfe"); @@ -3012,11 +3046,6 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, #endif err = -ENODEV; - - if (pci_enable_device(pdev)) - goto err_out; - pci_set_master(pdev); - if (!strcmp(prom_name, "SUNW,qfe") || !strcmp(prom_name, "qfe")) { qp = quattro_pci_find(pdev); if (qp == NULL) @@ -3079,15 +3108,11 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, dev->dev_addr[i] = macaddr[i]; macaddr[5]++; } else { -#ifdef CONFIG_SPARC - unsigned char *addr; - int len; - +#ifdef __sparc__ if (qfe_slot != -1 && - (addr = of_get_property(pcp->prom_node, - "local-mac-address", &len)) != NULL - && len == 6) { - memcpy(dev->dev_addr, addr, 6); + prom_getproplen(node, "local-mac-address") == 6) { + prom_getproperty(node, "local-mac-address", + dev->dev_addr, 6); } else { memcpy(dev->dev_addr, idprom->id_ethaddr, 6); } @@ -3103,8 +3128,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, hp->bigmacregs = (hpreg_base + 0x6000UL); hp->tcvregs = (hpreg_base + 0x7000UL); -#ifdef CONFIG_SPARC - hp->hm_revision = of_getintprop_default(pcp->prom_node, "hm-rev", 0xff); +#ifdef __sparc__ + hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff); if (hp->hm_revision == 0xff) { unsigned char prev; @@ -3128,7 +3153,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, /* And of course, indicate this is PCI. */ hp->happy_flags |= HFLAG_PCI; -#ifdef CONFIG_SPARC +#ifdef __sparc__ /* Assume PCI happy meals can handle all burst sizes. */ hp->happy_bursts = DMA_BURSTBITS; #endif @@ -3191,8 +3216,6 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, goto err_out_iounmap; } - dev_set_drvdata(&pdev->dev, hp); - if (!qfe_slot) { struct pci_dev *qpdev = qp->quattro_dev; @@ -3222,6 +3245,12 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, printk("\n"); + /* We are home free at this point, link us in to the happy + * device list. + */ + hp->next_module = root_happy_dev; + root_happy_dev = hp; + return 0; err_out_iounmap: @@ -3239,141 +3268,136 @@ err_out_clear_quattro: err_out: return err; } +#endif -static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) -{ - struct happy_meal *hp = dev_get_drvdata(&pdev->dev); - struct net_device *net_dev = hp->dev; - - unregister_netdev(net_dev); - - pci_free_consistent(hp->happy_dev, - PAGE_SIZE, - hp->happy_block, - hp->hblock_dvma); - iounmap(hp->gregs); - pci_release_regions(hp->happy_dev); - - free_netdev(net_dev); - - dev_set_drvdata(&pdev->dev, NULL); -} - -static struct pci_device_id happymeal_pci_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); - -static struct pci_driver hme_pci_driver = { - .name = "hme", - .id_table = happymeal_pci_ids, - .probe = happy_meal_pci_probe, - .remove = __devexit_p(happy_meal_pci_remove), -}; - -static int __init happy_meal_pci_init(void) -{ - return pci_register_driver(&hme_pci_driver); -} - -static void happy_meal_pci_exit(void) +#ifdef CONFIG_SBUS +static int __init happy_meal_sbus_probe(void) { - pci_unregister_driver(&hme_pci_driver); - - while (qfe_pci_list) { - struct quattro *qfe = qfe_pci_list; - struct quattro *next = qfe->next; - - kfree(qfe); - - qfe_pci_list = next; + struct sbus_bus *sbus; + struct sbus_dev *sdev; + int cards = 0; + char model[128]; + + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + char *name = sdev->prom_name; + + if (!strcmp(name, "SUNW,hme")) { + cards++; + prom_getstring(sdev->prom_node, "model", + model, sizeof(model)); + if (!strcmp(model, "SUNW,sbus-qfe")) + happy_meal_sbus_init(sdev, 1); + else + happy_meal_sbus_init(sdev, 0); + } else if (!strcmp(name, "qfe") || + !strcmp(name, "SUNW,qfe")) { + cards++; + happy_meal_sbus_init(sdev, 1); + } + } } + if (cards != 0) + quattro_sbus_register_irqs(); + return cards; } - #endif -#ifdef CONFIG_SBUS -static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match) +#ifdef CONFIG_PCI +static int __init happy_meal_pci_probe(void) { - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - struct device_node *dp = dev->node; - char *model = of_get_property(dp, "model", NULL); - int is_qfe = (match->data != NULL); - - if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) - is_qfe = 1; + struct pci_dev *pdev = NULL; + int cards = 0; - return happy_meal_sbus_probe_one(sdev, is_qfe); + while ((pdev = pci_find_device(PCI_VENDOR_ID_SUN, + PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev)) != NULL) { + if (pci_enable_device(pdev)) + continue; + pci_set_master(pdev); + cards++; + happy_meal_pci_init(pdev); + } + return cards; } +#endif -static int __devexit hme_sbus_remove(struct of_device *dev) +static int __init happy_meal_probe(void) { - struct happy_meal *hp = dev_get_drvdata(&dev->dev); - struct net_device *net_dev = hp->dev; - - unregister_netdevice(net_dev); + static int called = 0; + int cards; - /* XXX qfe parent interrupt... */ + root_happy_dev = NULL; - sbus_iounmap(hp->gregs, GREG_REG_SIZE); - sbus_iounmap(hp->etxregs, ETX_REG_SIZE); - sbus_iounmap(hp->erxregs, ERX_REG_SIZE); - sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); - sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); - sbus_free_consistent(hp->happy_dev, - PAGE_SIZE, - hp->happy_block, - hp->hblock_dvma); - - free_netdev(net_dev); - - dev_set_drvdata(&dev->dev, NULL); + if (called) + return -ENODEV; + called++; + cards = 0; +#ifdef CONFIG_SBUS + cards += happy_meal_sbus_probe(); +#endif +#ifdef CONFIG_PCI + cards += happy_meal_pci_probe(); +#endif + if (!cards) + return -ENODEV; return 0; } -static struct of_device_id hme_sbus_match[] = { - { - .name = "SUNW,hme", - }, - { - .name = "SUNW,qfe", - .data = (void *) 1, - }, - { - .name = "qfe", - .data = (void *) 1, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, hme_sbus_match); +static void __exit happy_meal_cleanup_module(void) +{ +#ifdef CONFIG_SBUS + struct quattro *last_seen_qfe = NULL; +#endif -static struct of_platform_driver hme_sbus_driver = { - .name = "hme", - .match_table = hme_sbus_match, - .probe = hme_sbus_probe, - .remove = __devexit_p(hme_sbus_remove), -}; + while (root_happy_dev) { + struct happy_meal *hp = root_happy_dev; + struct happy_meal *next = root_happy_dev->next_module; + struct net_device *dev = hp->dev; -static int __init happy_meal_sbus_init(void) -{ - int err; + /* Unregister netdev before unmapping registers as this + * call can end up trying to access those registers. + */ + unregister_netdev(dev); - err = of_register_driver(&hme_sbus_driver, &sbus_bus_type); - if (!err) - quattro_sbus_register_irqs(); +#ifdef CONFIG_SBUS + if (!(hp->happy_flags & HFLAG_PCI)) { + if (hp->happy_flags & HFLAG_QUATTRO) { + if (hp->qfe_parent != last_seen_qfe) { + free_irq(dev->irq, hp->qfe_parent); + last_seen_qfe = hp->qfe_parent; + } + } - return err; -} + sbus_iounmap(hp->gregs, GREG_REG_SIZE); + sbus_iounmap(hp->etxregs, ETX_REG_SIZE); + sbus_iounmap(hp->erxregs, ERX_REG_SIZE); + sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); + sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); + sbus_free_consistent(hp->happy_dev, + PAGE_SIZE, + hp->happy_block, + hp->hblock_dvma); + } +#endif +#ifdef CONFIG_PCI + if ((hp->happy_flags & HFLAG_PCI)) { + pci_free_consistent(hp->happy_dev, + PAGE_SIZE, + hp->happy_block, + hp->hblock_dvma); + iounmap(hp->gregs); + pci_release_regions(hp->happy_dev); + } +#endif + free_netdev(dev); -static void happy_meal_sbus_exit(void) -{ - of_unregister_driver(&hme_sbus_driver); - quattro_sbus_free_irqs(); + root_happy_dev = next; + } + /* Now cleanup the quattro lists. */ +#ifdef CONFIG_SBUS while (qfe_sbus_list) { struct quattro *qfe = qfe_sbus_list; struct quattro *next = qfe->next; @@ -3382,39 +3406,18 @@ static void happy_meal_sbus_exit(void) qfe_sbus_list = next; } -} -#endif - -static int __init happy_meal_probe(void) -{ - int err = 0; - -#ifdef CONFIG_SBUS - err = happy_meal_sbus_init(); #endif #ifdef CONFIG_PCI - if (!err) { - err = happy_meal_pci_init(); -#ifdef CONFIG_SBUS - if (err) - happy_meal_sbus_exit(); -#endif - } -#endif - - return err; -} + while (qfe_pci_list) { + struct quattro *qfe = qfe_pci_list; + struct quattro *next = qfe->next; + kfree(qfe); -static void __exit happy_meal_exit(void) -{ -#ifdef CONFIG_SBUS - happy_meal_sbus_exit(); -#endif -#ifdef CONFIG_PCI - happy_meal_pci_exit(); + qfe_pci_list = next; + } #endif } module_init(happy_meal_probe); -module_exit(happy_meal_exit); +module_exit(happy_meal_cleanup_module);