diff options
Diffstat (limited to 'drivers/net/myri_sbus.c')
-rw-r--r-- | drivers/net/myri_sbus.c | 147 |
1 files changed, 76 insertions, 71 deletions
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 6c86dca62e2a..a925bc9db4ac 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c | |||
@@ -1,13 +1,12 @@ | |||
1 | /* myri_sbus.h: MyriCOM MyriNET SBUS card driver. | 1 | /* myri_sbus.c: MyriCOM MyriNET SBUS card driver. |
2 | * | 2 | * |
3 | * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 1996, 1999, 2006 David S. Miller (davem@davemloft.net) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | static char version[] = | 6 | static char version[] = |
7 | "myri_sbus.c:v1.9 12/Sep/99 David S. Miller (davem@redhat.com)\n"; | 7 | "myri_sbus.c:v2.0 June 23, 2006 David S. Miller (davem@davemloft.net)\n"; |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/config.h> | ||
11 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
12 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
13 | #include <linux/types.h> | 12 | #include <linux/types.h> |
@@ -81,10 +80,6 @@ static char version[] = | |||
81 | #define DHDR(x) | 80 | #define DHDR(x) |
82 | #endif | 81 | #endif |
83 | 82 | ||
84 | #ifdef MODULE | ||
85 | static struct myri_eth *root_myri_dev; | ||
86 | #endif | ||
87 | |||
88 | static void myri_reset_off(void __iomem *lp, void __iomem *cregs) | 83 | static void myri_reset_off(void __iomem *lp, void __iomem *cregs) |
89 | { | 84 | { |
90 | /* Clear IRQ mask. */ | 85 | /* Clear IRQ mask. */ |
@@ -365,7 +360,7 @@ static void myri_tx(struct myri_eth *mp, struct net_device *dev) | |||
365 | mp->tx_old = entry; | 360 | mp->tx_old = entry; |
366 | } | 361 | } |
367 | 362 | ||
368 | /* Determine the packet's protocol ID. The rule here is that we | 363 | /* Determine the packet's protocol ID. The rule here is that we |
369 | * assume 802.3 if the type field is short enough to be a length. | 364 | * assume 802.3 if the type field is short enough to be a length. |
370 | * This is normal practice and works for any 'now in use' protocol. | 365 | * This is normal practice and works for any 'now in use' protocol. |
371 | */ | 366 | */ |
@@ -373,11 +368,11 @@ static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
373 | { | 368 | { |
374 | struct ethhdr *eth; | 369 | struct ethhdr *eth; |
375 | unsigned char *rawp; | 370 | unsigned char *rawp; |
376 | 371 | ||
377 | skb->mac.raw = (((unsigned char *)skb->data) + MYRI_PAD_LEN); | 372 | skb->mac.raw = (((unsigned char *)skb->data) + MYRI_PAD_LEN); |
378 | skb_pull(skb, dev->hard_header_len); | 373 | skb_pull(skb, dev->hard_header_len); |
379 | eth = eth_hdr(skb); | 374 | eth = eth_hdr(skb); |
380 | 375 | ||
381 | #ifdef DEBUG_HEADER | 376 | #ifdef DEBUG_HEADER |
382 | DHDR(("myri_type_trans: ")); | 377 | DHDR(("myri_type_trans: ")); |
383 | dump_ehdr(eth); | 378 | dump_ehdr(eth); |
@@ -391,12 +386,12 @@ static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
391 | if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) | 386 | if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) |
392 | skb->pkt_type = PACKET_OTHERHOST; | 387 | skb->pkt_type = PACKET_OTHERHOST; |
393 | } | 388 | } |
394 | 389 | ||
395 | if (ntohs(eth->h_proto) >= 1536) | 390 | if (ntohs(eth->h_proto) >= 1536) |
396 | return eth->h_proto; | 391 | return eth->h_proto; |
397 | 392 | ||
398 | rawp = skb->data; | 393 | rawp = skb->data; |
399 | 394 | ||
400 | /* This is a magic hack to spot IPX packets. Older Novell breaks | 395 | /* This is a magic hack to spot IPX packets. Older Novell breaks |
401 | * the protocol design and runs IPX over 802.3 without an 802.2 LLC | 396 | * the protocol design and runs IPX over 802.3 without an 802.2 LLC |
402 | * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This | 397 | * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This |
@@ -404,7 +399,7 @@ static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
404 | */ | 399 | */ |
405 | if (*(unsigned short *)rawp == 0xFFFF) | 400 | if (*(unsigned short *)rawp == 0xFFFF) |
406 | return htons(ETH_P_802_3); | 401 | return htons(ETH_P_802_3); |
407 | 402 | ||
408 | /* Real 802.2 LLC */ | 403 | /* Real 802.2 LLC */ |
409 | return htons(ETH_P_802_2); | 404 | return htons(ETH_P_802_2); |
410 | } | 405 | } |
@@ -683,7 +678,7 @@ static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
683 | return 0; | 678 | return 0; |
684 | } | 679 | } |
685 | 680 | ||
686 | /* Create the MyriNet MAC header for an arbitrary protocol layer | 681 | /* Create the MyriNet MAC header for an arbitrary protocol layer |
687 | * | 682 | * |
688 | * saddr=NULL means use device source address | 683 | * saddr=NULL means use device source address |
689 | * daddr=NULL means leave destination address (eg unresolved arp) | 684 | * daddr=NULL means leave destination address (eg unresolved arp) |
@@ -706,7 +701,7 @@ static int myri_header(struct sk_buff *skb, struct net_device *dev, unsigned sho | |||
706 | /* Set the protocol type. For a packet of type ETH_P_802_3 we put the length | 701 | /* Set the protocol type. For a packet of type ETH_P_802_3 we put the length |
707 | * in here instead. It is up to the 802.2 layer to carry protocol information. | 702 | * in here instead. It is up to the 802.2 layer to carry protocol information. |
708 | */ | 703 | */ |
709 | if (type != ETH_P_802_3) | 704 | if (type != ETH_P_802_3) |
710 | eth->h_proto = htons(type); | 705 | eth->h_proto = htons(type); |
711 | else | 706 | else |
712 | eth->h_proto = htons(len); | 707 | eth->h_proto = htons(len); |
@@ -724,7 +719,7 @@ static int myri_header(struct sk_buff *skb, struct net_device *dev, unsigned sho | |||
724 | eth->h_dest[i] = 0; | 719 | eth->h_dest[i] = 0; |
725 | return(dev->hard_header_len); | 720 | return(dev->hard_header_len); |
726 | } | 721 | } |
727 | 722 | ||
728 | if (daddr) { | 723 | if (daddr) { |
729 | memcpy(eth->h_dest, daddr, dev->addr_len); | 724 | memcpy(eth->h_dest, daddr, dev->addr_len); |
730 | return dev->hard_header_len; | 725 | return dev->hard_header_len; |
@@ -759,16 +754,16 @@ static int myri_rebuild_header(struct sk_buff *skb) | |||
759 | #endif | 754 | #endif |
760 | 755 | ||
761 | default: | 756 | default: |
762 | printk(KERN_DEBUG | 757 | printk(KERN_DEBUG |
763 | "%s: unable to resolve type %X addresses.\n", | 758 | "%s: unable to resolve type %X addresses.\n", |
764 | dev->name, (int)eth->h_proto); | 759 | dev->name, (int)eth->h_proto); |
765 | 760 | ||
766 | memcpy(eth->h_source, dev->dev_addr, dev->addr_len); | 761 | memcpy(eth->h_source, dev->dev_addr, dev->addr_len); |
767 | return 0; | 762 | return 0; |
768 | break; | 763 | break; |
769 | } | 764 | } |
770 | 765 | ||
771 | return 0; | 766 | return 0; |
772 | } | 767 | } |
773 | 768 | ||
774 | int myri_header_cache(struct neighbour *neigh, struct hh_cache *hh) | 769 | int myri_header_cache(struct neighbour *neigh, struct hh_cache *hh) |
@@ -896,8 +891,9 @@ static void dump_eeprom(struct myri_eth *mp) | |||
896 | } | 891 | } |
897 | #endif | 892 | #endif |
898 | 893 | ||
899 | static int __init myri_ether_init(struct sbus_dev *sdev, int num) | 894 | static int __init myri_ether_init(struct sbus_dev *sdev) |
900 | { | 895 | { |
896 | static int num; | ||
901 | static unsigned version_printed; | 897 | static unsigned version_printed; |
902 | struct net_device *dev; | 898 | struct net_device *dev; |
903 | struct myri_eth *mp; | 899 | struct myri_eth *mp; |
@@ -913,6 +909,9 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num) | |||
913 | if (version_printed++ == 0) | 909 | if (version_printed++ == 0) |
914 | printk(version); | 910 | printk(version); |
915 | 911 | ||
912 | SET_MODULE_OWNER(dev); | ||
913 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | ||
914 | |||
916 | mp = (struct myri_eth *) dev->priv; | 915 | mp = (struct myri_eth *) dev->priv; |
917 | spin_lock_init(&mp->irq_lock); | 916 | spin_lock_init(&mp->irq_lock); |
918 | mp->myri_sdev = sdev; | 917 | mp->myri_sdev = sdev; |
@@ -1070,7 +1069,7 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num) | |||
1070 | /* Register interrupt handler now. */ | 1069 | /* Register interrupt handler now. */ |
1071 | DET(("Requesting MYRIcom IRQ line.\n")); | 1070 | DET(("Requesting MYRIcom IRQ line.\n")); |
1072 | if (request_irq(dev->irq, &myri_interrupt, | 1071 | if (request_irq(dev->irq, &myri_interrupt, |
1073 | SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) { | 1072 | IRQF_SHARED, "MyriCOM Ethernet", (void *) dev)) { |
1074 | printk("MyriCOM: Cannot register interrupt handler.\n"); | 1073 | printk("MyriCOM: Cannot register interrupt handler.\n"); |
1075 | goto err; | 1074 | goto err; |
1076 | } | 1075 | } |
@@ -1092,10 +1091,9 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num) | |||
1092 | goto err_free_irq; | 1091 | goto err_free_irq; |
1093 | } | 1092 | } |
1094 | 1093 | ||
1095 | #ifdef MODULE | 1094 | dev_set_drvdata(&sdev->ofdev.dev, mp); |
1096 | mp->next_module = root_myri_dev; | 1095 | |
1097 | root_myri_dev = mp; | 1096 | num++; |
1098 | #endif | ||
1099 | 1097 | ||
1100 | printk("%s: MyriCOM MyriNET Ethernet ", dev->name); | 1098 | printk("%s: MyriCOM MyriNET Ethernet ", dev->name); |
1101 | 1099 | ||
@@ -1114,61 +1112,68 @@ err: | |||
1114 | return -ENODEV; | 1112 | return -ENODEV; |
1115 | } | 1113 | } |
1116 | 1114 | ||
1117 | static int __init myri_sbus_match(struct sbus_dev *sdev) | ||
1118 | { | ||
1119 | char *name = sdev->prom_name; | ||
1120 | 1115 | ||
1121 | if (!strcmp(name, "MYRICOM,mlanai") || | 1116 | static int __devinit myri_sbus_probe(struct of_device *dev, const struct of_device_id *match) |
1122 | !strcmp(name, "myri")) | 1117 | { |
1123 | return 1; | 1118 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
1124 | 1119 | ||
1125 | return 0; | 1120 | return myri_ether_init(sdev); |
1126 | } | 1121 | } |
1127 | 1122 | ||
1128 | static int __init myri_sbus_probe(void) | 1123 | static int __devexit myri_sbus_remove(struct of_device *dev) |
1129 | { | 1124 | { |
1130 | struct sbus_bus *bus; | 1125 | struct myri_eth *mp = dev_get_drvdata(&dev->dev); |
1131 | struct sbus_dev *sdev = NULL; | 1126 | struct net_device *net_dev = mp->dev; |
1132 | static int called; | ||
1133 | int cards = 0, v; | ||
1134 | 1127 | ||
1135 | #ifdef MODULE | 1128 | unregister_netdevice(net_dev); |
1136 | root_myri_dev = NULL; | ||
1137 | #endif | ||
1138 | 1129 | ||
1139 | if (called) | 1130 | free_irq(net_dev->irq, net_dev); |
1140 | return -ENODEV; | 1131 | |
1141 | called++; | 1132 | if (mp->eeprom.cpuvers < CPUVERS_4_0) { |
1142 | 1133 | sbus_iounmap(mp->regs, mp->reg_size); | |
1143 | for_each_sbus(bus) { | 1134 | } else { |
1144 | for_each_sbusdev(sdev, bus) { | 1135 | sbus_iounmap(mp->cregs, PAGE_SIZE); |
1145 | if (myri_sbus_match(sdev)) { | 1136 | sbus_iounmap(mp->lregs, (256 * 1024)); |
1146 | cards++; | 1137 | sbus_iounmap(mp->lanai, (512 * 1024)); |
1147 | DET(("Found myricom myrinet as %s\n", sdev->prom_name)); | ||
1148 | if ((v = myri_ether_init(sdev, (cards - 1)))) | ||
1149 | return v; | ||
1150 | } | ||
1151 | } | ||
1152 | } | 1138 | } |
1153 | if (!cards) | 1139 | |
1154 | return -ENODEV; | 1140 | free_netdev(net_dev); |
1141 | |||
1142 | dev_set_drvdata(&dev->dev, NULL); | ||
1143 | |||
1155 | return 0; | 1144 | return 0; |
1156 | } | 1145 | } |
1157 | 1146 | ||
1158 | static void __exit myri_sbus_cleanup(void) | 1147 | static struct of_device_id myri_sbus_match[] = { |
1148 | { | ||
1149 | .name = "MYRICOM,mlanai", | ||
1150 | }, | ||
1151 | { | ||
1152 | .name = "myri", | ||
1153 | }, | ||
1154 | {}, | ||
1155 | }; | ||
1156 | |||
1157 | MODULE_DEVICE_TABLE(of, myri_sbus_match); | ||
1158 | |||
1159 | static struct of_platform_driver myri_sbus_driver = { | ||
1160 | .name = "myri", | ||
1161 | .match_table = myri_sbus_match, | ||
1162 | .probe = myri_sbus_probe, | ||
1163 | .remove = __devexit_p(myri_sbus_remove), | ||
1164 | }; | ||
1165 | |||
1166 | static int __init myri_sbus_init(void) | ||
1167 | { | ||
1168 | return of_register_driver(&myri_sbus_driver, &sbus_bus_type); | ||
1169 | } | ||
1170 | |||
1171 | static void __exit myri_sbus_exit(void) | ||
1159 | { | 1172 | { |
1160 | #ifdef MODULE | 1173 | of_unregister_driver(&myri_sbus_driver); |
1161 | while (root_myri_dev) { | ||
1162 | struct myri_eth *next = root_myri_dev->next_module; | ||
1163 | |||
1164 | unregister_netdev(root_myri_dev->dev); | ||
1165 | /* this will also free the co-allocated 'root_myri_dev' */ | ||
1166 | free_netdev(root_myri_dev->dev); | ||
1167 | root_myri_dev = next; | ||
1168 | } | ||
1169 | #endif /* MODULE */ | ||
1170 | } | 1174 | } |
1171 | 1175 | ||
1172 | module_init(myri_sbus_probe); | 1176 | module_init(myri_sbus_init); |
1173 | module_exit(myri_sbus_cleanup); | 1177 | module_exit(myri_sbus_exit); |
1178 | |||
1174 | MODULE_LICENSE("GPL"); | 1179 | MODULE_LICENSE("GPL"); |