diff options
Diffstat (limited to 'drivers/net/sunhme.c')
-rw-r--r-- | drivers/net/sunhme.c | 360 |
1 files changed, 187 insertions, 173 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); |