diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-23 21:21:02 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 02:15:58 -0400 |
| commit | 050bbb196392b9c178f82b1205a23dd2f915ee93 (patch) | |
| tree | 7558fc040ea5cfedefd56f0e5412b15ee23d8228 | |
| parent | 9e326acf567b605cf4177081cc7367c24ec10a66 (diff) | |
[NET] sunhme: Convert to new SBUS driver framework.
And make it a real PCI driver too.
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/sunhme.c | 360 | ||||
| -rw-r--r-- | drivers/net/sunhme.h | 1 |
2 files changed, 187 insertions, 174 deletions
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 9f4367e2aa0d..ec51f397e1ed 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | /* $Id: sunhme.c,v 1.124 2002/01/15 06:25:51 davem Exp $ | 1 | /* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, |
| 2 | * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, | ||
| 3 | * auto carrier detecting ethernet driver. Also known as the | 2 | * auto carrier detecting ethernet driver. Also known as the |
| 4 | * "Happy Meal Ethernet" found on SunSwift SBUS cards. | 3 | * "Happy Meal Ethernet" found on SunSwift SBUS cards. |
| 5 | * | 4 | * |
| 6 | * Copyright (C) 1996, 1998, 1999, 2002, 2003 David S. Miller (davem@redhat.com) | 5 | * Copyright (C) 1996, 1998, 1999, 2002, 2003, |
| 6 | 2006 David S. Miller (davem@davemloft.net) | ||
| 7 | * | 7 | * |
| 8 | * Changes : | 8 | * Changes : |
| 9 | * 2000/11/11 Willy Tarreau <willy AT meta-x.org> | 9 | * 2000/11/11 Willy Tarreau <willy AT meta-x.org> |
| @@ -47,9 +47,6 @@ | |||
| 47 | #include <asm/oplib.h> | 47 | #include <asm/oplib.h> |
| 48 | #include <asm/prom.h> | 48 | #include <asm/prom.h> |
| 49 | #include <asm/auxio.h> | 49 | #include <asm/auxio.h> |
| 50 | #ifndef CONFIG_SPARC64 | ||
| 51 | #include <asm/io-unit.h> | ||
| 52 | #endif | ||
| 53 | #endif | 50 | #endif |
| 54 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
| 55 | 52 | ||
| @@ -66,9 +63,9 @@ | |||
| 66 | #include "sunhme.h" | 63 | #include "sunhme.h" |
| 67 | 64 | ||
| 68 | #define DRV_NAME "sunhme" | 65 | #define DRV_NAME "sunhme" |
| 69 | #define DRV_VERSION "2.02" | 66 | #define DRV_VERSION "3.00" |
| 70 | #define DRV_RELDATE "8/24/03" | 67 | #define DRV_RELDATE "June 23, 2006" |
| 71 | #define DRV_AUTHOR "David S. Miller (davem@redhat.com)" | 68 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" |
| 72 | 69 | ||
| 73 | static char version[] = | 70 | static char version[] = |
| 74 | DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; | 71 | DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; |
| @@ -84,8 +81,6 @@ static int macaddr[6]; | |||
| 84 | module_param_array(macaddr, int, NULL, 0); | 81 | module_param_array(macaddr, int, NULL, 0); |
| 85 | MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set"); | 82 | MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set"); |
| 86 | 83 | ||
| 87 | static struct happy_meal *root_happy_dev; | ||
| 88 | |||
| 89 | #ifdef CONFIG_SBUS | 84 | #ifdef CONFIG_SBUS |
| 90 | static struct quattro *qfe_sbus_list; | 85 | static struct quattro *qfe_sbus_list; |
| 91 | #endif | 86 | #endif |
| @@ -182,26 +177,6 @@ static __inline__ void tx_dump_ring(struct happy_meal *hp) | |||
| 182 | #define DEFAULT_IPG2 4 /* For all modes */ | 177 | #define DEFAULT_IPG2 4 /* For all modes */ |
| 183 | #define DEFAULT_JAMSIZE 4 /* Toe jam */ | 178 | #define DEFAULT_JAMSIZE 4 /* Toe jam */ |
| 184 | 179 | ||
| 185 | #if defined(CONFIG_PCI) && defined(MODULE) | ||
| 186 | /* This happy_pci_ids is declared __initdata because it is only used | ||
| 187 | as an advisory to depmod. If this is ported to the new PCI interface | ||
| 188 | where it could be referenced at any time due to hot plugging, | ||
| 189 | the __initdata reference should be removed. */ | ||
| 190 | |||
| 191 | static struct pci_device_id happymeal_pci_ids[] = { | ||
| 192 | { | ||
| 193 | .vendor = PCI_VENDOR_ID_SUN, | ||
| 194 | .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, | ||
| 195 | .subvendor = PCI_ANY_ID, | ||
| 196 | .subdevice = PCI_ANY_ID, | ||
| 197 | }, | ||
| 198 | { } /* Terminating entry */ | ||
| 199 | }; | ||
| 200 | |||
| 201 | MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); | ||
| 202 | |||
| 203 | #endif | ||
| 204 | |||
| 205 | /* NOTE: In the descriptor writes one _must_ write the address | 180 | /* NOTE: In the descriptor writes one _must_ write the address |
| 206 | * member _first_. The card must not be allowed to see | 181 | * member _first_. The card must not be allowed to see |
| 207 | * the updated descriptor flags until the address is | 182 | * the updated descriptor flags until the address is |
| @@ -2656,6 +2631,17 @@ static void __init quattro_sbus_register_irqs(void) | |||
| 2656 | } | 2631 | } |
| 2657 | } | 2632 | } |
| 2658 | } | 2633 | } |
| 2634 | |||
| 2635 | static void __devexit quattro_sbus_free_irqs(void) | ||
| 2636 | { | ||
| 2637 | struct quattro *qp; | ||
| 2638 | |||
| 2639 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | ||
| 2640 | struct sbus_dev *sdev = qp->quattro_dev; | ||
| 2641 | |||
| 2642 | free_irq(sdev->irqs[0], qp); | ||
| 2643 | } | ||
| 2644 | } | ||
| 2659 | #endif /* CONFIG_SBUS */ | 2645 | #endif /* CONFIG_SBUS */ |
| 2660 | 2646 | ||
| 2661 | #ifdef CONFIG_PCI | 2647 | #ifdef CONFIG_PCI |
| @@ -2690,8 +2676,9 @@ static struct quattro * __init quattro_pci_find(struct pci_dev *pdev) | |||
| 2690 | #endif /* CONFIG_PCI */ | 2676 | #endif /* CONFIG_PCI */ |
| 2691 | 2677 | ||
| 2692 | #ifdef CONFIG_SBUS | 2678 | #ifdef CONFIG_SBUS |
| 2693 | static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | 2679 | static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) |
| 2694 | { | 2680 | { |
| 2681 | struct device_node *dp = sdev->ofdev.node; | ||
| 2695 | struct quattro *qp = NULL; | 2682 | struct quattro *qp = NULL; |
| 2696 | struct happy_meal *hp; | 2683 | struct happy_meal *hp; |
| 2697 | struct net_device *dev; | 2684 | struct net_device *dev; |
| @@ -2714,6 +2701,7 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2714 | if (!dev) | 2701 | if (!dev) |
| 2715 | goto err_out; | 2702 | goto err_out; |
| 2716 | SET_MODULE_OWNER(dev); | 2703 | SET_MODULE_OWNER(dev); |
| 2704 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | ||
| 2717 | 2705 | ||
| 2718 | if (hme_version_printed++ == 0) | 2706 | if (hme_version_printed++ == 0) |
| 2719 | printk(KERN_INFO "%s", version); | 2707 | printk(KERN_INFO "%s", version); |
| @@ -2729,13 +2717,16 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2729 | for (i = 0; i < 6; i++) | 2717 | for (i = 0; i < 6; i++) |
| 2730 | dev->dev_addr[i] = macaddr[i]; | 2718 | dev->dev_addr[i] = macaddr[i]; |
| 2731 | macaddr[5]++; | 2719 | macaddr[5]++; |
| 2732 | } else if (qfe_slot != -1 && | ||
| 2733 | prom_getproplen(sdev->prom_node, | ||
| 2734 | "local-mac-address") == 6) { | ||
| 2735 | prom_getproperty(sdev->prom_node, "local-mac-address", | ||
| 2736 | dev->dev_addr, 6); | ||
| 2737 | } else { | 2720 | } else { |
| 2738 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); | 2721 | unsigned char *addr; |
| 2722 | int len; | ||
| 2723 | |||
| 2724 | addr = of_get_property(dp, "local-mac-address", &len); | ||
| 2725 | |||
| 2726 | if (qfe_slot != -1 && addr && len == 6) | ||
| 2727 | memcpy(dev->dev_addr, addr, 6); | ||
| 2728 | else | ||
| 2729 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); | ||
| 2739 | } | 2730 | } |
| 2740 | 2731 | ||
| 2741 | hp = dev->priv; | 2732 | hp = dev->priv; |
| @@ -2746,9 +2737,8 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2746 | 2737 | ||
| 2747 | err = -ENODEV; | 2738 | err = -ENODEV; |
| 2748 | if (sdev->num_registers != 5) { | 2739 | if (sdev->num_registers != 5) { |
| 2749 | printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n", | 2740 | printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n", |
| 2750 | sdev->num_registers); | 2741 | sdev->num_registers); |
| 2751 | printk(KERN_ERR "happymeal: Would you like that for here or to go?\n"); | ||
| 2752 | goto err_out_free_netdev; | 2742 | goto err_out_free_netdev; |
| 2753 | } | 2743 | } |
| 2754 | 2744 | ||
| @@ -2762,39 +2752,39 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2762 | hp->gregs = sbus_ioremap(&sdev->resource[0], 0, | 2752 | hp->gregs = sbus_ioremap(&sdev->resource[0], 0, |
| 2763 | GREG_REG_SIZE, "HME Global Regs"); | 2753 | GREG_REG_SIZE, "HME Global Regs"); |
| 2764 | if (!hp->gregs) { | 2754 | if (!hp->gregs) { |
| 2765 | printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n"); | 2755 | printk(KERN_ERR "happymeal: Cannot map global registers.\n"); |
| 2766 | goto err_out_free_netdev; | 2756 | goto err_out_free_netdev; |
| 2767 | } | 2757 | } |
| 2768 | 2758 | ||
| 2769 | hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, | 2759 | hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, |
| 2770 | ETX_REG_SIZE, "HME TX Regs"); | 2760 | ETX_REG_SIZE, "HME TX Regs"); |
| 2771 | if (!hp->etxregs) { | 2761 | if (!hp->etxregs) { |
| 2772 | printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Transmit registers.\n"); | 2762 | printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); |
| 2773 | goto err_out_iounmap; | 2763 | goto err_out_iounmap; |
| 2774 | } | 2764 | } |
| 2775 | 2765 | ||
| 2776 | hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, | 2766 | hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, |
| 2777 | ERX_REG_SIZE, "HME RX Regs"); | 2767 | ERX_REG_SIZE, "HME RX Regs"); |
| 2778 | if (!hp->erxregs) { | 2768 | if (!hp->erxregs) { |
| 2779 | printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Receive registers.\n"); | 2769 | printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); |
| 2780 | goto err_out_iounmap; | 2770 | goto err_out_iounmap; |
| 2781 | } | 2771 | } |
| 2782 | 2772 | ||
| 2783 | hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, | 2773 | hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, |
| 2784 | BMAC_REG_SIZE, "HME BIGMAC Regs"); | 2774 | BMAC_REG_SIZE, "HME BIGMAC Regs"); |
| 2785 | if (!hp->bigmacregs) { | 2775 | if (!hp->bigmacregs) { |
| 2786 | printk(KERN_ERR "happymeal: Cannot map Happy Meal BIGMAC registers.\n"); | 2776 | printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); |
| 2787 | goto err_out_iounmap; | 2777 | goto err_out_iounmap; |
| 2788 | } | 2778 | } |
| 2789 | 2779 | ||
| 2790 | hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, | 2780 | hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, |
| 2791 | TCVR_REG_SIZE, "HME Tranceiver Regs"); | 2781 | TCVR_REG_SIZE, "HME Tranceiver Regs"); |
| 2792 | if (!hp->tcvregs) { | 2782 | if (!hp->tcvregs) { |
| 2793 | printk(KERN_ERR "happymeal: Cannot map Happy Meal Tranceiver registers.\n"); | 2783 | printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); |
| 2794 | goto err_out_iounmap; | 2784 | goto err_out_iounmap; |
| 2795 | } | 2785 | } |
| 2796 | 2786 | ||
| 2797 | hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff); | 2787 | hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff); |
| 2798 | if (hp->hm_revision == 0xff) | 2788 | if (hp->hm_revision == 0xff) |
| 2799 | hp->hm_revision = 0xa0; | 2789 | hp->hm_revision = 0xa0; |
| 2800 | 2790 | ||
| @@ -2808,8 +2798,8 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2808 | hp->happy_flags |= HFLAG_QUATTRO; | 2798 | hp->happy_flags |= HFLAG_QUATTRO; |
| 2809 | 2799 | ||
| 2810 | /* Get the supported DVMA burst sizes from our Happy SBUS. */ | 2800 | /* Get the supported DVMA burst sizes from our Happy SBUS. */ |
| 2811 | hp->happy_bursts = prom_getintdefault(sdev->bus->prom_node, | 2801 | hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node, |
| 2812 | "burst-sizes", 0x00); | 2802 | "burst-sizes", 0x00); |
| 2813 | 2803 | ||
| 2814 | hp->happy_block = sbus_alloc_consistent(hp->happy_dev, | 2804 | hp->happy_block = sbus_alloc_consistent(hp->happy_dev, |
| 2815 | PAGE_SIZE, | 2805 | PAGE_SIZE, |
| @@ -2872,6 +2862,8 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2872 | goto err_out_free_consistent; | 2862 | goto err_out_free_consistent; |
| 2873 | } | 2863 | } |
| 2874 | 2864 | ||
| 2865 | dev_set_drvdata(&sdev->ofdev.dev, hp); | ||
| 2866 | |||
| 2875 | if (qfe_slot != -1) | 2867 | if (qfe_slot != -1) |
| 2876 | printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", | 2868 | printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", |
| 2877 | dev->name, qfe_slot); | 2869 | dev->name, qfe_slot); |
| @@ -2884,12 +2876,6 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) | |||
| 2884 | dev->dev_addr[i], i == 5 ? ' ' : ':'); | 2876 | dev->dev_addr[i], i == 5 ? ' ' : ':'); |
| 2885 | printk("\n"); | 2877 | printk("\n"); |
| 2886 | 2878 | ||
| 2887 | /* We are home free at this point, link us in to the happy | ||
| 2888 | * device list. | ||
| 2889 | */ | ||
| 2890 | hp->next_module = root_happy_dev; | ||
| 2891 | root_happy_dev = hp; | ||
| 2892 | |||
| 2893 | return 0; | 2879 | return 0; |
| 2894 | 2880 | ||
| 2895 | err_out_free_consistent: | 2881 | err_out_free_consistent: |
| @@ -3009,7 +2995,8 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr) | |||
| 3009 | } | 2995 | } |
| 3010 | #endif /* !(CONFIG_SPARC) */ | 2996 | #endif /* !(CONFIG_SPARC) */ |
| 3011 | 2997 | ||
| 3012 | static int __init happy_meal_pci_init(struct pci_dev *pdev) | 2998 | static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, |
| 2999 | const struct pci_device_id *ent) | ||
| 3013 | { | 3000 | { |
| 3014 | struct quattro *qp = NULL; | 3001 | struct quattro *qp = NULL; |
| 3015 | #ifdef CONFIG_SPARC | 3002 | #ifdef CONFIG_SPARC |
| @@ -3214,6 +3201,8 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) | |||
| 3214 | goto err_out_iounmap; | 3201 | goto err_out_iounmap; |
| 3215 | } | 3202 | } |
| 3216 | 3203 | ||
| 3204 | dev_set_drvdata(&pdev->dev, hp); | ||
| 3205 | |||
| 3217 | if (!qfe_slot) { | 3206 | if (!qfe_slot) { |
| 3218 | struct pci_dev *qpdev = qp->quattro_dev; | 3207 | struct pci_dev *qpdev = qp->quattro_dev; |
| 3219 | 3208 | ||
| @@ -3243,12 +3232,6 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) | |||
| 3243 | 3232 | ||
| 3244 | printk("\n"); | 3233 | printk("\n"); |
| 3245 | 3234 | ||
| 3246 | /* We are home free at this point, link us in to the happy | ||
| 3247 | * device list. | ||
| 3248 | */ | ||
| 3249 | hp->next_module = root_happy_dev; | ||
| 3250 | root_happy_dev = hp; | ||
| 3251 | |||
| 3252 | return 0; | 3235 | return 0; |
| 3253 | 3236 | ||
| 3254 | err_out_iounmap: | 3237 | err_out_iounmap: |
| @@ -3266,136 +3249,146 @@ err_out_clear_quattro: | |||
| 3266 | err_out: | 3249 | err_out: |
| 3267 | return err; | 3250 | return err; |
| 3268 | } | 3251 | } |
| 3269 | #endif | ||
| 3270 | 3252 | ||
| 3271 | #ifdef CONFIG_SBUS | 3253 | static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) |
| 3272 | static int __init happy_meal_sbus_probe(void) | ||
| 3273 | { | 3254 | { |
| 3274 | struct sbus_bus *sbus; | 3255 | struct happy_meal *hp = dev_get_drvdata(&pdev->dev); |
| 3275 | struct sbus_dev *sdev; | 3256 | struct net_device *net_dev = hp->dev; |
| 3276 | int cards = 0; | ||
| 3277 | char model[128]; | ||
| 3278 | 3257 | ||
| 3279 | for_each_sbus(sbus) { | 3258 | unregister_netdev(net_dev); |
| 3280 | for_each_sbusdev(sdev, sbus) { | 3259 | |
| 3281 | char *name = sdev->prom_name; | 3260 | pci_free_consistent(hp->happy_dev, |
| 3282 | 3261 | PAGE_SIZE, | |
| 3283 | if (!strcmp(name, "SUNW,hme")) { | 3262 | hp->happy_block, |
| 3284 | cards++; | 3263 | hp->hblock_dvma); |
| 3285 | prom_getstring(sdev->prom_node, "model", | 3264 | iounmap(hp->gregs); |
| 3286 | model, sizeof(model)); | 3265 | pci_release_regions(hp->happy_dev); |
| 3287 | if (!strcmp(model, "SUNW,sbus-qfe")) | 3266 | |
| 3288 | happy_meal_sbus_init(sdev, 1); | 3267 | free_netdev(net_dev); |
| 3289 | else | 3268 | |
| 3290 | happy_meal_sbus_init(sdev, 0); | 3269 | dev_set_drvdata(&pdev->dev, NULL); |
| 3291 | } else if (!strcmp(name, "qfe") || | ||
| 3292 | !strcmp(name, "SUNW,qfe")) { | ||
| 3293 | cards++; | ||
| 3294 | happy_meal_sbus_init(sdev, 1); | ||
| 3295 | } | ||
| 3296 | } | ||
| 3297 | } | ||
| 3298 | if (cards != 0) | ||
| 3299 | quattro_sbus_register_irqs(); | ||
| 3300 | return cards; | ||
| 3301 | } | 3270 | } |
| 3302 | #endif | ||
| 3303 | 3271 | ||
| 3304 | #ifdef CONFIG_PCI | 3272 | static struct pci_device_id happymeal_pci_ids[] = { |
| 3305 | static int __init happy_meal_pci_probe(void) | 3273 | { |
| 3274 | .vendor = PCI_VENDOR_ID_SUN, | ||
| 3275 | .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, | ||
| 3276 | .subvendor = PCI_ANY_ID, | ||
| 3277 | .subdevice = PCI_ANY_ID, | ||
| 3278 | }, | ||
| 3279 | { } /* Terminating entry */ | ||
| 3280 | }; | ||
| 3281 | |||
| 3282 | MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); | ||
| 3283 | |||
| 3284 | static struct pci_driver hme_pci_driver = { | ||
| 3285 | .name = "hme", | ||
| 3286 | .id_table = happymeal_pci_ids, | ||
| 3287 | .probe = happy_meal_pci_probe, | ||
| 3288 | .remove = __devexit_p(happy_meal_pci_remove), | ||
| 3289 | }; | ||
| 3290 | |||
| 3291 | static int __init happy_meal_pci_init(void) | ||
| 3306 | { | 3292 | { |
| 3307 | struct pci_dev *pdev = NULL; | 3293 | return pci_module_init(&hme_pci_driver); |
| 3308 | int cards = 0; | 3294 | } |
| 3309 | 3295 | ||
| 3310 | while ((pdev = pci_find_device(PCI_VENDOR_ID_SUN, | 3296 | static void happy_meal_pci_exit(void) |
| 3311 | PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev)) != NULL) { | 3297 | { |
| 3312 | if (pci_enable_device(pdev)) | 3298 | pci_unregister_driver(&hme_pci_driver); |
| 3313 | continue; | 3299 | |
| 3314 | pci_set_master(pdev); | 3300 | while (qfe_pci_list) { |
| 3315 | cards++; | 3301 | struct quattro *qfe = qfe_pci_list; |
| 3316 | happy_meal_pci_init(pdev); | 3302 | struct quattro *next = qfe->next; |
| 3303 | |||
| 3304 | kfree(qfe); | ||
| 3305 | |||
| 3306 | qfe_pci_list = next; | ||
| 3317 | } | 3307 | } |
| 3318 | return cards; | ||
| 3319 | } | 3308 | } |
| 3309 | |||
| 3320 | #endif | 3310 | #endif |
| 3321 | 3311 | ||
| 3322 | static int __init happy_meal_probe(void) | 3312 | #ifdef CONFIG_SBUS |
| 3313 | static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
| 3323 | { | 3314 | { |
| 3324 | static int called = 0; | 3315 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
| 3325 | int cards; | 3316 | struct device_node *dp = dev->node; |
| 3317 | char *model = of_get_property(dp, "model", NULL); | ||
| 3318 | int is_qfe = (match->data != NULL); | ||
| 3326 | 3319 | ||
| 3327 | root_happy_dev = NULL; | 3320 | if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) |
| 3321 | is_qfe = 1; | ||
| 3328 | 3322 | ||
| 3329 | if (called) | 3323 | return happy_meal_sbus_probe_one(sdev, is_qfe); |
| 3330 | return -ENODEV; | 3324 | } |
| 3331 | called++; | 3325 | |
| 3326 | static int __devexit hme_sbus_remove(struct of_device *dev) | ||
| 3327 | { | ||
| 3328 | struct happy_meal *hp = dev_get_drvdata(&dev->dev); | ||
| 3329 | struct net_device *net_dev = hp->dev; | ||
| 3330 | |||
| 3331 | unregister_netdevice(net_dev); | ||
| 3332 | |||
| 3333 | /* XXX qfe parent interrupt... */ | ||
| 3334 | |||
| 3335 | sbus_iounmap(hp->gregs, GREG_REG_SIZE); | ||
| 3336 | sbus_iounmap(hp->etxregs, ETX_REG_SIZE); | ||
| 3337 | sbus_iounmap(hp->erxregs, ERX_REG_SIZE); | ||
| 3338 | sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); | ||
| 3339 | sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); | ||
| 3340 | sbus_free_consistent(hp->happy_dev, | ||
| 3341 | PAGE_SIZE, | ||
| 3342 | hp->happy_block, | ||
| 3343 | hp->hblock_dvma); | ||
| 3344 | |||
| 3345 | free_netdev(net_dev); | ||
| 3346 | |||
| 3347 | dev_set_drvdata(&dev->dev, NULL); | ||
| 3332 | 3348 | ||
| 3333 | cards = 0; | ||
| 3334 | #ifdef CONFIG_SBUS | ||
| 3335 | cards += happy_meal_sbus_probe(); | ||
| 3336 | #endif | ||
| 3337 | #ifdef CONFIG_PCI | ||
| 3338 | cards += happy_meal_pci_probe(); | ||
| 3339 | #endif | ||
| 3340 | if (!cards) | ||
| 3341 | return -ENODEV; | ||
| 3342 | return 0; | 3349 | return 0; |
| 3343 | } | 3350 | } |
| 3344 | 3351 | ||
| 3352 | static struct of_device_id hme_sbus_match[] = { | ||
| 3353 | { | ||
| 3354 | .name = "SUNW,hme", | ||
| 3355 | }, | ||
| 3356 | { | ||
| 3357 | .name = "SUNW,qfe", | ||
| 3358 | .data = (void *) 1, | ||
| 3359 | }, | ||
| 3360 | { | ||
| 3361 | .name = "qfe", | ||
| 3362 | .data = (void *) 1, | ||
| 3363 | }, | ||
| 3364 | {}, | ||
| 3365 | }; | ||
| 3345 | 3366 | ||
| 3346 | static void __exit happy_meal_cleanup_module(void) | 3367 | MODULE_DEVICE_TABLE(of, hme_sbus_match); |
| 3347 | { | ||
| 3348 | #ifdef CONFIG_SBUS | ||
| 3349 | struct quattro *last_seen_qfe = NULL; | ||
| 3350 | #endif | ||
| 3351 | 3368 | ||
| 3352 | while (root_happy_dev) { | 3369 | static struct of_platform_driver hme_sbus_driver = { |
| 3353 | struct happy_meal *hp = root_happy_dev; | 3370 | .name = "hme", |
| 3354 | struct happy_meal *next = root_happy_dev->next_module; | 3371 | .match_table = hme_sbus_match, |
| 3355 | struct net_device *dev = hp->dev; | 3372 | .probe = hme_sbus_probe, |
| 3373 | .remove = __devexit_p(hme_sbus_remove), | ||
| 3374 | }; | ||
| 3356 | 3375 | ||
| 3357 | /* Unregister netdev before unmapping registers as this | 3376 | static int __init happy_meal_sbus_init(void) |
| 3358 | * call can end up trying to access those registers. | 3377 | { |
| 3359 | */ | 3378 | int err; |
| 3360 | unregister_netdev(dev); | ||
| 3361 | 3379 | ||
| 3362 | #ifdef CONFIG_SBUS | 3380 | err = of_register_driver(&hme_sbus_driver, &sbus_bus_type); |
| 3363 | if (!(hp->happy_flags & HFLAG_PCI)) { | 3381 | if (!err) |
| 3364 | if (hp->happy_flags & HFLAG_QUATTRO) { | 3382 | quattro_sbus_register_irqs(); |
| 3365 | if (hp->qfe_parent != last_seen_qfe) { | ||
| 3366 | free_irq(dev->irq, hp->qfe_parent); | ||
| 3367 | last_seen_qfe = hp->qfe_parent; | ||
| 3368 | } | ||
| 3369 | } | ||
| 3370 | 3383 | ||
| 3371 | sbus_iounmap(hp->gregs, GREG_REG_SIZE); | 3384 | return err; |
| 3372 | sbus_iounmap(hp->etxregs, ETX_REG_SIZE); | 3385 | } |
| 3373 | sbus_iounmap(hp->erxregs, ERX_REG_SIZE); | ||
| 3374 | sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); | ||
| 3375 | sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); | ||
| 3376 | sbus_free_consistent(hp->happy_dev, | ||
| 3377 | PAGE_SIZE, | ||
| 3378 | hp->happy_block, | ||
| 3379 | hp->hblock_dvma); | ||
| 3380 | } | ||
| 3381 | #endif | ||
| 3382 | #ifdef CONFIG_PCI | ||
| 3383 | if ((hp->happy_flags & HFLAG_PCI)) { | ||
| 3384 | pci_free_consistent(hp->happy_dev, | ||
| 3385 | PAGE_SIZE, | ||
| 3386 | hp->happy_block, | ||
| 3387 | hp->hblock_dvma); | ||
| 3388 | iounmap(hp->gregs); | ||
| 3389 | pci_release_regions(hp->happy_dev); | ||
| 3390 | } | ||
| 3391 | #endif | ||
| 3392 | free_netdev(dev); | ||
| 3393 | 3386 | ||
| 3394 | root_happy_dev = next; | 3387 | static void happy_meal_sbus_exit(void) |
| 3395 | } | 3388 | { |
| 3389 | of_unregister_driver(&hme_sbus_driver); | ||
| 3390 | quattro_sbus_free_irqs(); | ||
| 3396 | 3391 | ||
| 3397 | /* Now cleanup the quattro lists. */ | ||
| 3398 | #ifdef CONFIG_SBUS | ||
| 3399 | while (qfe_sbus_list) { | 3392 | while (qfe_sbus_list) { |
| 3400 | struct quattro *qfe = qfe_sbus_list; | 3393 | struct quattro *qfe = qfe_sbus_list; |
| 3401 | struct quattro *next = qfe->next; | 3394 | struct quattro *next = qfe->next; |
| @@ -3404,18 +3397,39 @@ static void __exit happy_meal_cleanup_module(void) | |||
| 3404 | 3397 | ||
| 3405 | qfe_sbus_list = next; | 3398 | qfe_sbus_list = next; |
| 3406 | } | 3399 | } |
| 3400 | } | ||
| 3407 | #endif | 3401 | #endif |
| 3408 | #ifdef CONFIG_PCI | ||
| 3409 | while (qfe_pci_list) { | ||
| 3410 | struct quattro *qfe = qfe_pci_list; | ||
| 3411 | struct quattro *next = qfe->next; | ||
| 3412 | 3402 | ||
| 3413 | kfree(qfe); | 3403 | static int __init happy_meal_probe(void) |
| 3404 | { | ||
| 3405 | int err = 0; | ||
| 3414 | 3406 | ||
| 3415 | qfe_pci_list = next; | 3407 | #ifdef CONFIG_SBUS |
| 3408 | err = happy_meal_sbus_init(); | ||
| 3409 | #endif | ||
| 3410 | #ifdef CONFIG_PCI | ||
| 3411 | if (!err) { | ||
| 3412 | err = happy_meal_pci_init(); | ||
| 3413 | #ifdef CONFIG_SBUS | ||
| 3414 | if (err) | ||
| 3415 | happy_meal_sbus_exit(); | ||
| 3416 | #endif | ||
| 3416 | } | 3417 | } |
| 3417 | #endif | 3418 | #endif |
| 3419 | |||
| 3420 | return err; | ||
| 3421 | } | ||
| 3422 | |||
| 3423 | |||
| 3424 | static void __exit happy_meal_exit(void) | ||
| 3425 | { | ||
| 3426 | #ifdef CONFIG_SBUS | ||
| 3427 | happy_meal_sbus_exit(); | ||
| 3428 | #endif | ||
| 3429 | #ifdef CONFIG_PCI | ||
| 3430 | happy_meal_pci_exit(); | ||
| 3431 | #endif | ||
| 3418 | } | 3432 | } |
| 3419 | 3433 | ||
| 3420 | module_init(happy_meal_probe); | 3434 | module_init(happy_meal_probe); |
| 3421 | module_exit(happy_meal_cleanup_module); | 3435 | module_exit(happy_meal_exit); |
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index 34e9f953cea4..9b7ccaeeee89 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h | |||
| @@ -461,7 +461,6 @@ struct happy_meal { | |||
| 461 | struct net_device *dev; /* Backpointer */ | 461 | struct net_device *dev; /* Backpointer */ |
| 462 | struct quattro *qfe_parent; /* For Quattro cards */ | 462 | struct quattro *qfe_parent; /* For Quattro cards */ |
| 463 | int qfe_ent; /* Which instance on quattro */ | 463 | int qfe_ent; /* Which instance on quattro */ |
| 464 | struct happy_meal *next_module; | ||
| 465 | }; | 464 | }; |
| 466 | 465 | ||
| 467 | /* Here are the happy flags. */ | 466 | /* Here are the happy flags. */ |
