bk://gkernel.bkbits.net/netdev-2.6 jgarzik@pobox.com|ChangeSet|20040611092528|21407 jgarzik # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/13 11:23:12-07:00 akpm@bix.(none) # Merge bk://gkernel.bkbits.net/netdev-2.6 # into bix.(none):/usr/src/bk-netdev # # drivers/net/epic100.c # 2004/06/13 11:23:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/at1700.c # 2004/06/13 11:23:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/06/13 11:23:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/3c527.c # 2004/06/13 11:23:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/10 20:53:18-04:00 jgarzik@pobox.com # Merge pobox.com:/spare/repo/netdev-2.6/acenic # into pobox.com:/spare/repo/netdev-2.6/ALL # # ChangeSet # 2004/06/10 20:14:00-04:00 jgarzik@pobox.com # Merge # # ChangeSet # 2004/06/10 20:00:01-04:00 margitsw@t-online.de # [PATCH] prism54: White space and indentation # # 2004-05-29 Margit Schubert-While # # * White space and indentation patch # # ChangeSet # 2004/06/10 19:59:53-04:00 margitsw@t-online.de # [PATCH] prism54: Fix typo # # 2004-05-29 Margit Schubert-While # # * isl_ioctl.c : Fix typo # # ChangeSet # 2004/06/10 19:59:45-04:00 margitsw@t-online.de # [PATCH] prism54: Fix channel stats, bump version to 1.2 # # 2004-05-20 Aurelien Alleaume # # * islpci_eth.c : use dev_kfree_skb_irq instead of dev_kfree_skb where needed. # # * isl_ioctl.c : report channel instead of frequency in scan. # # * islpci_hotplug.c : bump version to 1.2 # # ChangeSet # 2004/06/10 19:59:36-04:00 margitsw@t-online.de # [PATCH] prism54: Reduce module verbosity # # 2004-05-01 Margit Schubert-While # # * Reduce module verbosity # # ChangeSet # 2004/06/10 19:59:28-04:00 margitsw@t-online.de # [PATCH] prism54: Align skb patch # # * islpci_eth.c, islpci_dev.c : Align skb->data unconditonally after # allocation. This would appear to improve RX rate # # ChangeSet # 2004/06/10 19:59:20-04:00 margitsw@t-online.de # [PATCH] prism54: Add likely/unlikely, KO wds completely # # * islpci_mgt.h : Change init_wds definition # # * islpci_eth.c : Do some likely/unlikely # # ChangeSet # 2004/06/10 19:59:11-04:00 margitsw@t-online.de # [PATCH] prism54: Don't allow mib reads while unconfigured # # 004-04-17 Aurelien Alleaume # # * oid_mgt.c, isl_ioctl.c : Cleanup. Prevented real oid reading # before the card is configured with mib values (might be # related to # bug #53). # # ChangeSet # 2004/06/10 19:59:03-04:00 margitsw@t-online.de # [PATCH] prism54: Fix bug 77, strengthened oid txn # # 2004-04-09 Aurelien Alleaume # # * oid_mgt.c, isl_ioctl.c : Cleanups. Bug #77. Minor stuffs. # # * islpci_mgt.c (islpci_mgt_transaction) : enforce serialization # in oid transaction. lindent.sh. # # * islpci_mgt.c (islpci_mgt_transaction) : Strengthened oid transaction. # # ChangeSet # 2004/06/10 20:03:05-04:00 jgarzik@pobox.com # Merge pobox.com:/spare/repo/netdev-2.6/misc # into pobox.com:/spare/repo/netdev-2.6/ALL # # ChangeSet # 2004/06/10 20:12:44-04:00 scott.feldman@intel.com # [PATCH] e100: use NAPI mode all the time # # I see no reason to keep the non-NAPI option for e100. This patch removes # the CONFIG_E100_NAPI option and puts the driver in NAPI mode all the time. # Matches the way tg3 works. # # Unless someone has a really good reason to keep the non-NAPI mode, this # should go in for 2.6.7. # # -scott # # ChangeSet # 2004/06/10 19:58:55-04:00 margitsw@t-online.de # [PATCH] prism54: Fix bugs 39/73 # # 2004-04-07 Margit Schubert-While # # * Bugs 39 and 73 # # ChangeSet # 2004/06/10 19:58:46-04:00 margitsw@t-online.de # [PATCH] prism54: Fix bugs 74/75 # # 2004-03-22 Aurelien Alleaume # # * oid_mgt.c, isl_ioctl.c : Minor bugfixes : #74 and #75. # # ChangeSet # 2004/06/10 19:38:59-04:00 bunk@fs.tum.de # [PATCH] add NAPI help texts # # NAPI seems to be so self-explaining that no help texts are needed. ;-) # # I combined the two help texts that were at NAPI options, and added them # to all NAPI options. # # ChangeSet # 2004/06/10 19:37:53-04:00 rmk@arm.linux.org.uk # [PATCH] add ARM smc91x driver # # ChangeSet # 2004/06/10 19:58:38-04:00 margitsw@t-online.de # [PATCH] prism54: Fix endian patch # # * Split out patch islpci_eth.c : # * Fix endian problem (bug 74/75 related) # # ChangeSet # 2004/06/10 20:52:50-04:00 jgarzik@pobox.com # [netdrvr acenic] remove unneeded ifdefs # # ChangeSet # 2004/06/10 20:19:03-04:00 shemminger@osdl.org # [PATCH] fix oops from acenic ethtool # # Fix the following OOPS that happens when doing ifup on FC-2 # with 2.6.7 in acenic and a security hole due to missing capable(NET_ADMIN), # by replacing private ethtool handling with ethtool_ops. # # (Yes, Jes because of DEV_ETHTOOL_OPS define it will still work # on ancient kernels.) # # ChangeSet # 2004/06/10 19:58:30-04:00 margitsw@t-online.de # [PATCH] prism54: Kernel compatibility # # 2004-03-20 Margit Schubert-While # # * isl_38xx.[ch], isl_ioctl.c, islpci_dev.[ch], islpci_eth.c # islpci_hotplug.c, islpci_mgt.[ch], oid_mgt.c, prismcompat.h: # Adopt new prism54 kernel compatibility. # Remove remaining kernel version ifdefs. # # ChangeSet # 2004/06/10 19:27:16-04:00 jgarzik@pobox.com # Merge pobox.com:/spare/repo/linux-2.6 # into pobox.com:/spare/repo/netdev-2.6/ALL # # ChangeSet # 2004/06/10 19:37:01-04:00 akpm@osdl.org # [PATCH] fealnx-mac-address-and-other-issues.patch # # (resend - I need to get this out of my tree my one means or another..) # # # From: "SuD (Alex)" # # I recently was given a surecom 10/100 ethernet card and found that i could # not change Mac address for it as other driver/devices allow. I tried to # implement the missing feature and noticed that the device is quite peculiar # (or either my system is broken), when trying to fill mac address registers # (no matter whether io_ops is set): - If I write a byte (writeb) to an even # i/o address it seems like actually a word was written (the next byte is set # to 0). - If I write a byte to an odd i/o address my pc gets bad freezed. # # That made think of writing 16bit words (writew) for the memory address, as # opposed to what most driver examples do. It works for me (I hope i set the # lines at the right place in device_open function after the device is # reset). I hope the code is clean enough and does not mess with byte # ordering. This is the patch (this time against 2.6.5): # # (akpm: Is this right on big-endian?) # # drivers/net/acenic.c # 2004/06/10 20:53:15-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/acenic.c # 2004/06/10 20:52:44-04:00 jgarzik@pobox.com +0 -6 # [netdrvr acenic] remove unneeded ifdefs # # drivers/net/acenic.h # 2004/06/04 17:31:46-04:00 shemminger@osdl.org +0 -1 # fix oops from acenic ethtool # # drivers/net/acenic.c # 2004/06/04 17:31:46-04:00 shemminger@osdl.org +127 -121 # fix oops from acenic ethtool # # drivers/net/Kconfig # 2004/06/10 20:13:57-04:00 jgarzik@pobox.com +0 -0 # SCCS merged # # drivers/net/e100.c # 2004/06/04 19:02:04-04:00 scott.feldman@intel.com +5 -24 # e100: use NAPI mode all the time # # drivers/net/Kconfig # 2004/06/04 19:02:34-04:00 scott.feldman@intel.com +0 -4 # e100: use NAPI mode all the time # # drivers/net/Kconfig # 2004/06/10 20:03:02-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/wireless/prism54/oid_mgt.h # 2004/05/28 08:06:38-04:00 margitsw@t-online.de +1 -1 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/oid_mgt.c # 2004/05/28 09:12:49-04:00 margitsw@t-online.de +7 -7 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/islpci_mgt.c # 2004/05/28 09:12:49-04:00 margitsw@t-online.de +42 -42 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +8 -8 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/islpci_dev.h # 2004/05/28 08:25:30-04:00 margitsw@t-online.de +1 -1 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +28 -34 # prism54: White space and indentation (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 09:33:42-04:00 margitsw@t-online.de +1 -1 # prism54: Fix typo # # drivers/net/wireless/prism54/islpci_hotplug.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +1 -1 # prism54: Fix channel stats, bump version to 1.2 (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +3 -3 # prism54: Fix channel stats, bump version to 1.2 (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 09:49:41-04:00 margitsw@t-online.de +2 -2 # prism54: Fix channel stats, bump version to 1.2 (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 08:11:34-04:00 margitsw@t-online.de +3 -1 # prism54: Reduce module verbosity (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/06/05 08:09:41-04:00 margitsw@t-online.de +1 -0 # prism54: Align skb patch (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 08:09:41-04:00 margitsw@t-online.de +1 -0 # prism54: Align skb patch (resend) # # drivers/net/wireless/prism54/islpci_mgt.h # 2004/05/28 09:33:42-04:00 margitsw@t-online.de +1 -1 # prism54: Add likely/unlikely, KO wds completely (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/05/28 09:33:42-04:00 margitsw@t-online.de +9 -8 # prism54: Add likely/unlikely, KO wds completely (resend) # # drivers/net/wireless/prism54/oid_mgt.c # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +40 -21 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/islpci_mgt.c # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +5 -3 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +3 -1 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/isl_ioctl.h # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +0 -1 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/06/05 08:03:15-04:00 margitsw@t-online.de +5 -31 # prism54: Don't allow mib reads while unconfigured (resend) # # drivers/net/wireless/prism54/oid_mgt.c # 2004/05/28 09:08:01-04:00 margitsw@t-online.de +2 -6 # prism54: Fix bug 77, strengthened oid txn (resend) # # drivers/net/wireless/prism54/islpci_mgt.c # 2004/05/28 09:08:01-04:00 margitsw@t-online.de +35 -26 # prism54: Fix bug 77, strengthened oid txn (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 09:08:01-04:00 margitsw@t-online.de +13 -76 # prism54: Fix bug 77, strengthened oid txn (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 07:57:11-04:00 margitsw@t-online.de +2 -2 # prism54: Fix bugs 39/73 (resend) # # drivers/net/wireless/prism54/oid_mgt.c # 2004/05/28 08:43:01-04:00 margitsw@t-online.de +2 -2 # prism54: Fix bugs 74/75 (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/05/28 08:43:01-04:00 margitsw@t-online.de +1 -0 # prism54: Fix bugs 74/75 (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/05/28 08:25:30-04:00 margitsw@t-online.de +16 -16 # prism54: Fix endian patch (resend) # # drivers/net/wireless/prism54/prismcompat.h # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +46 -0 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/prismcompat.h # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +0 -0 # BitKeeper file /spare/repo/netdev-2.6/prism54/drivers/net/wireless/prism54/prismcompat.h # # drivers/net/wireless/prism54/oid_mgt.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_mgt.h # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +0 -9 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_mgt.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -15 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_hotplug.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_eth.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -0 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_dev.h # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +0 -20 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/islpci_dev.c # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +121 -27 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/isl_ioctl.c # 2004/06/05 07:44:14-04:00 margitsw@t-online.de +1 -1 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/isl_38xx.h # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +0 -10 # prism54: Kernel compatibility (resend) # # drivers/net/wireless/prism54/isl_38xx.c # 2004/06/05 07:45:32-04:00 margitsw@t-online.de +2 -132 # prism54: Kernel compatibility (resend) # # drivers/net/tulip/Kconfig # 2004/06/04 11:16:07-04:00 bunk@fs.tum.de +11 -4 # add NAPI help texts # # drivers/net/Kconfig # 2004/06/04 11:18:14-04:00 bunk@fs.tum.de +70 -0 # add NAPI help texts # # drivers/net/arm/smc91x.h # 2004/05/29 08:04:43-04:00 rmk@arm.linux.org.uk +829 -0 # Re: smc91x driver # # drivers/net/arm/smc91x.c # 2004/05/29 07:57:20-04:00 rmk@arm.linux.org.uk +2171 -0 # Re: smc91x driver # # drivers/net/arm/smc91x.h # 2004/05/29 08:04:43-04:00 rmk@arm.linux.org.uk +0 -0 # BitKeeper file /spare/repo/netdev-2.6/misc/drivers/net/arm/smc91x.h # # drivers/net/arm/smc91x.c # 2004/05/29 07:57:20-04:00 rmk@arm.linux.org.uk +0 -0 # BitKeeper file /spare/repo/netdev-2.6/misc/drivers/net/arm/smc91x.c # # drivers/net/arm/Makefile # 2003/07/06 11:12:19-04:00 rmk@arm.linux.org.uk +1 -0 # Re: smc91x driver # # drivers/net/arm/Kconfig # 2003/09/28 11:03:12-04:00 rmk@arm.linux.org.uk +17 -0 # Re: smc91x driver # # drivers/net/fealnx.c # 2004/04/23 01:29:23-04:00 akpm@osdl.org +5 -0 # fealnx-mac-address-and-other-issues.patch # # drivers/net/epic100.c # 2004/06/10 19:27:12-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/at1700.c # 2004/06/10 19:27:12-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/3c527.c # 2004/06/10 19:27:12-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # ChangeSet # 2004/06/08 12:31:22-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev # # drivers/net/epic100.c # 2004/06/08 12:31:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/at1700.c # 2004/06/08 12:31:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/3c527.c # 2004/06/08 12:31:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/07 19:56:33-07:00 akpm@bix.(none) # Merge bk://gkernel.bkbits.net/netdev-2.6 # into bix.(none):/usr/src/bk-netdev # # drivers/net/yellowfin.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/via-rhine.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/tulip/winbond-840.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/sungem.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/starfire.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/ns83820.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/natsemi.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/forcedeth.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/ewrk3.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/epic100.c # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/06/07 19:56:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/07 17:41:39-04:00 jgarzik@pobox.com # Merge pobox.com:/spare/repo/linux-2.6 # into pobox.com:/spare/repo/netdev-2.6/ALL # # drivers/net/yellowfin.c # 2004/06/07 17:41:35-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/tulip/winbond-840.c # 2004/06/07 17:41:35-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/via-rhine.c # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/sungem.c # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/starfire.c # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/ns83820.c # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/natsemi.c # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/forcedeth.c # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/ewrk3.c # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/epic100.c # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/06/07 17:41:34-04:00 jgarzik@pobox.com +0 -0 # Auto merged # # ChangeSet # 2004/06/04 22:52:13-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev # # drivers/net/yellowfin.c # 2004/06/04 22:52:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/via-rhine.c # 2004/06/04 22:52:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/tulip/winbond-840.c # 2004/06/04 22:52:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/sungem.c # 2004/06/04 22:52:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/starfire.c # 2004/06/04 22:52:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/natsemi.c # 2004/06/04 22:52:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/ewrk3.c # 2004/06/04 22:52:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/epic100.c # 2004/06/04 22:52:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/04 02:29:25-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev # # drivers/net/yellowfin.c # 2004/06/04 02:29:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/starfire.c # 2004/06/04 02:29:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/ns83820.c # 2004/06/04 02:29:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/natsemi.c # 2004/06/04 02:29:21-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/forcedeth.c # 2004/06/04 02:29:21-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/ewrk3.c # 2004/06/04 02:29:21-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/02 23:45:50-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev # # drivers/net/Kconfig # 2004/06/02 23:45:47-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/02 20:05:09-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/r8169 # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/r8169.c # 2004/06/02 20:05:05-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/06/02 20:03:26-04:00 romieu@fr.zoreil.com # [PATCH] r8169: tx lock removal # # spinlock removal crusade. # # The patch rephrases the spinlock_irq() in rtl8169_start_xmit() and its # companion in the Tx irq handling patch in terms of ordered operations. # # drivers/net/r8169.c # 2004/06/02 18:15:37-04:00 romieu@fr.zoreil.com +10 -9 # r8169: tx lock removal # # ChangeSet # 2004/06/02 20:03:18-04:00 romieu@fr.zoreil.com # [PATCH] r8169: gcc bug workaround # # Add a temporary variable to workaround gcc 2.95.3 bug. # # drivers/net/r8169.c # 2004/06/02 18:15:34-04:00 romieu@fr.zoreil.com +5 -2 # r8169: gcc bug workaround # # ChangeSet # 2004/06/02 20:03:10-04:00 romieu@fr.zoreil.com # [PATCH] r8169: initial link setup rework # # Use rtl8169_set_speed() for link setup in rtl8169_init_one(): # - the code which handles the option checking is isolated; # - display (once) a notice message about the deprecated interface; # - rtl8169_open() enables the phy timer if the link is not up; # - rtl8169_set_speed() checks that the netdevice is actually ready # in order to activate the timer. # # drivers/net/r8169.c # 2004/06/02 17:18:02-04:00 romieu@fr.zoreil.com +43 -93 # r8169: initial link setup rework # # ChangeSet # 2004/06/02 20:03:02-04:00 romieu@fr.zoreil.com # [PATCH] r8169: link handling and phy reset rework # # Link handling changes (Andy Lutomirski ): # - removed rtl8169_hw_phy_reset() and its busy loop; # - RTL8169_PHY_TIMEOUT is x10 to account for the removal of the # phy_link_down_cnt loop in rtl8169_phy_timer(); # - added spinlocking in timer context for rtl8169_phy_timer to avoid # messing with the {set/get}_settings commands issued via ethtool; # - more TBI stuff. # # This patch differs from the former version on the following points: # - the LinkChg irq does not enable the phy timer when the link goes # down any more; # - the phy timer is not enabled in rtl8169_set_speed(); # - removal of the initial renegotiation hack. # # drivers/net/r8169.c # 2004/06/02 17:17:50-04:00 romieu@fr.zoreil.com +94 -50 # r8169: link handling and phy reset rework # # ChangeSet # 2004/06/02 15:37:59-04:00 rl@hellgate.ch # [PATCH] Add rhine_power_init(): get power regs into sane state # # Add rhine_power_init(): get power regs into sane state. # Move the respective code out of rhine_init_one. Add code for # two additional patterns (Rhine III). # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +35 -20 # Add rhine_power_init(): get power regs into sane state # # ChangeSet # 2004/06/02 15:37:51-04:00 rl@hellgate.ch # [PATCH] Rewrite special-casing # # Use PCI revision to determine special cases. One bit field replaces a # bunch of data structures holding special case information. # # Replace chip_id, drv_flags in rhine_private with quirks # # Remove enum rhine_chips, struct rhine_chip_info (and array), # enum chip_capability_flags # # Add enum rhine_revs, enum rhine_quirks (some values in preparation for # subsequent changes) # # wait_for_reset() and enable_mmio() now use quirks instead of chip_id # # Remove model names from ident strings for now. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +76 -58 # Rewrite special-casing # # ChangeSet # 2004/06/02 15:37:42-04:00 rl@hellgate.ch # [PATCH] Return codes for rhine_init_one # # Use return codes in rhine_init_one instead of -ENODEV for all errors. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +15 -7 # Return codes for rhine_init_one # # ChangeSet # 2004/06/02 15:37:34-04:00 rl@hellgate.ch # [PATCH] Nuke all pci_flags # # All this code together can be replaced with a single #ifdef USE_MMIO. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +11 -20 # Nuke all pci_flags # # ChangeSet # 2004/06/02 15:37:26-04:00 rl@hellgate.ch # [PATCH] Nuke default_port, references to if_port, medialock # # As is, code doesn't do anything useful. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +0 -10 # Nuke default_port, references to if_port, medialock # # ChangeSet # 2004/06/02 15:37:18-04:00 rl@hellgate.ch # [PATCH] Nuke HasESIPhy and related code # # This has been dead code forever. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +2 -3 # Nuke HasESIPhy and related code # # ChangeSet # 2004/06/02 15:37:09-04:00 rl@hellgate.ch # [PATCH] Nuke CanHaveMII and related code # # All Rhines can have a MII. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +26 -40 # Nuke CanHaveMII and related code # # ChangeSet # 2004/06/02 15:37:01-04:00 rl@hellgate.ch # [PATCH] Nuke HAS_IP_COPYSUM # # HAS_IP_COPYSUM has been utterly meaningless for a long time. # # Signed-off-by: Roger Luethi # # drivers/net/via-rhine.c # 2004/06/01 20:00:00-04:00 rl@hellgate.ch +0 -5 # Nuke HAS_IP_COPYSUM # # ChangeSet # 2004/06/02 09:39:39-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/r8169 # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/r8169.c # 2004/06/02 09:39:36-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/06/02 09:39:36-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/06/02 09:38:31-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/misc-herbert # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/yellowfin.c # 2004/06/02 09:38:27-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/natsemi.c # 2004/06/02 09:38:27-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/ibmlana.c # 2004/06/02 09:38:27-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/acenic.c # 2004/06/02 09:38:27-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/06/02 09:37:12-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/ip-copysum # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/tulip/winbond-840.c # 2004/06/02 09:37:08-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/epic100.c # 2004/06/02 09:37:08-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/05/27 15:21:03-04:00 herbert@gondor.apana.org.au # [NETDRV #2] Use driver-specific name for resources # # Here is the next part which uses a driver-specific name instead of # dev->name for resource allocations prior to netdev registration. # It also changes printks that are in direct response to errors in # resource allocations. # # drivers/net/zorro8390.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/yellowfin.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/wd.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/sunhme.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/sungem.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/sun3_82586.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/stnic.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/starfire.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/smc9194.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/smc-ultra32.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/smc-ultra.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/smc-mca.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/r8169.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/oaknet.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ns83820.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ni52.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne3210.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +6 -4 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne2k_cbus.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne2.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ne-h8300.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/natsemi.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/lp486e.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/lne390.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/jazzsonic.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ibmlana.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/hp.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/hp-plus.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/forcedeth.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/fmv18x.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ewrk3.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/eth16i.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -4 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/eepro.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/e2100.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/defxx.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/cs89x0.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/at1700.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +5 -3 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/apne.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/acenic.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/ac3200.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +4 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/82596.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +3 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c527.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c523.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c507.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c503.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +2 -2 # 2/x: [NETDRV] Use driver-specific name for resources # # drivers/net/3c501.c # 2004/05/22 13:40:55-04:00 herbert@gondor.apana.org.au +1 -1 # 2/x: [NETDRV] Use driver-specific name for resources # # ChangeSet # 2004/05/27 15:20:53-04:00 herbert@gondor.apana.org.au # [NETDRV #1] Ifdef builtin-only probe in ISA/MCA drivers # # Here is the bit which conditionalises the # builtin-only probe functions. # # drivers/net/wd.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/smc-ultra.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ne2k_cbus.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ne2.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ne.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ne-h8300.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/lne390.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/lance.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/isa-skeleton.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/hp100.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/hp.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/hp-plus.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ewrk3.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/eth16i.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/es3210.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/eexpress.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/eepro.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/e2100.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/cs89x0.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +1 -1 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/ac3200.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/3c523.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/3c505.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -1 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # drivers/net/3c503.c # 2004/05/20 17:16:23-04:00 herbert@gondor.apana.org.au +2 -0 # 1/x: [NETDRV] Ifdef builtin-only probe in ISA/MCA drivers # # ChangeSet # 2004/05/27 13:58:44-04:00 romieu@fr.zoreil.com # [PATCH] r8169: ethtool .get_{settings/link} # # - ethtool get_settings() for r8169 (Andy Lutomirski ); # - rtl8169_ethtool_ops.get_drvinfo() is set as well; # - added some bits to handle the TBI status. # # The locking does not need to be specially clever. # # drivers/net/r8169.c # 2004/05/20 07:15:59-04:00 romieu@fr.zoreil.com +87 -0 # r8169: ethtool .get_{settings/link} # # ChangeSet # 2004/05/27 13:58:35-04:00 romieu@fr.zoreil.com # [PATCH] r8169: ethtool .set_settings # # ethtool set_settings support (Andy Lutomirski ). # The initial code has been modified so that the settings of parameters # for TBI and normal mode do not step on each others shoes. # # drivers/net/r8169.c # 2004/05/20 07:03:25-04:00 romieu@fr.zoreil.com +97 -0 # r8169: ethtool .set_settings # # ChangeSet # 2004/05/27 13:38:57-04:00 rl@hellgate.ch # [PATCH] Nuke HAS_IP_COPYSUM for net drivers # # Entirely untested, but Obviously Correct(TM). HAS_IP_COPYSUM has been # utterly meaningless for a long time. # # drivers/net/yellowfin.c # 2004/05/25 14:46:47-04:00 rl@hellgate.ch +0 -5 # Nuke HAS_IP_COPYSUM for net drivers # # drivers/net/tulip/winbond-840.c # 2004/05/25 14:46:26-04:00 rl@hellgate.ch +0 -6 # Nuke HAS_IP_COPYSUM for net drivers # # drivers/net/natsemi.c # 2004/05/25 14:51:58-04:00 rl@hellgate.ch +0 -5 # Nuke HAS_IP_COPYSUM for net drivers # # drivers/net/epic100.c # 2004/05/25 14:45:55-04:00 rl@hellgate.ch +0 -5 # Nuke HAS_IP_COPYSUM for net drivers # # ChangeSet # 2004/05/17 14:07:14-04:00 romieu@fr.zoreil.com # [PATCH] r8169: janitoring # # Spring cleanup # - unsigned int (u32) should be slightly faster on ppc64 (Jon D Mason); # - misc minor de-uglyfication. # # drivers/net/r8169.c # 2004/05/14 17:08:45-04:00 romieu@fr.zoreil.com +47 -47 # 2.6.6-mm2 - r8169 janitoring # # ChangeSet # 2004/05/17 14:07:06-04:00 romieu@fr.zoreil.com # [PATCH] r8169: cosmetic renaming of a register # # RxUnderrun status bit renamed to LinkChg (identical to the 8139cp driver). # # drivers/net/r8169.c # 2004/05/14 17:08:47-04:00 romieu@fr.zoreil.com +5 -5 # 2.6.6-mm2 - r8169 register rename # # ChangeSet # 2004/05/17 14:06:58-04:00 romieu@fr.zoreil.com # [PATCH] r8169: napi support # # Napi for r8169 (Jon D Mason ). # Both Tx and Rx processing are moved to the ->poll() function. # # drivers/net/r8169.c # 2004/05/14 17:07:18-04:00 romieu@fr.zoreil.com +78 -11 # 2.6.6-mm2 - r8169 napi # # drivers/net/Kconfig # 2004/05/14 17:07:18-04:00 romieu@fr.zoreil.com +5 -0 # 2.6.6-mm2 - r8169 napi # # ChangeSet # 2004/04/21 23:30:47-04:00 romieu@fr.zoreil.com # [PATCH] epic100: code removal in irq handler # # The loop in the irq handler is not needed any more as the high frequency # events have been deferred due to napi usage. # # drivers/net/epic100.c # 2004/04/19 18:37:16-04:00 romieu@fr.zoreil.com +52 -64 # 2.6.6-rc1-mm1 - code removal in the epic100 irq handler # # ChangeSet # 2004/04/21 23:30:40-04:00 romieu@fr.zoreil.com # [PATCH] epic100: spin_unlock_irqrestore avoidance # # This patch avoids to duplicate a spin_unlock: # - it is mostly an artifact due to wild goto; # - it makes the generated code smaller. # # drivers/net/epic100.c # 2004/04/19 18:37:05-04:00 romieu@fr.zoreil.com +16 -10 # 2.6.6-rc1-mm1 - spin_unlock_irqrestore avoidance in epic100 # # ChangeSet # 2004/03/25 23:52:21-05:00 romieu@fr.zoreil.com # [netdrvr epic100] napi fixes # # Multiple invocation of __netif_rx_schedule() in epic_interrupt() while # epic_poll loops over __netif_rx_complete() leads to serious device # refcount leak. # # drivers/net/epic100.c # 2004/03/25 23:52:16-05:00 romieu@fr.zoreil.com +18 -15 # [netdrvr epic100] napi fixes # # Multiple invocation of __netif_rx_schedule() in epic_interrupt() while # epic_poll loops over __netif_rx_complete() leads to serious device # refcount leak. # # ChangeSet # 2004/03/22 19:07:18-05:00 romieu@fr.zoreil.com # [netdrvr epic100] napi 3/3 - transmit path # # drivers/net/epic100.c # 2004/03/22 18:18:40-05:00 romieu@fr.zoreil.com +9 -11 # 2.6.5-rc2 - epic100 napi # # ChangeSet # 2004/03/22 19:07:11-05:00 romieu@fr.zoreil.com # [netdrvr epic100] napi 2/3 - receive path # # drivers/net/epic100.c # 2004/03/22 18:18:33-05:00 romieu@fr.zoreil.com +116 -21 # 2.6.5-rc2 - epic100 napi # # ChangeSet # 2004/03/22 19:07:03-05:00 romieu@fr.zoreil.com # [netdrvr epic100] napi 1/3 - just shuffle some code around # # Isolate the classical TX part of epic_interrupt. Innocent code shuffling. # # drivers/net/epic100.c # 2004/03/22 16:53:18-05:00 romieu@fr.zoreil.com +76 -61 # 2.6.5-rc2 - epic100 napi # # ChangeSet # 2004/03/22 19:06:56-05:00 romieu@fr.zoreil.com # [netdrvr epic100] minor cleanups # # - extra pci_disable_device() to balance invocation of pci_enable_device() # in epic_init_one() (-> error path + epic_remove_one()); # - lazy return status in epic_init_one(), tsss...; # - memory dedicated to Rx descriptors was not freed after failure of # register_netdev() in epic_init_one(); # - use of epic_pause() in epic_close() offers a small window for a late # interruption just before the final free_irq(). Let's close the window to # avoid two epic_rx() threads racing with each other. # # drivers/net/epic100.c # 2004/03/22 16:53:16-05:00 romieu@fr.zoreil.com +40 -19 # 2.6.5-rc2 - epic100 fixup # diff -Nru a/drivers/net/3c501.c b/drivers/net/3c501.c --- a/drivers/net/3c501.c 2004-06-13 23:56:43 -07:00 +++ b/drivers/net/3c501.c 2004-06-13 23:56:43 -07:00 @@ -225,7 +225,7 @@ * Reserve I/O resource for exclusive use by this driver */ - if (!request_region(ioaddr, EL1_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, EL1_IO_EXTENT, DRV_NAME)) return -ENODEV; /* diff -Nru a/drivers/net/3c503.c b/drivers/net/3c503.c --- a/drivers/net/3c503.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/3c503.c 2004-06-13 23:56:44 -07:00 @@ -147,6 +147,7 @@ release_region(dev->base_addr, EL2_IO_EXTENT); } +#ifndef MODULE struct net_device * __init el2_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -171,6 +172,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /* Probe for the Etherlink II card at I/O port base IOADDR, returning non-zero on success. If found, set the station @@ -182,10 +184,10 @@ static unsigned version_printed; unsigned long vendor_id; - if (!request_region(ioaddr, EL2_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME)) return -EBUSY; - if (!request_region(ioaddr + 0x400, 8, dev->name)) { + if (!request_region(ioaddr + 0x400, 8, DRV_NAME)) { retval = -EBUSY; goto out; } diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c --- a/drivers/net/3c505.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/3c505.c 2004-06-13 23:56:44 -07:00 @@ -1614,6 +1614,7 @@ return err; } +#ifndef MODULE struct net_device * __init elplus_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(elp_device)); @@ -1632,7 +1633,7 @@ return dev; } -#ifdef MODULE +#else static struct net_device *dev_3c505[ELP_MAX_CARDS]; static int io[ELP_MAX_CARDS]; static int irq[ELP_MAX_CARDS]; diff -Nru a/drivers/net/3c507.c b/drivers/net/3c507.c --- a/drivers/net/3c507.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/3c507.c 2004-06-13 23:56:44 -07:00 @@ -373,7 +373,7 @@ init_ID_done = 1; } - if (!request_region(ioaddr, EL16_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, EL16_IO_EXTENT, DRV_NAME)) return -ENODEV; if ((inb(ioaddr) != '*') || (inb(ioaddr + 1) != '3') || @@ -392,7 +392,7 @@ irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; - irqval = request_irq(irq, &el16_interrupt, 0, dev->name, dev); + irqval = request_irq(irq, &el16_interrupt, 0, DRV_NAME, dev); if (irqval) { printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval); retval = -EAGAIN; diff -Nru a/drivers/net/3c523.c b/drivers/net/3c523.c --- a/drivers/net/3c523.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/3c523.c 2004-06-13 23:56:44 -07:00 @@ -445,7 +445,7 @@ slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); continue; } - if (!request_region(dev->base_addr, ELMC_IO_EXTENT, dev->name)) { + if (!request_region(dev->base_addr, ELMC_IO_EXTENT, DRV_NAME)) { slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); continue; } @@ -585,6 +585,7 @@ release_region(dev->base_addr, ELMC_IO_EXTENT); } +#ifndef MODULE struct net_device * __init elmc_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct priv)); @@ -609,6 +610,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /********************************************** * init the chip (elmc-interrupt should be disabled?!) diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c --- a/drivers/net/3c527.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/3c527.c 2004-06-13 23:56:44 -07:00 @@ -435,10 +435,10 @@ * Grab the IRQ */ - err = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); + err = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, DRV_NAME, dev); if (err) { release_region(dev->base_addr, MC32_IO_EXTENT); - printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq); goto err_exit_ports; } diff -Nru a/drivers/net/82596.c b/drivers/net/82596.c --- a/drivers/net/82596.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/82596.c 2004-06-13 23:56:44 -07:00 @@ -63,6 +63,8 @@ static char version[] __initdata = "82596.c $Revision: 1.5 $\n"; +#define DRV_NAME "82596" + /* DEBUG flags */ @@ -1191,7 +1193,7 @@ /* this is easy the ethernet interface can only be at 0x300 */ /* first check nothing is already registered here */ - if (!request_region(ioaddr, I596_TOTAL_SIZE, dev->name)) { + if (!request_region(ioaddr, I596_TOTAL_SIZE, DRV_NAME)) { printk(KERN_ERR "82596: IO address 0x%04x in use\n", ioaddr); err = -EBUSY; goto out; diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/Kconfig 2004-06-13 23:56:44 -07:00 @@ -1287,6 +1287,19 @@ config AMD8111E_NAPI bool "Enable NAPI support" depends on AMD8111_ETH + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. config ADAPTEC_STARFIRE tristate "Adaptec Starfire/DuraLAN support" @@ -1314,6 +1327,11 @@ deployed on potentially unfriendly networks (e.g. in a firewall), then say Y here. + See for more + information. + + If in doubt, say N. + config AC3200 tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)" depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL @@ -1498,10 +1516,6 @@ . The module will be called e100. -config E100_NAPI - bool "Use Rx Polling (NAPI)" - depends on E100 - config LNE390 tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)" depends on NET_PCI && EISA && EXPERIMENTAL @@ -1963,6 +1977,19 @@ config E1000_NAPI bool "Use Rx Polling (NAPI)" depends on E1000 + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. config MYRI_SBUS tristate "MyriCOM Gigabit Ethernet support" @@ -2020,6 +2047,11 @@ To compile this driver as a module, choose M here: the module will be called r8169. This is recommended. +config R8169_NAPI + bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)" + depends on R8169 && EXPERIMENTAL + + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI @@ -2148,6 +2180,19 @@ config IXGB_NAPI bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" depends on IXGB && EXPERIMENTAL + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. config S2IO tristate "S2IO 10Gbe XFrame NIC" @@ -2160,6 +2205,19 @@ config S2IO_NAPI bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" depends on S2IO && EXPERIMENTAL + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + + If in doubt, say N. endmenu diff -Nru a/drivers/net/ac3200.c b/drivers/net/ac3200.c --- a/drivers/net/ac3200.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ac3200.c 2004-06-13 23:56:44 -07:00 @@ -39,6 +39,8 @@ #include "8390.h" +#define DRV_NAME "ac3200" + /* Offsets from the base address. */ #define AC_NIC_BASE 0x00 #define AC_SA_PROM 0x16 /* The station address PROM. */ @@ -130,6 +132,7 @@ iounmap((void *)dev->mem_start); } +#ifndef MODULE struct net_device * __init ac3200_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -154,12 +157,13 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ac_probe1(int ioaddr, struct net_device *dev) { int i, retval; - if (!request_region(ioaddr, AC_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME)) return -EBUSY; if (inb_p(ioaddr + AC_ID_PORT) == 0xff) { @@ -203,7 +207,7 @@ printk(", assigning"); } - retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (retval) { printk (" nothing! Unable to get IRQ %d.\n", dev->irq); goto out1; diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c --- a/drivers/net/acenic.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/acenic.c 2004-06-13 23:56:44 -07:00 @@ -85,6 +85,8 @@ #include +#define DRV_NAME "acenic" + #undef INDEX_DEBUG #ifdef CONFIG_ACENIC_OMIT_TIGON_I @@ -443,6 +445,16 @@ "acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; +static int ace_get_settings(struct net_device *, struct ethtool_cmd *); +static int ace_set_settings(struct net_device *, struct ethtool_cmd *); +static void ace_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); + +static struct ethtool_ops ace_ethtool_ops = { + .get_settings = ace_get_settings, + .set_settings = ace_set_settings, + .get_drvinfo = ace_get_drvinfo, +}; + static int __devinit acenic_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -480,7 +492,7 @@ dev->hard_start_xmit = &ace_start_xmit; dev->get_stats = &ace_get_stats; dev->set_multicast_list = &ace_set_multicast_list; - dev->do_ioctl = &ace_ioctl; + SET_ETHTOOL_OPS(dev, &ace_ethtool_ops); dev->set_mac_address = &ace_set_mac_addr; dev->change_mtu = &ace_change_mtu; @@ -1195,10 +1207,10 @@ } ecode = request_irq(pdev->irq, ace_interrupt, SA_SHIRQ, - dev->name, dev); + DRV_NAME, dev); if (ecode) { printk(KERN_WARNING "%s: Requested IRQ %d is busy\n", - dev->name, pdev->irq); + DRV_NAME, pdev->irq); goto init_error; } else dev->irq = pdev->irq; @@ -2688,146 +2700,136 @@ return 0; } - -static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct ace_private *ap = dev->priv; struct ace_regs *regs = ap->regs; -#ifdef SIOCETHTOOL - struct ethtool_cmd ecmd; - u32 link, speed; + u32 link; - if (cmd != SIOCETHTOOL) - return -EOPNOTSUPP; - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd))) - return -EFAULT; - switch (ecmd.cmd) { - case ETHTOOL_GSET: - ecmd.supported = - (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_FIBRE); - - ecmd.port = PORT_FIBRE; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = 0; - - link = readl(®s->GigLnkState); - if (link & LNK_1000MB) - ecmd.speed = SPEED_1000; - else { - link = readl(®s->FastLnkState); - if (link & LNK_100MB) - ecmd.speed = SPEED_100; - else if (link & LNK_100MB) - ecmd.speed = SPEED_10; - else - ecmd.speed = 0; - } - if (link & LNK_FULL_DUPLEX) - ecmd.duplex = DUPLEX_FULL; + memset(ecmd, 0, sizeof(struct ethtool_cmd)); + ecmd->supported = + (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_FIBRE); + + ecmd->port = PORT_FIBRE; + ecmd->transceiver = XCVR_INTERNAL; + + link = readl(®s->GigLnkState); + if (link & LNK_1000MB) + ecmd->speed = SPEED_1000; + else { + link = readl(®s->FastLnkState); + if (link & LNK_100MB) + ecmd->speed = SPEED_100; + else if (link & LNK_100MB) + ecmd->speed = SPEED_10; else - ecmd.duplex = DUPLEX_HALF; + ecmd->speed = 0; + } + if (link & LNK_FULL_DUPLEX) + ecmd->duplex = DUPLEX_FULL; + else + ecmd->duplex = DUPLEX_HALF; - if (link & LNK_NEGOTIATE) - ecmd.autoneg = AUTONEG_ENABLE; - else - ecmd.autoneg = AUTONEG_DISABLE; + if (link & LNK_NEGOTIATE) + ecmd->autoneg = AUTONEG_ENABLE; + else + ecmd->autoneg = AUTONEG_DISABLE; #if 0 - /* - * Current struct ethtool_cmd is insufficient - */ - ecmd.trace = readl(®s->TuneTrace); + /* + * Current struct ethtool_cmd is insufficient + */ + ecmd->trace = readl(®s->TuneTrace); - ecmd.txcoal = readl(®s->TuneTxCoalTicks); - ecmd.rxcoal = readl(®s->TuneRxCoalTicks); + ecmd->txcoal = readl(®s->TuneTxCoalTicks); + ecmd->rxcoal = readl(®s->TuneRxCoalTicks); #endif - ecmd.maxtxpkt = readl(®s->TuneMaxTxDesc); - ecmd.maxrxpkt = readl(®s->TuneMaxRxDesc); + ecmd->maxtxpkt = readl(®s->TuneMaxTxDesc); + ecmd->maxrxpkt = readl(®s->TuneMaxRxDesc); - if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - - case ETHTOOL_SSET: - link = readl(®s->GigLnkState); - if (link & LNK_1000MB) - speed = SPEED_1000; - else { - link = readl(®s->FastLnkState); - if (link & LNK_100MB) - speed = SPEED_100; - else if (link & LNK_100MB) - speed = SPEED_10; - else - speed = SPEED_100; - } + return 0; +} - link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB | - LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL; - if (!ACE_IS_TIGON_I(ap)) - link |= LNK_TX_FLOW_CTL_Y; - if (ecmd.autoneg == AUTONEG_ENABLE) - link |= LNK_NEGOTIATE; - if (ecmd.speed != speed) { - link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB); - switch (speed) { - case SPEED_1000: - link |= LNK_1000MB; - break; - case SPEED_100: - link |= LNK_100MB; - break; - case SPEED_10: - link |= LNK_10MB; - break; - } +static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct ace_private *ap = dev->priv; + struct ace_regs *regs = ap->regs; + u32 link, speed; + + link = readl(®s->GigLnkState); + if (link & LNK_1000MB) + speed = SPEED_1000; + else { + link = readl(®s->FastLnkState); + if (link & LNK_100MB) + speed = SPEED_100; + else if (link & LNK_100MB) + speed = SPEED_10; + else + speed = SPEED_100; + } + + link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB | + LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL; + if (!ACE_IS_TIGON_I(ap)) + link |= LNK_TX_FLOW_CTL_Y; + if (ecmd->autoneg == AUTONEG_ENABLE) + link |= LNK_NEGOTIATE; + if (ecmd->speed != speed) { + link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB); + switch (speed) { + case SPEED_1000: + link |= LNK_1000MB; + break; + case SPEED_100: + link |= LNK_100MB; + break; + case SPEED_10: + link |= LNK_10MB; + break; } - if (ecmd.duplex == DUPLEX_FULL) - link |= LNK_FULL_DUPLEX; + } - if (link != ap->link) { - struct cmd cmd; - printk(KERN_INFO "%s: Renegotiating link state\n", - dev->name); + if (ecmd->duplex == DUPLEX_FULL) + link |= LNK_FULL_DUPLEX; - ap->link = link; - writel(link, ®s->TuneLink); - if (!ACE_IS_TIGON_I(ap)) - writel(link, ®s->TuneFastLink); - wmb(); + if (link != ap->link) { + struct cmd cmd; + printk(KERN_INFO "%s: Renegotiating link state\n", + dev->name); - cmd.evt = C_LNK_NEGOTIATION; - cmd.code = 0; - cmd.idx = 0; - ace_issue_cmd(regs, &cmd); - } - return 0; + ap->link = link; + writel(link, ®s->TuneLink); + if (!ACE_IS_TIGON_I(ap)) + writel(link, ®s->TuneFastLink); + wmb(); - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strncpy(info.driver, "acenic", sizeof(info.driver) - 1); - sprintf(info.fw_version, "%i.%i.%i", - tigonFwReleaseMajor, tigonFwReleaseMinor, - tigonFwReleaseFix); - strncpy(info.version, version, sizeof(info.version) - 1); - if (ap && ap->pdev) - strcpy(info.bus_info, pci_name(ap->pdev)); - if (copy_to_user(ifr->ifr_data, &info, sizeof(info))) - return -EFAULT; - return 0; - } - default: - break; + cmd.evt = C_LNK_NEGOTIATION; + cmd.code = 0; + cmd.idx = 0; + ace_issue_cmd(regs, &cmd); } - -#endif - - return -EOPNOTSUPP; + return 0; } +static void ace_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct ace_private *ap = dev->priv; + + strlcpy(info->driver, "acenic", sizeof(info->driver)); + snprintf(info->version, sizeof(info->version), "%i.%i.%i", + tigonFwReleaseMajor, tigonFwReleaseMinor, + tigonFwReleaseFix); + + if (ap->pdev) + strlcpy(info->bus_info, pci_name(ap->pdev), + sizeof(info->bus_info)); + +} /* * Set the hardware MAC address. diff -Nru a/drivers/net/acenic.h b/drivers/net/acenic.h --- a/drivers/net/acenic.h 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/acenic.h 2004-06-13 23:56:44 -07:00 @@ -790,7 +790,6 @@ static void ace_dump_trace(struct ace_private *ap); static void ace_set_multicast_list(struct net_device *dev); static int ace_change_mtu(struct net_device *dev, int new_mtu); -static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int ace_set_mac_addr(struct net_device *dev, void *p); static void ace_set_rxtx_parms(struct net_device *dev, int jumbo); static int ace_allocate_descriptors(struct net_device *dev); diff -Nru a/drivers/net/apne.c b/drivers/net/apne.c --- a/drivers/net/apne.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/apne.c 2004-06-13 23:56:44 -07:00 @@ -49,6 +49,8 @@ /* ---- No user-serviceable parts below ---- */ +#define DRV_NAME "apne" + #define NE_BASE (dev->base_addr) #define NE_CMD 0x00 #define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ @@ -168,7 +170,7 @@ return ERR_PTR(-ENODEV); } - if (!request_region(IOBASE, 0x20, dev->name)) { + if (!request_region(IOBASE, 0x20, DRV_NAME)) { free_netdev(dev); return ERR_PTR(-EBUSY); } @@ -310,7 +312,7 @@ dev->base_addr = ioaddr; /* Install the Interrupt handler */ - i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, dev->name, dev); + i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, DRV_NAME, dev); if (i) return i; for(i = 0; i < ETHER_ADDR_LEN; i++) { diff -Nru a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig --- a/drivers/net/arm/Kconfig 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/arm/Kconfig 2004-06-13 23:56:44 -07:00 @@ -45,3 +45,20 @@ number (MTD support is required for this). Otherwise you will need to set a suitable hw address using ifconfig. +config SMC91X + tristate "SMC 91C9x/91C1xxx support" + select CRC32 + select MII + depends on ARM + help + This is a driver for SMC's 91x series of Ethernet chipsets, + including the SMC91C94 and the SMC91C111. Say Y if you want it + compiled into the kernel, and read the file + and the Ethernet-HOWTO, + available from . + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called smc91x. If you want to compile it as a + module, say M here and read as well + as . diff -Nru a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile --- a/drivers/net/arm/Makefile 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/arm/Makefile 2004-06-13 23:56:44 -07:00 @@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_ETHERH) += etherh.o obj-$(CONFIG_ARM_ETHER3) += ether3.o obj-$(CONFIG_ARM_ETHER1) += ether1.o +obj-$(CONFIG_SMC91X) += smc91x.o diff -Nru a/drivers/net/arm/smc91x.c b/drivers/net/arm/smc91x.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/net/arm/smc91x.c 2004-06-13 23:56:44 -07:00 @@ -0,0 +1,2171 @@ +/* + * smc91x.c + * This is a driver for SMSC's 91C9x/91C1xx single-chip Ethernet devices. + * + * Copyright (C) 1996 by Erik Stahlman + * Copyright (C) 2001 Standard Microsystems Corporation + * Developed by Simple Network Magic Corporation + * Copyright (C) 2003 Monta Vista Software, Inc. + * Unified SMC91x driver by Nicolas Pitre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Arguments: + * io = for the base address + * irq = for the IRQ + * nowait = 0 for normal wait states, 1 eliminates additional wait states + * + * original author: + * Erik Stahlman + * + * hardware multicast code: + * Peter Cammaert + * + * contributors: + * Daris A Nevil + * Nicolas Pitre + * Russell King + * + * History: + * 08/20/00 Arnaldo Melo fix kfree(skb) in smc_hardware_send_packet + * 12/15/00 Christian Jullien fix "Warning: kfree_skb on hard IRQ" + * 03/16/01 Daris A Nevil modified smc9194.c for use with LAN91C111 + * 08/22/01 Scott Anderson merge changes from smc9194 to smc91111 + * 08/21/01 Pramod B Bhardwaj added support for RevB of LAN91C111 + * 12/20/01 Jeff Sutherland initial port to Xscale PXA with DMA support + * 04/07/03 Nicolas Pitre unified SMC91x driver, killed irq races, + * more bus abstraction, big cleanup, etc. + * 29/09/03 Russell King - add driver model support + * - ethtool support + * - convert to use generic MII interface + * - add link up/down notification + * - don't try to handle full negotiation in + * smc_phy_configure + * - clean up (and fix stack overrun) in PHY + * MII read/write functions + */ +static const char version[] = + "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre \n"; + +/* Debugging level */ +#ifndef SMC_DEBUG +#define SMC_DEBUG 0 +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "smc91x.h" + +#ifdef CONFIG_ISA +/* + * the LAN91C111 can be at any of the following port addresses. To change, + * for a slightly different card, you can add it to the array. Keep in + * mind that the array must end in zero. + */ +static unsigned int smc_portlist[] __initdata = { + 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, + 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0 +}; + +#ifndef SMC_IOADDR +# define SMC_IOADDR -1 +#endif +static unsigned long io = SMC_IOADDR; +module_param(io, ulong, 0400); +MODULE_PARM_DESC(io, "I/O base address"); + +#ifndef SMC_IRQ +# define SMC_IRQ -1 +#endif +static int irq = SMC_IRQ; +module_param(irq, int, 0400); +MODULE_PARM_DESC(irq, "IRQ number"); + +#endif /* CONFIG_ISA */ + +#ifndef SMC_NOWAIT +# define SMC_NOWAIT 0 +#endif +static int nowait = SMC_NOWAIT; +module_param(nowait, int, 0400); +MODULE_PARM_DESC(nowait, "set to 1 for no wait state"); + +/* + * Transmit timeout, default 5 seconds. + */ +static int watchdog = 5000; +module_param(watchdog, int, 0400); +MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); + +MODULE_LICENSE("GPL"); + +/* + * The internal workings of the driver. If you are changing anything + * here with the SMC stuff, you should have the datasheet and know + * what you are doing. + */ +#define CARDNAME "smc91x" + +/* + * Use power-down feature of the chip + */ +#define POWER_DOWN 1 + +/* + * Wait time for memory to be free. This probably shouldn't be + * tuned that much, as waiting for this means nothing else happens + * in the system + */ +#define MEMORY_WAIT_TIME 16 + +/* + * This selects whether TX packets are sent one by one to the SMC91x internal + * memory and throttled until transmission completes. This may prevent + * RX overruns a litle by keeping much of the memory free for RX packets + * but to the expense of reduced TX throughput and increased IRQ overhead. + * Note this is not a cure for a too slow data bus or too high IRQ latency. + */ +#define THROTTLE_TX_PKTS 0 + +/* + * The MII clock high/low times. 2x this number gives the MII clock period + * in microseconds. (was 50, but this gives 6.4ms for each MII transaction!) + */ +#define MII_DELAY 1 + +/* store this information for the driver.. */ +struct smc_local { + /* + * If I have to wait until memory is available to send a + * packet, I will store the skbuff here, until I get the + * desired memory. Then, I'll send it out and free it. + */ + struct sk_buff *saved_skb; + + /* + * these are things that the kernel wants me to keep, so users + * can find out semi-useless statistics of how well the card is + * performing + */ + struct net_device_stats stats; + + /* version/revision of the SMC91x chip */ + int version; + + /* Contains the current active transmission mode */ + int tcr_cur_mode; + + /* Contains the current active receive mode */ + int rcr_cur_mode; + + /* Contains the current active receive/phy mode */ + int rpc_cur_mode; + int ctl_rfduplx; + int ctl_rspeed; + + u32 msg_enable; + u32 phy_type; + struct mii_if_info mii; + spinlock_t lock; + +#ifdef SMC_USE_PXA_DMA + /* DMA needs the physical address of the chip */ + u_long physaddr; +#endif +}; + +#if SMC_DEBUG > 0 +#define DBG(n, args...) \ + do { \ + if (SMC_DEBUG >= (n)) \ + printk(KERN_DEBUG args); \ + } while (0) + +#define PRINTK(args...) printk(args) +#else +#define DBG(n, args...) do { } while(0) +#define PRINTK(args...) printk(KERN_DEBUG args) +#endif + +#if SMC_DEBUG > 3 +static void PRINT_PKT(u_char *buf, int length) +{ + int i; + int remainder; + int lines; + + lines = length / 16; + remainder = length % 16; + + for (i = 0; i < lines ; i ++) { + int cur; + for (cur = 0; cur < 8; cur++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); + } + for (i = 0; i < remainder/2 ; i++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); +} +#else +#define PRINT_PKT(x...) do { } while(0) +#endif + + +/* this enables an interrupt in the interrupt mask register */ +#define SMC_ENABLE_INT(x) do { \ + unsigned long flags; \ + unsigned char mask; \ + spin_lock_irqsave(&lp->lock, flags); \ + mask = SMC_GET_INT_MASK(); \ + mask |= (x); \ + SMC_SET_INT_MASK(mask); \ + spin_unlock_irqrestore(&lp->lock, flags); \ +} while (0) + +/* this disables an interrupt from the interrupt mask register */ +#define SMC_DISABLE_INT(x) do { \ + unsigned long flags; \ + unsigned char mask; \ + spin_lock_irqsave(&lp->lock, flags); \ + mask = SMC_GET_INT_MASK(); \ + mask &= ~(x); \ + SMC_SET_INT_MASK(mask); \ + spin_unlock_irqrestore(&lp->lock, flags); \ +} while (0) + +/* + * Wait while MMU is busy. This is usually in the order of a few nanosecs + * if at all, but let's avoid deadlocking the system if the hardware + * decides to go south. + */ +#define SMC_WAIT_MMU_BUSY() do { \ + if (unlikely(SMC_GET_MMU_CMD() & MC_BUSY)) { \ + unsigned long timeout = jiffies + 2; \ + while (SMC_GET_MMU_CMD() & MC_BUSY) { \ + if (time_after(jiffies, timeout)) { \ + printk("%s: timeout %s line %d\n", \ + dev->name, __FILE__, __LINE__); \ + break; \ + } \ + cpu_relax(); \ + } \ + } \ +} while (0) + + +/* + * this does a soft reset on the device + */ +static void smc_reset(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int ctl, cfg; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + /* + * This resets the registers mostly to defaults, but doesn't + * affect EEPROM. That seems unnecessary + */ + SMC_SELECT_BANK(0); + SMC_SET_RCR(RCR_SOFTRST); + + /* + * Setup the Configuration Register + * This is necessary because the CONFIG_REG is not affected + * by a soft reset + */ + SMC_SELECT_BANK(1); + + cfg = CONFIG_DEFAULT; + + /* + * Setup for fast accesses if requested. If the card/system + * can't handle it then there will be no recovery except for + * a hard reset or power cycle + */ + if (nowait) + cfg |= CONFIG_NO_WAIT; + + /* + * Release from possible power-down state + * Configuration register is not affected by Soft Reset + */ + cfg |= CONFIG_EPH_POWER_EN; + + SMC_SET_CONFIG(cfg); + + /* this should pause enough for the chip to be happy */ + /* + * elaborate? What does the chip _need_? --jgarzik + * + * This seems to be undocumented, but something the original + * driver(s) have always done. Suspect undocumented timing + * info/determined empirically. --rmk + */ + udelay(1); + + /* Disable transmit and receive functionality */ + SMC_SELECT_BANK(0); + SMC_SET_RCR(RCR_CLEAR); + SMC_SET_TCR(TCR_CLEAR); + + SMC_SELECT_BANK(1); + ctl = SMC_GET_CTL() | CTL_LE_ENABLE; + + /* + * Set the control register to automatically release successfully + * transmitted packets, to make the best use out of our limited + * memory + */ +#if ! THROTTLE_TX_PKTS + ctl |= CTL_AUTO_RELEASE; +#else + ctl &= ~CTL_AUTO_RELEASE; +#endif + SMC_SET_CTL(ctl); + + /* Disable all interrupts */ + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(0); + + /* Reset the MMU */ + SMC_SET_MMU_CMD(MC_RESET); + SMC_WAIT_MMU_BUSY(); +} + +/* + * Enable Interrupts, Receive, and Transmit + */ +static void smc_enable(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + int mask; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + /* see the header file for options in TCR/RCR DEFAULT */ + SMC_SELECT_BANK(0); + SMC_SET_TCR(lp->tcr_cur_mode); + SMC_SET_RCR(lp->rcr_cur_mode); + + /* now, enable interrupts */ + mask = IM_EPH_INT|IM_RX_OVRN_INT|IM_RCV_INT; + if (lp->version >= (CHIP_91100 << 4)) + mask |= IM_MDINT; + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(mask); +} + +/* + * this puts the device in an inactive state + */ +static void smc_shutdown(unsigned long ioaddr) +{ + DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + + /* no more interrupts for me */ + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(0); + + /* and tell the card to stay away from that nasty outside world */ + SMC_SELECT_BANK(0); + SMC_SET_RCR(RCR_CLEAR); + SMC_SET_TCR(TCR_CLEAR); + +#ifdef POWER_DOWN + /* finally, shut the chip down */ + SMC_SELECT_BANK(1); + SMC_SET_CONFIG(SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN); +#endif +} + +/* + * This is the procedure to handle the receipt of a packet. + */ +static inline void smc_rcv(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int packet_number, status, packet_len; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + packet_number = SMC_GET_RXFIFO(); + if (unlikely(packet_number & RXFIFO_REMPTY)) { + PRINTK("%s: smc_rcv with nothing on FIFO.\n", dev->name); + return; + } + + /* read from start of packet */ + SMC_SET_PTR(PTR_READ | PTR_RCV | PTR_AUTOINC); + + /* First two words are status and packet length */ + SMC_GET_PKT_HDR(status, packet_len); + packet_len &= 0x07ff; /* mask off top bits */ + DBG(2, "%s: RX PNR 0x%x STATUS 0x%04x LENGTH 0x%04x (%d)\n", + dev->name, packet_number, status, + packet_len, packet_len); + + if (unlikely(status & RS_ERRORS)) { + lp->stats.rx_errors++; + if (status & RS_ALGNERR) + lp->stats.rx_frame_errors++; + if (status & (RS_TOOSHORT | RS_TOOLONG)) + lp->stats.rx_length_errors++; + if (status & RS_BADCRC) + lp->stats.rx_crc_errors++; + } else { + struct sk_buff *skb; + unsigned char *data; + unsigned int data_len; + + /* set multicast stats */ + if (status & RS_MULTICAST) + lp->stats.multicast++; + + /* + * Actual payload is packet_len - 4 (or 3 if odd byte). + * We want skb_reserve(2) and the final ctrl word + * (2 bytes, possibly containing the payload odd byte). + * Ence packet_len - 4 + 2 + 2. + */ + skb = dev_alloc_skb(packet_len); + if (unlikely(skb == NULL)) { + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", + dev->name); + lp->stats.rx_dropped++; + goto done; + } + + /* Align IP header to 32 bits */ + skb_reserve(skb, 2); + + /* BUG: the LAN91C111 rev A never sets this bit. Force it. */ + if (lp->version == 0x90) + status |= RS_ODDFRAME; + + /* + * If odd length: packet_len - 3, + * otherwise packet_len - 4. + */ + data_len = packet_len - ((status & RS_ODDFRAME) ? 3 : 4); + data = skb_put(skb, data_len); + SMC_PULL_DATA(data, packet_len - 2); + + PRINT_PKT(data, packet_len - 2); + + dev->last_rx = jiffies; + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + lp->stats.rx_bytes += data_len; + } + +done: + SMC_WAIT_MMU_BUSY(); + SMC_SET_MMU_CMD(MC_RELEASE); +} + +/* + * This is called to actually send a packet to the chip. + * Returns non-zero when successful. + */ +static void smc_hardware_send_packet(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + struct sk_buff *skb = lp->saved_skb; + unsigned int packet_no, len; + unsigned char *buf; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + packet_no = SMC_GET_AR(); + if (unlikely(packet_no & AR_FAILED)) { + printk("%s: Memory allocation failed.\n", dev->name); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_fifo_errors++; + dev_kfree_skb_any(skb); + return; + } + + /* point to the beginning of the packet */ + SMC_SET_PN(packet_no); + SMC_SET_PTR(PTR_AUTOINC); + + buf = skb->data; + len = skb->len; + DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n", + dev->name, packet_no, len, len, buf); + PRINT_PKT(buf, len); + + /* + * Send the packet length (+6 for status words, length, and ctl. + * The card will pad to 64 bytes with zeroes if packet is too small. + */ + SMC_PUT_PKT_HDR(0, len + 6); + + /* send the actual data */ + SMC_PUSH_DATA(buf, len & ~1); + + /* Send final ctl word with the last byte if there is one */ + SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG); + + /* and let the chipset deal with it */ + SMC_SET_MMU_CMD(MC_ENQUEUE); + SMC_ACK_INT(IM_TX_EMPTY_INT); + + dev->trans_start = jiffies; + dev_kfree_skb_any(skb); + lp->saved_skb = NULL; + lp->stats.tx_packets++; + lp->stats.tx_bytes += len; +} + +/* + * Since I am not sure if I will have enough room in the chip's ram + * to store the packet, I call this routine which either sends it + * now, or set the card to generates an interrupt when ready + * for the packet. + */ +static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int numPages, poll_count, status, saved_bank; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + BUG_ON(lp->saved_skb != NULL); + lp->saved_skb = skb; + + /* + * The MMU wants the number of pages to be the number of 256 bytes + * 'pages', minus 1 (since a packet can't ever have 0 pages :)) + * + * The 91C111 ignores the size bits, but earlier models don't. + * + * Pkt size for allocating is data length +6 (for additional status + * words, length and ctl) + * + * If odd size then last byte is included in ctl word. + */ + numPages = ((skb->len & ~1) + (6 - 1)) >> 8; + if (unlikely(numPages > 7)) { + printk("%s: Far too big packet error.\n", dev->name); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + + /* now, try to allocate the memory */ + saved_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(2); + SMC_SET_MMU_CMD(MC_ALLOC | numPages); + + /* + * Poll the chip for a short amount of time in case the + * allocation succeeds quickly. + */ + poll_count = MEMORY_WAIT_TIME; + do { + status = SMC_GET_INT(); + if (status & IM_ALLOC_INT) { + SMC_ACK_INT(IM_ALLOC_INT); + break; + } + } while (--poll_count); + + if (!poll_count) { + /* oh well, wait until the chip finds memory later */ + netif_stop_queue(dev); + DBG(2, "%s: TX memory allocation deferred.\n", dev->name); + SMC_ENABLE_INT(IM_ALLOC_INT); + } else { + /* + * Allocation succeeded: push packet to the chip's own memory + * immediately. + * + * If THROTTLE_TX_PKTS is selected that means we don't want + * more than a single TX packet taking up space in the chip's + * internal memory at all time, in which case we stop the + * queue right here until we're notified of TX completion. + * + * Otherwise we're quite happy to feed more TX packets right + * away for better TX throughput, in which case the queue is + * left active. + */ +#if THROTTLE_TX_PKTS + netif_stop_queue(dev); +#endif + smc_hardware_send_packet(dev); + SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT); + } + + SMC_SELECT_BANK(saved_bank); + return 0; +} + +/* + * This handles a TX interrupt, which is only called when: + * - a TX error occurred, or + * - CTL_AUTO_RELEASE is not set and TX of a packet completed. + */ +static void smc_tx(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + unsigned int saved_packet, packet_no, tx_status, pkt_len; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + /* If the TX FIFO is empty then nothing to do */ + packet_no = SMC_GET_TXFIFO(); + if (unlikely(packet_no & TXFIFO_TEMPTY)) { + PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name); + return; + } + + /* select packet to read from */ + saved_packet = SMC_GET_PN(); + SMC_SET_PN(packet_no); + + /* read the first word (status word) from this packet */ + SMC_SET_PTR(PTR_AUTOINC | PTR_READ); + SMC_GET_PKT_HDR(tx_status, pkt_len); + DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n", + dev->name, tx_status, packet_no); + + if (!(tx_status & TS_SUCCESS)) + lp->stats.tx_errors++; + if (tx_status & TS_LOSTCAR) + lp->stats.tx_carrier_errors++; + + SMC_WAIT_MMU_BUSY(); + + if (tx_status & TS_LATCOL) { + PRINTK("%s: late collision occurred on last xmit\n", dev->name); + lp->stats.tx_window_errors++; + /* It's really cheap to requeue the pkt here */ + SMC_SET_MMU_CMD( MC_ENQUEUE ); + } else { + /* kill the packet */ + SMC_SET_MMU_CMD(MC_FREEPKT); + } + + /* Don't restore Packet Number Reg until busy bit is cleared */ + SMC_WAIT_MMU_BUSY(); + SMC_SET_PN(saved_packet); + + /* re-enable transmit */ + SMC_SELECT_BANK(0); + SMC_SET_TCR(lp->tcr_cur_mode); + SMC_SELECT_BANK(2); +} + + +/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ + +static void smc_mii_out(struct net_device *dev, unsigned int val, int bits) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int mii_reg, mask; + + mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO); + mii_reg |= MII_MDOE; + + for (mask = 1 << (bits - 1); mask; mask >>= 1) { + if (val & mask) + mii_reg |= MII_MDO; + else + mii_reg &= ~MII_MDO; + + SMC_SET_MII(mii_reg); + udelay(MII_DELAY); + SMC_SET_MII(mii_reg | MII_MCLK); + udelay(MII_DELAY); + } +} + +static unsigned int smc_mii_in(struct net_device *dev, int bits) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int mii_reg, mask, val; + + mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO); + SMC_SET_MII(mii_reg); + + for (mask = 1 << (bits - 1), val = 0; mask; mask >>= 1) { + if (SMC_GET_MII() & MII_MDI) + val |= mask; + + SMC_SET_MII(mii_reg); + udelay(MII_DELAY); + SMC_SET_MII(mii_reg | MII_MCLK); + udelay(MII_DELAY); + } + + return val; +} + +/* + * Reads a register from the MII Management serial interface + */ +static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int phydata, old_bank; + + /* Save the current bank, and select bank 3 */ + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(3); + + /* Idle - 32 ones */ + smc_mii_out(dev, 0xffffffff, 32); + + /* Start code (01) + read (10) + phyaddr + phyreg */ + smc_mii_out(dev, 6 << 10 | phyaddr << 5 | phyreg, 14); + + /* Turnaround (2bits) + phydata */ + phydata = smc_mii_in(dev, 18); + + /* Return to idle state */ + SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO)); + + /* And select original bank */ + SMC_SELECT_BANK(old_bank); + + DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", + __FUNCTION__, phyaddr, phyreg, phydata); + + return phydata; +} + +/* + * Writes a register to the MII Management serial interface + */ +static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg, + int phydata) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int old_bank; + + /* Save the current bank, and select bank 3 */ + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(3); + + /* Idle - 32 ones */ + smc_mii_out(dev, 0xffffffff, 32); + + /* Start code (01) + write (01) + phyaddr + phyreg + turnaround + phydata */ + smc_mii_out(dev, 5 << 28 | phyaddr << 23 | phyreg << 18 | 2 << 16 | phydata, 32); + + /* Return to idle state */ + SMC_SET_MII(SMC_GET_MII() & ~(MII_MCLK|MII_MDOE|MII_MDO)); + + /* And select original bank */ + SMC_SELECT_BANK(old_bank); + + DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", + __FUNCTION__, phyaddr, phyreg, phydata); +} + +/* + * Finds and reports the PHY address + */ +static void smc_detect_phy(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + int phyaddr; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + lp->phy_type = 0; + + /* + * Scan all 32 PHY addresses if necessary, starting at + * PHY#1 to PHY#31, and then PHY#0 last. + */ + for (phyaddr = 1; phyaddr < 33; ++phyaddr) { + unsigned int id1, id2; + + /* Read the PHY identifiers */ + id1 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID1); + id2 = smc_phy_read(dev, phyaddr & 31, MII_PHYSID2); + + DBG(3, "%s: phy_id1=0x%x, phy_id2=0x%x\n", + dev->name, id1, id2); + + /* Make sure it is a valid identifier */ + if (id1 != 0x0000 && id1 != 0xffff && id1 != 0x8000 && + id2 != 0x0000 && id2 != 0xffff && id2 != 0x8000) { + /* Save the PHY's address */ + lp->mii.phy_id = phyaddr & 31; + lp->phy_type = id1 << 16 | id2; + break; + } + } +} + +/* + * Sets the PHY to a configuration as determined by the user + */ +static int smc_phy_fixed(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int bmcr, cfg1; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + /* Enter Link Disable state */ + cfg1 = smc_phy_read(dev, phyaddr, PHY_CFG1_REG); + cfg1 |= PHY_CFG1_LNKDIS; + smc_phy_write(dev, phyaddr, PHY_CFG1_REG, cfg1); + + /* + * Set our fixed capabilities + * Disable auto-negotiation + */ + bmcr = 0; + + if (lp->ctl_rfduplx) + bmcr |= BMCR_FULLDPLX; + + if (lp->ctl_rspeed == 100) + bmcr |= BMCR_SPEED100; + + /* Write our capabilities to the phy control register */ + smc_phy_write(dev, phyaddr, MII_BMCR, bmcr); + + /* Re-Configure the Receive/Phy Control register */ + SMC_SET_RPC(lp->rpc_cur_mode); + + return 1; +} + +/* + * smc_phy_reset - reset the phy + * @dev: net device + * @phy: phy address + * + * Issue a software reset for the specified PHY and + * wait up to 100ms for the reset to complete. We should + * not access the PHY for 50ms after issuing the reset. + * + * The time to wait appears to be dependent on the PHY. + * + * Must be called with lp->lock locked. + */ +static int smc_phy_reset(struct net_device *dev, int phy) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned int bmcr; + int timeout; + + smc_phy_write(dev, phy, MII_BMCR, BMCR_RESET); + + for (timeout = 2; timeout; timeout--) { + spin_unlock_irq(&lp->lock); + msleep(50); + spin_lock_irq(&lp->lock); + + bmcr = smc_phy_read(dev, phy, MII_BMCR); + if (!(bmcr & BMCR_RESET)) + break; + } + + return bmcr & BMCR_RESET; +} + +/* + * smc_phy_powerdown - powerdown phy + * @dev: net device + * @phy: phy address + * + * Power down the specified PHY + */ +static void smc_phy_powerdown(struct net_device *dev, int phy) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned int bmcr; + + spin_lock_irq(&lp->lock); + bmcr = smc_phy_read(dev, phy, MII_BMCR); + smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN); + spin_unlock_irq(&lp->lock); +} + +/* + * smc_phy_check_media - check the media status and adjust TCR + * @dev: net device + * @init: set true for initialisation + * + * Select duplex mode depending on negotiation state. This + * also updates our carrier state. + */ +static void smc_phy_check_media(struct net_device *dev, int init) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + + if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { + unsigned int old_bank; + + /* duplex state has changed */ + if (lp->mii.full_duplex) { + lp->tcr_cur_mode |= TCR_SWFDUP; + } else { + lp->tcr_cur_mode &= ~TCR_SWFDUP; + } + + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(0); + SMC_SET_TCR(lp->tcr_cur_mode); + SMC_SELECT_BANK(old_bank); + } +} + +/* + * Configures the specified PHY through the MII management interface + * using Autonegotiation. + * Calls smc_phy_fixed() if the user has requested a certain config. + * If RPC ANEG bit is set, the media selection is dependent purely on + * the selection by the MII (either in the MII BMCR reg or the result + * of autonegotiation.) If the RPC ANEG bit is cleared, the selection + * is controlled by the RPC SPEED and RPC DPLX bits. + */ +static void smc_phy_configure(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int my_phy_caps; /* My PHY capabilities */ + int my_ad_caps; /* My Advertised capabilities */ + int status; + + DBG(3, "%s:smc_program_phy()\n", dev->name); + + spin_lock_irq(&lp->lock); + + /* + * We should not be called if phy_type is zero. + */ + if (lp->phy_type == 0) + goto smc_phy_configure_exit; + + if (smc_phy_reset(dev, phyaddr)) { + printk("%s: PHY reset timed out\n", dev->name); + goto smc_phy_configure_exit; + } + + /* + * Enable PHY Interrupts (for register 18) + * Interrupts listed here are disabled + */ + smc_phy_write(dev, phyaddr, PHY_MASK_REG, + PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD | + PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB | + PHY_INT_SPDDET | PHY_INT_DPLXDET); + + /* Configure the Receive/Phy Control register */ + SMC_SELECT_BANK(0); + SMC_SET_RPC(lp->rpc_cur_mode); + + /* If the user requested no auto neg, then go set his request */ + if (lp->mii.force_media) { + smc_phy_fixed(dev); + goto smc_phy_configure_exit; + } + + /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */ + my_phy_caps = smc_phy_read(dev, phyaddr, MII_BMSR); + + if (!(my_phy_caps & BMSR_ANEGCAPABLE)) { + printk(KERN_INFO "Auto negotiation NOT supported\n"); + smc_phy_fixed(dev); + goto smc_phy_configure_exit; + } + + my_ad_caps = ADVERTISE_CSMA; /* I am CSMA capable */ + + if (my_phy_caps & BMSR_100BASE4) + my_ad_caps |= ADVERTISE_100BASE4; + if (my_phy_caps & BMSR_100FULL) + my_ad_caps |= ADVERTISE_100FULL; + if (my_phy_caps & BMSR_100HALF) + my_ad_caps |= ADVERTISE_100HALF; + if (my_phy_caps & BMSR_10FULL) + my_ad_caps |= ADVERTISE_10FULL; + if (my_phy_caps & BMSR_10HALF) + my_ad_caps |= ADVERTISE_10HALF; + + /* Disable capabilities not selected by our user */ + if (lp->ctl_rspeed != 100) + my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF); + + if (!lp->ctl_rfduplx) + my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL); + + /* Update our Auto-Neg Advertisement Register */ + smc_phy_write(dev, phyaddr, MII_ADVERTISE, my_ad_caps); + lp->mii.advertising = my_ad_caps; + + /* + * Read the register back. Without this, it appears that when + * auto-negotiation is restarted, sometimes it isn't ready and + * the link does not come up. + */ + status = smc_phy_read(dev, phyaddr, MII_ADVERTISE); + + DBG(2, "%s: phy caps=%x\n", dev->name, my_phy_caps); + DBG(2, "%s: phy advertised caps=%x\n", dev->name, my_ad_caps); + + /* Restart auto-negotiation process in order to advertise my caps */ + smc_phy_write(dev, phyaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); + + smc_phy_check_media(dev, 1); + +smc_phy_configure_exit: + spin_unlock_irq(&lp->lock); +} + +/* + * smc_phy_interrupt + * + * Purpose: Handle interrupts relating to PHY register 18. This is + * called from the "hard" interrupt handler under our private spinlock. + */ +static void smc_phy_interrupt(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + int phyaddr = lp->mii.phy_id; + int phy18; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + if (lp->phy_type == 0) + return; + + for(;;) { + smc_phy_check_media(dev, 0); + + /* Read PHY Register 18, Status Output */ + phy18 = smc_phy_read(dev, phyaddr, PHY_INT_REG); + if ((phy18 & PHY_INT_INT) == 0) + break; + } +} + +/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/ + +static void smc_10bt_check_media(struct net_device *dev, int init) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int old_carrier, new_carrier, old_bank; + + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(0); + old_carrier = netif_carrier_ok(dev) ? 1 : 0; + new_carrier = SMC_inw(ioaddr, EPH_STATUS_REG) & ES_LINK_OK ? 1 : 0; + + if (init || (old_carrier != new_carrier)) { + if (!new_carrier) { + netif_carrier_off(dev); + } else { + netif_carrier_on(dev); + } + if (netif_msg_link(lp)) + printk(KERN_INFO "%s: link %s\n", dev->name, + new_carrier ? "up" : "down"); + } + SMC_SELECT_BANK(old_bank); +} + +static void smc_eph_interrupt(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int old_bank, ctl; + + smc_10bt_check_media(dev, 0); + + old_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(1); + + ctl = SMC_GET_CTL(); + SMC_SET_CTL(ctl & ~CTL_LE_ENABLE); + SMC_SET_CTL(ctl); + + SMC_SELECT_BANK(old_bank); +} + +/* + * This is the main routine of the driver, to handle the device when + * it needs some attention. + */ +static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + unsigned long ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + int status, mask, timeout, card_stats; + int saved_bank, saved_pointer; + + DBG(3, "%s: %s\n", dev->name, __FUNCTION__); + + saved_bank = SMC_CURRENT_BANK(); + SMC_SELECT_BANK(2); + saved_pointer = SMC_GET_PTR(); + mask = SMC_GET_INT_MASK(); + SMC_SET_INT_MASK(0); + + /* set a timeout value, so I don't stay here forever */ + timeout = 8; + + do { + status = SMC_GET_INT(); + + DBG(2, "%s: IRQ 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n", + dev->name, status, mask, + ({ int meminfo; SMC_SELECT_BANK(0); + meminfo = SMC_GET_MIR(); + SMC_SELECT_BANK(2); meminfo; }), + SMC_GET_FIFO()); + + status &= mask; + if (!status) + break; + + spin_lock(&lp->lock); + + if (status & IM_RCV_INT) { + DBG(3, "%s: RX irq\n", dev->name); + smc_rcv(dev); + } else if (status & IM_TX_INT) { + DBG(3, "%s: TX int\n", dev->name); + smc_tx(dev); + SMC_ACK_INT(IM_TX_INT); +#if THROTTLE_TX_PKTS + netif_wake_queue(dev); +#endif + } else if (status & IM_ALLOC_INT) { + DBG(3, "%s: Allocation irq\n", dev->name); + smc_hardware_send_packet(dev); + mask |= (IM_TX_INT | IM_TX_EMPTY_INT); + mask &= ~IM_ALLOC_INT; +#if ! THROTTLE_TX_PKTS + netif_wake_queue(dev); +#endif + } else if (status & IM_TX_EMPTY_INT) { + DBG(3, "%s: TX empty\n", dev->name); + mask &= ~IM_TX_EMPTY_INT; + + /* update stats */ + SMC_SELECT_BANK(0); + card_stats = SMC_GET_COUNTER(); + SMC_SELECT_BANK(2); + + /* single collisions */ + lp->stats.collisions += card_stats & 0xF; + card_stats >>= 4; + + /* multiple collisions */ + lp->stats.collisions += card_stats & 0xF; + } else if (status & IM_RX_OVRN_INT) { + DBG(1, "%s: RX overrun\n", dev->name); + SMC_ACK_INT(IM_RX_OVRN_INT); + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + } else if (status & IM_EPH_INT) { + smc_eph_interrupt(dev); + } else if (status & IM_MDINT) { + SMC_ACK_INT(IM_MDINT); + smc_phy_interrupt(dev); + } else if (status & IM_ERCV_INT) { + SMC_ACK_INT(IM_ERCV_INT); + PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name); + } + + spin_unlock(&lp->lock); + } while (--timeout); + + /* restore register states */ + SMC_SET_INT_MASK(mask); + SMC_SET_PTR(saved_pointer); + SMC_SELECT_BANK(saved_bank); + + DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); + + /* + * We return IRQ_HANDLED unconditionally here even if there was + * nothing to do. There is a possibility that a packet might + * get enqueued into the chip right after TX_EMPTY_INT is raised + * but just before the CPU acknowledges the IRQ. + * Better take an unneeded IRQ in some occasions than complexifying + * the code for all cases. + */ + return IRQ_HANDLED; +} + +/* Our watchdog timed out. Called by the networking layer */ +static void smc_timeout(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + smc_reset(dev); + smc_enable(dev); + +#if 0 + /* + * Reconfiguring the PHY doesn't seem like a bad idea here, but + * it introduced a problem. Now that this is a timeout routine, + * we are getting called from within an interrupt context. + * smc_phy_configure() calls msleep() which calls + * schedule_timeout() which calls schedule(). When schedule() + * is called from an interrupt context, it prints out + * "Scheduling in interrupt" and then calls BUG(). This is + * obviously not desirable. This was worked around by removing + * the call to smc_phy_configure() here because it didn't seem + * absolutely necessary. Ultimately, if msleep() is + * supposed to be usable from an interrupt context (which it + * looks like it thinks it should handle), it should be fixed. + */ + if (lp->phy_type != 0) + smc_phy_configure(dev); +#endif + + /* clear anything saved */ + if (lp->saved_skb != NULL) { + dev_kfree_skb (lp->saved_skb); + lp->saved_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + } + /* We can accept TX packets again */ + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + +/* + * This sets the internal hardware table to filter out unwanted multicast + * packets before they take up memory. + * + * The SMC chip uses a hash table where the high 6 bits of the CRC of + * address are the offset into the table. If that bit is 1, then the + * multicast packet is accepted. Otherwise, it's dropped silently. + * + * To use the 6 bits as an offset into the table, the high 3 bits are the + * number of the 8 bit register, while the low 3 bits are the bit within + * that register. + * + * This routine is based very heavily on the one provided by Peter Cammaert. + */ +static void +smc_setmulticast(unsigned long ioaddr, int count, struct dev_mc_list *addrs) +{ + int i; + unsigned char multicast_table[8]; + struct dev_mc_list *cur_addr; + + /* table for flipping the order of 3 bits */ + static unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + + /* start with a table of all zeros: reject all */ + memset(multicast_table, 0, sizeof(multicast_table)); + + cur_addr = addrs; + for (i = 0; i < count; i++, cur_addr = cur_addr->next) { + int position; + + /* do we have a pointer here? */ + if (!cur_addr) + break; + /* make sure this is a multicast address - shouldn't this + be a given if we have it here ? */ + if (!(*cur_addr->dmi_addr & 1)) + continue; + + /* only use the low order bits */ + position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + + /* do some messy swapping to put the bit in the right spot */ + multicast_table[invert3[position&7]] |= + (1<>3)&7]); + + } + /* now, the table can be loaded into the chipset */ + SMC_SELECT_BANK(3); + SMC_SET_MCAST(multicast_table); +} + +/* + * This routine will, depending on the values passed to it, + * either make it accept multicast packets, go into + * promiscuous mode (for TCPDUMP and cousins) or accept + * a select set of multicast packets + */ +static void smc_set_multicast_list(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + SMC_SELECT_BANK(0); + if (dev->flags & IFF_PROMISC) { + DBG(2, "%s: RCR_PRMS\n", dev->name); + lp->rcr_cur_mode |= RCR_PRMS; + SMC_SET_RCR(lp->rcr_cur_mode); + } + +/* BUG? I never disable promiscuous mode if multicasting was turned on. + Now, I turn off promiscuous mode, but I don't do anything to multicasting + when promiscuous mode is turned on. +*/ + + /* + * Here, I am setting this to accept all multicast packets. + * I don't need to zero the multicast table, because the flag is + * checked before the table is + */ + else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { + lp->rcr_cur_mode |= RCR_ALMUL; + SMC_SET_RCR(lp->rcr_cur_mode); + DBG(2, "%s: RCR_ALMUL\n", dev->name); + } + + /* + * We just get all multicast packets even if we only want them + * from one source. This will be changed at some future point. + */ + else if (dev->mc_count) { + /* support hardware multicasting */ + + /* be sure I get rid of flags I might have set */ + lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL); + SMC_SET_RCR(lp->rcr_cur_mode); + /* + * NOTE: this has to set the bank, so make sure it is the + * last thing called. The bank is set to zero at the top + */ + smc_setmulticast(ioaddr, dev->mc_count, dev->mc_list); + } else { + DBG(2, "%s: ~(RCR_PRMS|RCR_ALMUL)\n", dev->name); + lp->rcr_cur_mode &= ~(RCR_PRMS | RCR_ALMUL); + SMC_SET_RCR(lp->rcr_cur_mode); + + /* + * since I'm disabling all multicast entirely, I need to + * clear the multicast list + */ + SMC_SELECT_BANK(3); + SMC_CLEAR_MCAST(); + } +} + + +/* + * Open and Initialize the board + * + * Set up everything, reset the card, etc.. + */ +static int +smc_open(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + /* + * Check that the address is valid. If its not, refuse + * to bring the device up. The user must specify an + * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx + */ + if (!is_valid_ether_addr(dev->dev_addr)) { + DBG(2, (KERN_DEBUG "smc_open: no valid ethernet hw addr\n")); + return -EINVAL; + } + + /* clear out all the junk that was put here before... */ + lp->saved_skb = NULL; + + /* Setup the default Register Modes */ + lp->tcr_cur_mode = TCR_DEFAULT; + lp->rcr_cur_mode = RCR_DEFAULT; + lp->rpc_cur_mode = RPC_DEFAULT; + + /* + * If we are not using a MII interface, we need to + * monitor our own carrier signal to detect faults. + */ + if (lp->phy_type == 0) + lp->tcr_cur_mode |= TCR_MON_CSN; + + /* reset the hardware */ + smc_reset(dev); + smc_enable(dev); + + SMC_SELECT_BANK(1); + SMC_SET_MAC_ADDR(dev->dev_addr); + + /* Configure the PHY */ + if (lp->phy_type != 0) + smc_phy_configure(dev); + else { + spin_lock_irq(&lp->lock); + smc_10bt_check_media(dev, 1); + spin_unlock_irq(&lp->lock); + } + + /* + * make sure to initialize the link state with netif_carrier_off() + * somewhere, too --jgarzik + * + * smc_phy_configure() and smc_10bt_check_media() does that. --rmk + */ + netif_start_queue(dev); + return 0; +} + +/* + * smc_close + * + * this makes the board clean up everything that it can + * and not talk to the outside world. Caused by + * an 'ifconfig ethX down' + */ +static int smc_close(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + netif_stop_queue(dev); + netif_carrier_off(dev); + + /* clear everything */ + smc_shutdown(dev->base_addr); + + if (lp->phy_type != 0) + smc_phy_powerdown(dev, lp->mii.phy_id); + + return 0; +} + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ +static struct net_device_stats *smc_query_statistics(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + + DBG(2, "%s: %s\n", dev->name, __FUNCTION__); + + return &lp->stats; +} + +/* + * Ethtool support + */ +static int +smc_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct smc_local *lp = netdev_priv(dev); + int ret; + + cmd->maxtxpkt = 1; + cmd->maxrxpkt = 1; + + if (lp->phy_type != 0) { + spin_lock_irq(&lp->lock); + ret = mii_ethtool_gset(&lp->mii, cmd); + spin_unlock_irq(&lp->lock); + } else { + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_TP | SUPPORTED_AUI; + + if (lp->ctl_rspeed == 10) + cmd->speed = SPEED_10; + else if (lp->ctl_rspeed == 100) + cmd->speed = SPEED_100; + + cmd->autoneg = AUTONEG_DISABLE; + cmd->transceiver = XCVR_INTERNAL; + cmd->port = 0; + cmd->duplex = lp->tcr_cur_mode & TCR_SWFDUP ? DUPLEX_FULL : DUPLEX_HALF; + + ret = 0; + } + + return ret; +} + +static int +smc_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct smc_local *lp = netdev_priv(dev); + int ret; + + if (lp->phy_type != 0) { + spin_lock_irq(&lp->lock); + ret = mii_ethtool_sset(&lp->mii, cmd); + spin_unlock_irq(&lp->lock); + } else { + if (cmd->autoneg != AUTONEG_DISABLE || + cmd->speed != SPEED_10 || + (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) || + (cmd->port != PORT_TP && cmd->port != PORT_AUI)) + return -EINVAL; + +// lp->port = cmd->port; + lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL; + +// if (netif_running(dev)) +// smc_set_port(dev); + + ret = 0; + } + + return ret; +} + +static void +smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strncpy(info->driver, CARDNAME, sizeof(info->driver)); + strncpy(info->version, version, sizeof(info->version)); + strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); +} + +static int smc_ethtool_nwayreset(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + int ret = -EINVAL; + + if (lp->phy_type != 0) { + spin_lock_irq(&lp->lock); + ret = mii_nway_restart(&lp->mii); + spin_unlock_irq(&lp->lock); + } + + return ret; +} + +static u32 smc_ethtool_getmsglevel(struct net_device *dev) +{ + struct smc_local *lp = netdev_priv(dev); + return lp->msg_enable; +} + +static void smc_ethtool_setmsglevel(struct net_device *dev, u32 level) +{ + struct smc_local *lp = netdev_priv(dev); + lp->msg_enable = level; +} + +static struct ethtool_ops smc_ethtool_ops = { + .get_settings = smc_ethtool_getsettings, + .set_settings = smc_ethtool_setsettings, + .get_drvinfo = smc_ethtool_getdrvinfo, + + .get_msglevel = smc_ethtool_getmsglevel, + .set_msglevel = smc_ethtool_setmsglevel, + .nway_reset = smc_ethtool_nwayreset, + .get_link = ethtool_op_get_link, +// .get_eeprom = smc_ethtool_geteeprom, +// .set_eeprom = smc_ethtool_seteeprom, +}; + +/* + * smc_findirq + * + * This routine has a simple purpose -- make the SMC chip generate an + * interrupt, so an auto-detect routine can detect it, and find the IRQ, + */ +/* + * does this still work? + * + * I just deleted auto_irq.c, since it was never built... + * --jgarzik + */ +static int __init smc_findirq(unsigned long ioaddr) +{ + int timeout = 20; + unsigned long cookie; + + DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + + cookie = probe_irq_on(); + + /* + * What I try to do here is trigger an ALLOC_INT. This is done + * by allocating a small chunk of memory, which will give an interrupt + * when done. + */ + /* enable ALLOCation interrupts ONLY */ + SMC_SELECT_BANK(2); + SMC_SET_INT_MASK(IM_ALLOC_INT); + + /* + * Allocate 512 bytes of memory. Note that the chip was just + * reset so all the memory is available + */ + SMC_SET_MMU_CMD(MC_ALLOC | 1); + + /* + * Wait until positive that the interrupt has been generated + */ + do { + int int_status; + udelay(10); + int_status = SMC_GET_INT(); + if (int_status & IM_ALLOC_INT) + break; /* got the interrupt */ + } while (--timeout); + + /* + * there is really nothing that I can do here if timeout fails, + * as autoirq_report will return a 0 anyway, which is what I + * want in this case. Plus, the clean up is needed in both + * cases. + */ + + /* and disable all interrupts again */ + SMC_SET_INT_MASK(0); + + /* and return what I found */ + return probe_irq_off(cookie); +} + +/* + * Function: smc_probe(unsigned long ioaddr) + * + * Purpose: + * Tests to see if a given ioaddr points to an SMC91x chip. + * Returns a 0 on success + * + * Algorithm: + * (1) see if the high byte of BANK_SELECT is 0x33 + * (2) compare the ioaddr with the base register's address + * (3) see if I recognize the chip ID in the appropriate register + * + * Here I do typical initialization tasks. + * + * o Initialize the structure if needed + * o print out my vanity message if not done so already + * o print out what type of hardware is detected + * o print out the ethernet address + * o find the IRQ + * o set up my private data + * o configure the dev structure with my subroutines + * o actually GRAB the irq. + * o GRAB the region + */ +static int __init smc_probe(struct net_device *dev, unsigned long ioaddr) +{ + struct smc_local *lp = netdev_priv(dev); + static int version_printed = 0; + int i, retval; + unsigned int val, revision_register; + const char *version_string; + + DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); + + /* First, see if the high byte is 0x33 */ + val = SMC_CURRENT_BANK(); + DBG(2, "%s: bank signature probe returned 0x%04x\n", CARDNAME, val); + if ((val & 0xFF00) != 0x3300) { + if ((val & 0xFF) == 0x33) { + printk(KERN_WARNING + "%s: Detected possible byte-swapped interface" + " at IOADDR 0x%lx\n", CARDNAME, ioaddr); + } + retval = -ENODEV; + goto err_out; + } + + /* + * The above MIGHT indicate a device, but I need to write to + * further test this. + */ + SMC_SELECT_BANK(0); + val = SMC_CURRENT_BANK(); + if ((val & 0xFF00) != 0x3300) { + retval = -ENODEV; + goto err_out; + } + + /* + * well, we've already written once, so hopefully another + * time won't hurt. This time, I need to switch the bank + * register to bank 1, so I can access the base address + * register + */ + SMC_SELECT_BANK(1); + val = SMC_GET_BASE(); + val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT; + if ((ioaddr & ((PAGE_SIZE-1)<> 4) & 0xF]; + if (!version_string || (revision_register & 0xff00) != 0x3300) { + /* I don't recognize this chip, so... */ + printk("%s: IO 0x%lx: Unrecognized revision register 0x%04x" + ", Contact author.\n", CARDNAME, + ioaddr, revision_register); + + retval = -ENODEV; + goto err_out; + } + + /* At this point I'll assume that the chip is an SMC91x. */ + if (version_printed++ == 0) + printk("%s", version); + + /* fill in some of the fields */ + dev->base_addr = ioaddr; + lp->version = revision_register & 0xff; + + /* Get the MAC address */ + SMC_SELECT_BANK(1); + SMC_GET_MAC_ADDR(dev->dev_addr); + + /* now, reset the chip, and put it into a known state */ + smc_reset(dev); + + /* + * If dev->irq is 0, then the device has to be banged on to see + * what the IRQ is. + * + * This banging doesn't always detect the IRQ, for unknown reasons. + * a workaround is to reset the chip and try again. + * + * Interestingly, the DOS packet driver *SETS* the IRQ on the card to + * be what is requested on the command line. I don't do that, mostly + * because the card that I have uses a non-standard method of accessing + * the IRQs, and because this _should_ work in most configurations. + * + * Specifying an IRQ is done with the assumption that the user knows + * what (s)he is doing. No checking is done!!!! + */ + if (dev->irq < 1) { + int trials; + + trials = 3; + while (trials--) { + dev->irq = smc_findirq(ioaddr); + if (dev->irq) + break; + /* kick the card and try again */ + smc_reset(dev); + } + } + if (dev->irq == 0) { + printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n", + dev->name); + retval = -ENODEV; + goto err_out; + } + dev->irq = irq_canonicalize(dev->irq); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + + dev->open = smc_open; + dev->stop = smc_close; + dev->hard_start_xmit = smc_hard_start_xmit; + dev->tx_timeout = smc_timeout; + dev->watchdog_timeo = msecs_to_jiffies(watchdog); + dev->get_stats = smc_query_statistics; + dev->set_multicast_list = smc_set_multicast_list; + dev->ethtool_ops = &smc_ethtool_ops; + + spin_lock_init(&lp->lock); + lp->mii.phy_id_mask = 0x1f; + lp->mii.reg_num_mask = 0x1f; + lp->mii.force_media = 0; + lp->mii.full_duplex = 0; + lp->mii.dev = dev; + lp->mii.mdio_read = smc_phy_read; + lp->mii.mdio_write = smc_phy_write; + + /* + * Locate the phy, if any. + */ + if (lp->version >= (CHIP_91100 << 4)) + smc_detect_phy(dev); + + /* Set default parameters */ + lp->msg_enable = NETIF_MSG_LINK; + lp->ctl_rfduplx = 0; + lp->ctl_rspeed = 10; + + if (lp->version >= (CHIP_91100 << 4)) { + lp->ctl_rfduplx = 1; + lp->ctl_rspeed = 100; + } + + /* Grab the IRQ */ + retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); + if (retval) + goto err_out; + + set_irq_type(dev->irq, IRQT_RISING); +#ifdef SMC_USE_PXA_DMA + { + int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW, + smc_pxa_dma_irq, NULL); + if (dma >= 0) + dev->dma = dma; + } +#endif + + retval = register_netdev(dev); + if (retval == 0) { + /* now, print out the card info, in a short format.. */ + printk("%s: %s (rev %d) at %#lx IRQ %d", + dev->name, version_string, revision_register & 0x0f, + dev->base_addr, dev->irq); + + if (dev->dma != (unsigned char)-1) + printk(" DMA %d", dev->dma); + + printk("%s%s\n", nowait ? " [nowait]" : "", + THROTTLE_TX_PKTS ? " [throttle_tx]" : ""); + + if (!is_valid_ether_addr(dev->dev_addr)) { + printk("%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", dev->name); + } else { + /* Print the Ethernet address */ + printk("%s: Ethernet addr: ", dev->name); + for (i = 0; i < 5; i++) + printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x\n", dev->dev_addr[5]); + } + + if (lp->phy_type == 0) { + PRINTK("%s: No PHY found\n", dev->name); + } else if ((lp->phy_type & 0xfffffff0) == 0x0016f840) { + PRINTK("%s: PHY LAN83C183 (LAN91C111 Internal)\n", dev->name); + } else if ((lp->phy_type & 0xfffffff0) == 0x02821c50) { + PRINTK("%s: PHY LAN83C180\n", dev->name); + } + } + +err_out: +#ifdef SMC_USE_PXA_DMA + if (retval && dev->dma != (unsigned char)-1) + pxa_free_dma(dev->dma); +#endif + return retval; +} + +static int smc_enable_device(unsigned long attrib_phys) +{ + unsigned long flags; + unsigned char ecor, ecsr; + void *addr; + + /* + * Map the attribute space. This is overkill, but clean. + */ + addr = ioremap(attrib_phys, ATTRIB_SIZE); + if (!addr) + return -ENOMEM; + + /* + * Reset the device. We must disable IRQs around this + * since a reset causes the IRQ line become active. + */ + local_irq_save(flags); + ecor = readb(addr + (ECOR << SMC_IO_SHIFT)) & ~ECOR_RESET; + writeb(ecor | ECOR_RESET, addr + (ECOR << SMC_IO_SHIFT)); + readb(addr + (ECOR << SMC_IO_SHIFT)); + + /* + * Wait 100us for the chip to reset. + */ + udelay(100); + + /* + * The device will ignore all writes to the enable bit while + * reset is asserted, even if the reset bit is cleared in the + * same write. Must clear reset first, then enable the device. + */ + writeb(ecor, addr + (ECOR << SMC_IO_SHIFT)); + writeb(ecor | ECOR_ENABLE, addr + (ECOR << SMC_IO_SHIFT)); + + /* + * Set the appropriate byte/word mode. + */ + ecsr = readb(addr + (ECSR << SMC_IO_SHIFT)) & ~ECSR_IOIS8; +#ifndef SMC_CAN_USE_16BIT + ecsr |= ECSR_IOIS8; +#endif + writeb(ecsr, addr + (ECSR << SMC_IO_SHIFT)); + local_irq_restore(flags); + + iounmap(addr); + + /* + * Wait for the chip to wake up. We could poll the control + * register in the main register space, but that isn't mapped + * yet. We know this is going to take 750us. + */ + msleep(1); + + return 0; +} + +/* + * smc_init(void) + * Input parameters: + * dev->base_addr == 0, try to find all possible locations + * dev->base_addr > 0x1ff, this is the address to check + * dev->base_addr == , return failure code + * + * Output: + * 0 --> there is a device + * anything else, error + */ +static int smc_drv_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *ndev; + struct resource *res, *ext = NULL; + unsigned int *addr; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + goto out; + } + + /* + * Request the regions. + */ + if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) { + ret = -EBUSY; + goto out; + } + + ndev = alloc_etherdev(sizeof(struct smc_local)); + if (!ndev) { + printk("%s: could not allocate device.\n", CARDNAME); + ret = -ENOMEM; + goto release_1; + } + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, dev); + + ndev->dma = (unsigned char)-1; + ndev->irq = platform_get_irq(pdev, 0); + + ext = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (ext) { + if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) { + ret = -EBUSY; + goto release_1; + } + +#if defined(CONFIG_SA1100_ASSABET) + NCR_0 |= NCR_ENET_OSC_EN; +#endif + + ret = smc_enable_device(ext->start); + if (ret) + goto release_both; + } + + addr = ioremap(res->start, SMC_IO_EXTENT); + if (!addr) { + ret = -ENOMEM; + goto release_both; + } + + dev_set_drvdata(dev, ndev); + ret = smc_probe(ndev, (unsigned long)addr); + if (ret != 0) { + dev_set_drvdata(dev, NULL); + iounmap(addr); + release_both: + if (ext) + release_mem_region(ext->start, ATTRIB_SIZE); + free_netdev(ndev); + release_1: + release_mem_region(res->start, SMC_IO_EXTENT); + out: + printk("%s: not found (%d).\n", CARDNAME, ret); + } +#ifdef SMC_USE_PXA_DMA + else { + struct smc_local *lp = netdev_priv(ndev); + lp->physaddr = res->start; + } +#endif + + return ret; +} + +static int smc_drv_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *ndev = dev_get_drvdata(dev); + struct resource *res; + + dev_set_drvdata(dev, NULL); + + unregister_netdev(ndev); + + free_irq(ndev->irq, ndev); + +#ifdef SMC_USE_PXA_DMA + if (ndev->dma != (unsigned char)-1) + pxa_free_dma(ndev->dma); +#endif + iounmap((void *)ndev->base_addr); + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res) + release_mem_region(res->start, ATTRIB_SIZE); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, SMC_IO_EXTENT); + + free_netdev(ndev); + + return 0; +} + +static int smc_drv_suspend(struct device *dev, u32 state, u32 level) +{ + struct net_device *ndev = dev_get_drvdata(dev); + + if (ndev && level == SUSPEND_DISABLE) { + if (netif_running(ndev)) { + netif_device_detach(ndev); + smc_shutdown(ndev->base_addr); + } + } + return 0; +} + +static int smc_drv_resume(struct device *dev, u32 level) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *ndev = dev_get_drvdata(dev); + + if (ndev && level == RESUME_ENABLE) { + struct smc_local *lp = netdev_priv(ndev); + unsigned long ioaddr = ndev->base_addr; + + if (pdev->num_resources == 3) + smc_enable_device(pdev->resource[2].start); + if (netif_running(ndev)) { + smc_reset(ndev); + smc_enable(ndev); + SMC_SELECT_BANK(1); + SMC_SET_MAC_ADDR(ndev->dev_addr); + if (lp->phy_type != 0) + smc_phy_configure(ndev); + netif_device_attach(ndev); + } + } + return 0; +} + +static struct device_driver smc_driver = { + .name = CARDNAME, + .bus = &platform_bus_type, + .probe = smc_drv_probe, + .remove = smc_drv_remove, + .suspend = smc_drv_suspend, + .resume = smc_drv_resume, +}; + +static int __init smc_init(void) +{ +#ifdef MODULE + if (io == -1) + printk(KERN_WARNING + "%s: You shouldn't use auto-probing with insmod!\n", + CARDNAME); +#endif + + return driver_register(&smc_driver); +} + +static void __exit smc_cleanup(void) +{ + driver_unregister(&smc_driver); +} + +module_init(smc_init); +module_exit(smc_cleanup); diff -Nru a/drivers/net/arm/smc91x.h b/drivers/net/arm/smc91x.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/net/arm/smc91x.h 2004-06-13 23:56:44 -07:00 @@ -0,0 +1,829 @@ +/*------------------------------------------------------------------------ + . smc91x.h - macros for SMSC's 91C9x/91C1xx single-chip Ethernet device. + . + . Copyright (C) 1996 by Erik Stahlman + . Copyright (C) 2001 Standard Microsystems Corporation + . Developed by Simple Network Magic Corporation + . Copyright (C) 2003 Monta Vista Software, Inc. + . Unified SMC91x driver by Nicolas Pitre + . + . This program is free software; you can redistribute it and/or modify + . it under the terms of the GNU General Public License as published by + . the Free Software Foundation; either version 2 of the License, or + . (at your option) any later version. + . + . This program is distributed in the hope that it will be useful, + . but WITHOUT ANY WARRANTY; without even the implied warranty of + . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + . GNU General Public License for more details. + . + . You should have received a copy of the GNU General Public License + . along with this program; if not, write to the Free Software + . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + . + . Information contained in this file was obtained from the LAN91C111 + . manual from SMC. To get a copy, if you really want one, you can find + . information under www.smsc.com. + . + . Authors + . Erik Stahlman + . Daris A Nevil + . Nicolas Pitre + . + ---------------------------------------------------------------------------*/ +#ifndef _SMC91X_H_ +#define _SMC91X_H_ + + +/* + * Define your architecture specific bus configuration parameters here. + */ + +#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || \ + defined(CONFIG_SA1100_PFS168) || \ + defined(CONFIG_SA1100_FLEXANET) || \ + defined(CONFIG_SA1100_GRAPHICSMASTER) || \ + defined(CONFIG_ARCH_LUBBOCK) + +/* We can only do 16-bit reads and writes in the static memory space. */ +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +/* The first two address lines aren't connected... */ +#define SMC_IO_SHIFT 2 + +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) + +#elif defined(CONFIG_SA1100_ASSABET) + +#include + +/* We can only do 8-bit reads and writes in the static memory space. */ +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 0 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +/* The first two address lines aren't connected... */ +#define SMC_IO_SHIFT 2 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_insb(a, r, p, l) readsb((a) + (r), p, (l)) +#define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l)) + +#elif defined(CONFIG_ARCH_INNOKOM) || \ + defined(CONFIG_MACH_MAINSTONE) || \ + defined(CONFIG_ARCH_PXA_IDP) || \ + defined(CONFIG_ARCH_RAMSES) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_IO_SHIFT 0 +#define SMC_NOWAIT 1 +#define SMC_USE_PXA_DMA 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +/* We actually can't write halfwords properly if not word aligned */ +static inline void +SMC_outw(u16 val, unsigned long ioaddr, int reg) +{ + if (reg & 2) { + unsigned int v = val << 16; + v |= readl(ioaddr + (reg & ~2)) & 0xffff; + writel(v, ioaddr + (reg & ~2)); + } else { + writew(val, ioaddr + reg); + } +} + +#elif defined(CONFIG_ISA) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 + +#define SMC_inb(a, r) inb((a) + (r)) +#define SMC_inw(a, r) inw((a) + (r)) +#define SMC_outb(v, a, r) outb(v, (a) + (r)) +#define SMC_outw(v, a, r) outw(v, (a) + (r)) +#define SMC_insw(a, r, p, l) insw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) + +#else + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define RPC_LSA_DEFAULT RPC_LED_100_10 +#define RPC_LSB_DEFAULT RPC_LED_TX_RX + +#endif + + +#ifdef SMC_USE_PXA_DMA +/* + * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is + * always happening in irq context so no need to worry about races. TX is + * different and probably not worth it for that reason, and not as critical + * as RX which can overrun memory and lose packets. + */ +#include +#include + +#ifdef SMC_insl +#undef SMC_insl +#define SMC_insl(a, r, p, l) \ + smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l) +static inline void +smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma, + u_char *buf, int len) +{ + dma_addr_t dmabuf; + + /* fallback if no DMA available */ + if (dma == (unsigned char)-1) { + readsl(ioaddr + reg, buf, len); + return; + } + + /* 64 bit alignment is required for memory to memory DMA */ + if ((long)buf & 4) { + *((u32 *)buf)++ = SMC_inl(ioaddr, reg); + len--; + } + + len *= 4; + dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE); + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = dmabuf; + DSADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH4 | (DCMD_LENGTH & len)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; + while (!(DCSR(dma) & DCSR_STOPSTATE)); + DCSR(dma) = 0; + dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE); +} +#endif + +#ifdef SMC_insw +#undef SMC_insw +#define SMC_insw(a, r, p, l) \ + smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l) +static inline void +smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma, + u_char *buf, int len) +{ + dma_addr_t dmabuf; + + /* fallback if no DMA available */ + if (dma == (unsigned char)-1) { + readsw(ioaddr + reg, buf, len); + return; + } + + /* 64 bit alignment is required for memory to memory DMA */ + while ((long)buf & 6) { + *((u16 *)buf)++ = SMC_inw(ioaddr, reg); + len--; + } + + len *= 2; + dmabuf = dma_map_single(NULL, buf, len, PCI_DMA_FROMDEVICE); + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = dmabuf; + DSADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH2 | (DCMD_LENGTH & len)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; + while (!(DCSR(dma) & DCSR_STOPSTATE)); + DCSR(dma) = 0; + dma_unmap_single(NULL, dmabuf, len, PCI_DMA_FROMDEVICE); +} +#endif + +static void +smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs) +{ + DCSR(dma) = 0; +} +#endif /* SMC_USE_PXA_DMA */ + + +/* Because of bank switching, the LAN91x uses only 16 I/O ports */ +#ifndef SMC_IO_SHIFT +#define SMC_IO_SHIFT 0 +#endif +#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT) + + +/* + . Bank Select Register: + . + . yyyy yyyy 0000 00xx + . xx = bank number + . yyyy yyyy = 0x33, for identification purposes. +*/ +#define BANK_SELECT (14 << SMC_IO_SHIFT) + + +// Transmit Control Register +/* BANK 0 */ +#define TCR_REG SMC_REG(0x0000, 0) +#define TCR_ENABLE 0x0001 // When 1 we can transmit +#define TCR_LOOP 0x0002 // Controls output pin LBK +#define TCR_FORCOL 0x0004 // When 1 will force a collision +#define TCR_PAD_EN 0x0080 // When 1 will pad tx frames < 64 bytes w/0 +#define TCR_NOCRC 0x0100 // When 1 will not append CRC to tx frames +#define TCR_MON_CSN 0x0400 // When 1 tx monitors carrier +#define TCR_FDUPLX 0x0800 // When 1 enables full duplex operation +#define TCR_STP_SQET 0x1000 // When 1 stops tx if Signal Quality Error +#define TCR_EPH_LOOP 0x2000 // When 1 enables EPH block loopback +#define TCR_SWFDUP 0x8000 // When 1 enables Switched Full Duplex mode + +#define TCR_CLEAR 0 /* do NOTHING */ +/* the default settings for the TCR register : */ +#define TCR_DEFAULT (TCR_ENABLE | TCR_PAD_EN) + + +// EPH Status Register +/* BANK 0 */ +#define EPH_STATUS_REG SMC_REG(0x0002, 0) +#define ES_TX_SUC 0x0001 // Last TX was successful +#define ES_SNGL_COL 0x0002 // Single collision detected for last tx +#define ES_MUL_COL 0x0004 // Multiple collisions detected for last tx +#define ES_LTX_MULT 0x0008 // Last tx was a multicast +#define ES_16COL 0x0010 // 16 Collisions Reached +#define ES_SQET 0x0020 // Signal Quality Error Test +#define ES_LTXBRD 0x0040 // Last tx was a broadcast +#define ES_TXDEFR 0x0080 // Transmit Deferred +#define ES_LATCOL 0x0200 // Late collision detected on last tx +#define ES_LOSTCARR 0x0400 // Lost Carrier Sense +#define ES_EXC_DEF 0x0800 // Excessive Deferral +#define ES_CTR_ROL 0x1000 // Counter Roll Over indication +#define ES_LINK_OK 0x4000 // Driven by inverted value of nLNK pin +#define ES_TXUNRN 0x8000 // Tx Underrun + + +// Receive Control Register +/* BANK 0 */ +#define RCR_REG SMC_REG(0x0004, 0) +#define RCR_RX_ABORT 0x0001 // Set if a rx frame was aborted +#define RCR_PRMS 0x0002 // Enable promiscuous mode +#define RCR_ALMUL 0x0004 // When set accepts all multicast frames +#define RCR_RXEN 0x0100 // IFF this is set, we can receive packets +#define RCR_STRIP_CRC 0x0200 // When set strips CRC from rx packets +#define RCR_ABORT_ENB 0x0200 // When set will abort rx on collision +#define RCR_FILT_CAR 0x0400 // When set filters leading 12 bit s of carrier +#define RCR_SOFTRST 0x8000 // resets the chip + +/* the normal settings for the RCR register : */ +#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN) +#define RCR_CLEAR 0x0 // set it to a base state + + +// Counter Register +/* BANK 0 */ +#define COUNTER_REG SMC_REG(0x0006, 0) + + +// Memory Information Register +/* BANK 0 */ +#define MIR_REG SMC_REG(0x0008, 0) + + +// Receive/Phy Control Register +/* BANK 0 */ +#define RPC_REG SMC_REG(0x000A, 0) +#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode. +#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode +#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode +#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb +#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb +#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect +#define RPC_LED_RES (0x01) // LED = Reserved +#define RPC_LED_10 (0x02) // LED = 10Mbps link detect +#define RPC_LED_FD (0x03) // LED = Full Duplex Mode +#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred +#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect +#define RPC_LED_TX (0x06) // LED = TX packet occurred +#define RPC_LED_RX (0x07) // LED = RX packet occurred + +#ifndef RPC_LSA_DEFAULT +#define RPC_LSA_DEFAULT RPC_LED_100 +#endif +#ifndef RPC_LSB_DEFAULT +#define RPC_LSB_DEFAULT RPC_LED_FD +#endif + +#define RPC_DEFAULT (RPC_ANEG | (RPC_LSA_DEFAULT << RPC_LSXA_SHFT) | (RPC_LSB_DEFAULT << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) + + +/* Bank 0 0x0C is reserved */ + +// Bank Select Register +/* All Banks */ +#define BSR_REG 0x000E + + +// Configuration Reg +/* BANK 1 */ +#define CONFIG_REG SMC_REG(0x0000, 1) +#define CONFIG_EXT_PHY 0x0200 // 1=external MII, 0=internal Phy +#define CONFIG_GPCNTRL 0x0400 // Inverse value drives pin nCNTRL +#define CONFIG_NO_WAIT 0x1000 // When 1 no extra wait states on ISA bus +#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode. + +// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low +#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN) + + +// Base Address Register +/* BANK 1 */ +#define BASE_REG SMC_REG(0x0002, 1) + + +// Individual Address Registers +/* BANK 1 */ +#define ADDR0_REG SMC_REG(0x0004, 1) +#define ADDR1_REG SMC_REG(0x0006, 1) +#define ADDR2_REG SMC_REG(0x0008, 1) + + +// General Purpose Register +/* BANK 1 */ +#define GP_REG SMC_REG(0x000A, 1) + + +// Control Register +/* BANK 1 */ +#define CTL_REG SMC_REG(0x000C, 1) +#define CTL_RCV_BAD 0x4000 // When 1 bad CRC packets are received +#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically +#define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt +#define CTL_CR_ENABLE 0x0040 // When 1 enables Counter Rollover interrupt +#define CTL_TE_ENABLE 0x0020 // When 1 enables Transmit Error interrupt +#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store +#define CTL_RELOAD 0x0002 // When set reads EEPROM into registers +#define CTL_STORE 0x0001 // When set stores registers into EEPROM + + +// MMU Command Register +/* BANK 2 */ +#define MMU_CMD_REG SMC_REG(0x0000, 2) +#define MC_BUSY 1 // When 1 the last release has not completed +#define MC_NOP (0<<5) // No Op +#define MC_ALLOC (1<<5) // OR with number of 256 byte packets +#define MC_RESET (2<<5) // Reset MMU to initial state +#define MC_REMOVE (3<<5) // Remove the current rx packet +#define MC_RELEASE (4<<5) // Remove and release the current rx packet +#define MC_FREEPKT (5<<5) // Release packet in PNR register +#define MC_ENQUEUE (6<<5) // Enqueue the packet for transmit +#define MC_RSTTXFIFO (7<<5) // Reset the TX FIFOs + + +// Packet Number Register +/* BANK 2 */ +#define PN_REG SMC_REG(0x0002, 2) + + +// Allocation Result Register +/* BANK 2 */ +#define AR_REG SMC_REG(0x0003, 2) +#define AR_FAILED 0x80 // Alocation Failed + + +// TX FIFO Ports Register +/* BANK 2 */ +#define TXFIFO_REG SMC_REG(0x0004, 2) +#define TXFIFO_TEMPTY 0x80 // TX FIFO Empty + +// RX FIFO Ports Register +/* BANK 2 */ +#define RXFIFO_REG SMC_REG(0x0005, 2) +#define RXFIFO_REMPTY 0x80 // RX FIFO Empty + +#define FIFO_REG SMC_REG(0x0004, 2) + +// Pointer Register +/* BANK 2 */ +#define PTR_REG SMC_REG(0x0006, 2) +#define PTR_RCV 0x8000 // 1=Receive area, 0=Transmit area +#define PTR_AUTOINC 0x4000 // Auto increment the pointer on each access +#define PTR_READ 0x2000 // When 1 the operation is a read + + +// Data Register +/* BANK 2 */ +#define DATA_REG SMC_REG(0x0008, 2) + + +// Interrupt Status/Acknowledge Register +/* BANK 2 */ +#define INT_REG SMC_REG(0x000C, 2) + + +// Interrupt Mask Register +/* BANK 2 */ +#define IM_REG SMC_REG(0x000D, 2) +#define IM_MDINT 0x80 // PHY MI Register 18 Interrupt +#define IM_ERCV_INT 0x40 // Early Receive Interrupt +#define IM_EPH_INT 0x20 // Set by Ethernet Protocol Handler section +#define IM_RX_OVRN_INT 0x10 // Set by Receiver Overruns +#define IM_ALLOC_INT 0x08 // Set when allocation request is completed +#define IM_TX_EMPTY_INT 0x04 // Set if the TX FIFO goes empty +#define IM_TX_INT 0x02 // Transmit Interrupt +#define IM_RCV_INT 0x01 // Receive Interrupt + + +// Multicast Table Registers +/* BANK 3 */ +#define MCAST_REG1 SMC_REG(0x0000, 3) +#define MCAST_REG2 SMC_REG(0x0002, 3) +#define MCAST_REG3 SMC_REG(0x0004, 3) +#define MCAST_REG4 SMC_REG(0x0006, 3) + + +// Management Interface Register (MII) +/* BANK 3 */ +#define MII_REG SMC_REG(0x0008, 3) +#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup +#define MII_MDOE 0x0008 // MII Output Enable +#define MII_MCLK 0x0004 // MII Clock, pin MDCLK +#define MII_MDI 0x0002 // MII Input, pin MDI +#define MII_MDO 0x0001 // MII Output, pin MDO + + +// Revision Register +/* BANK 3 */ +/* ( hi: chip id low: rev # ) */ +#define REV_REG SMC_REG(0x000A, 3) + + +// Early RCV Register +/* BANK 3 */ +/* this is NOT on SMC9192 */ +#define ERCV_REG SMC_REG(0x000C, 3) +#define ERCV_RCV_DISCRD 0x0080 // When 1 discards a packet being received +#define ERCV_THRESHOLD 0x001F // ERCV Threshold Mask + + +// External Register +/* BANK 7 */ +#define EXT_REG SMC_REG(0x0000, 7) + + +#define CHIP_9192 3 +#define CHIP_9194 4 +#define CHIP_9195 5 +#define CHIP_9196 6 +#define CHIP_91100 7 +#define CHIP_91100FD 8 +#define CHIP_91111FD 9 + +static const char * chip_ids[ 16 ] = { + NULL, NULL, NULL, + /* 3 */ "SMC91C90/91C92", + /* 4 */ "SMC91C94", + /* 5 */ "SMC91C95", + /* 6 */ "SMC91C96", + /* 7 */ "SMC91C100", + /* 8 */ "SMC91C100FD", + /* 9 */ "SMC91C11xFD", + NULL, NULL, NULL, + NULL, NULL, NULL}; + + +/* + . Transmit status bits +*/ +#define TS_SUCCESS 0x0001 +#define TS_LOSTCAR 0x0400 +#define TS_LATCOL 0x0200 +#define TS_16COL 0x0010 + +/* + . Receive status bits +*/ +#define RS_ALGNERR 0x8000 +#define RS_BRODCAST 0x4000 +#define RS_BADCRC 0x2000 +#define RS_ODDFRAME 0x1000 +#define RS_TOOLONG 0x0800 +#define RS_TOOSHORT 0x0400 +#define RS_MULTICAST 0x0001 +#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) + + +/* + * PHY IDs + * LAN83C183 == LAN91C111 Internal PHY + */ +#define PHY_LAN83C183 0x0016f840 +#define PHY_LAN83C180 0x02821c50 + +/* + * PHY Register Addresses (LAN91C111 Internal PHY) + * + * Generic PHY registers can be found in + * + * These phy registers are specific to our on-board phy. + */ + +// PHY Configuration Register 1 +#define PHY_CFG1_REG 0x10 +#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled +#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled +#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down +#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler +#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable +#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled +#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm) +#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db +#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust +#define PHY_CFG1_TLVL_MASK 0x003C +#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time + + +// PHY Configuration Register 2 +#define PHY_CFG2_REG 0x11 +#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled +#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled +#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt) +#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo + +// PHY Status Output (and Interrupt status) Register +#define PHY_INT_REG 0x12 // Status Output (Interrupt Status) +#define PHY_INT_INT 0x8000 // 1=bits have changed since last read +#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected +#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync +#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx +#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx +#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx +#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected +#define PHY_INT_JAB 0x0100 // 1=Jabber detected +#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode +#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex + +// PHY Interrupt/Status Mask Register +#define PHY_MASK_REG 0x13 // Interrupt Mask +// Uses the same bit definitions as PHY_INT_REG + + +/* + * SMC91C96 ethernet config and status registers. + * These are in the "attribute" space. + */ +#define ECOR 0x8000 +#define ECOR_RESET 0x80 +#define ECOR_LEVEL_IRQ 0x40 +#define ECOR_WR_ATTRIB 0x04 +#define ECOR_ENABLE 0x01 + +#define ECSR 0x8002 +#define ECSR_IOIS8 0x20 +#define ECSR_PWRDWN 0x04 +#define ECSR_INT 0x02 + +#define ATTRIB_SIZE ((64*1024) << SMC_IO_SHIFT) + + +/* + * Macros to abstract register access according to the data bus + * capabilities. Please use those and not the in/out primitives. + * Note: the following macros do *not* select the bank -- this must + * be done separately as needed in the main code. The SMC_REG() macro + * only uses the bank argument for debugging purposes (when enabled). + */ + +#if SMC_DEBUG > 0 +#define SMC_REG(reg, bank) \ + ({ \ + int __b = SMC_CURRENT_BANK(); \ + if (unlikely((__b & ~0xf0) != (0x3300 | bank))) { \ + printk( "%s: bank reg screwed (0x%04x)\n", \ + CARDNAME, __b ); \ + BUG(); \ + } \ + reg<> 8) +#define SMC_GET_TXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF) +#define SMC_GET_RXFIFO() (SMC_inw( ioaddr, TXFIFO_REG ) >> 8) +#define SMC_GET_INT() (SMC_inw( ioaddr, INT_REG ) & 0xFF) +#define SMC_ACK_INT(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff; \ + SMC_outw( __mask | (x), ioaddr, INT_REG ); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_GET_INT_MASK() (SMC_inw( ioaddr, INT_REG ) >> 8) +#define SMC_SET_INT_MASK(x) SMC_outw( (x) << 8, ioaddr, INT_REG ) +#endif + +#define SMC_CURRENT_BANK() SMC_inw( ioaddr, BANK_SELECT ) +#define SMC_SELECT_BANK(x) SMC_outw( x, ioaddr, BANK_SELECT ) +#define SMC_GET_BASE() SMC_inw( ioaddr, BASE_REG ) +#define SMC_SET_BASE(x) SMC_outw( x, ioaddr, BASE_REG ) +#define SMC_GET_CONFIG() SMC_inw( ioaddr, CONFIG_REG ) +#define SMC_SET_CONFIG(x) SMC_outw( x, ioaddr, CONFIG_REG ) +#define SMC_GET_COUNTER() SMC_inw( ioaddr, COUNTER_REG ) +#define SMC_GET_CTL() SMC_inw( ioaddr, CTL_REG ) +#define SMC_SET_CTL(x) SMC_outw( x, ioaddr, CTL_REG ) +#define SMC_GET_MII() SMC_inw( ioaddr, MII_REG ) +#define SMC_SET_MII(x) SMC_outw( x, ioaddr, MII_REG ) +#define SMC_GET_MIR() SMC_inw( ioaddr, MIR_REG ) +#define SMC_SET_MIR(x) SMC_outw( x, ioaddr, MIR_REG ) +#define SMC_GET_MMU_CMD() SMC_inw( ioaddr, MMU_CMD_REG ) +#define SMC_SET_MMU_CMD(x) SMC_outw( x, ioaddr, MMU_CMD_REG ) +#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG ) +#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG ) +#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG ) +#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG ) +#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG ) +#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG ) +#define SMC_GET_RPC() SMC_inw( ioaddr, RPC_REG ) +#define SMC_SET_RPC(x) SMC_outw( x, ioaddr, RPC_REG ) +#define SMC_GET_TCR() SMC_inw( ioaddr, TCR_REG ) +#define SMC_SET_TCR(x) SMC_outw( x, ioaddr, TCR_REG ) + +#ifndef SMC_GET_MAC_ADDR +#define SMC_GET_MAC_ADDR(addr) \ + do { \ + unsigned int __v; \ + __v = SMC_inw( ioaddr, ADDR0_REG ); \ + addr[0] = __v; addr[1] = __v >> 8; \ + __v = SMC_inw( ioaddr, ADDR1_REG ); \ + addr[2] = __v; addr[3] = __v >> 8; \ + __v = SMC_inw( ioaddr, ADDR2_REG ); \ + addr[4] = __v; addr[5] = __v >> 8; \ + } while (0) +#endif + +#define SMC_SET_MAC_ADDR(addr) \ + do { \ + SMC_outw( addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG ); \ + SMC_outw( addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG ); \ + SMC_outw( addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG ); \ + } while (0) + +#define SMC_CLEAR_MCAST() \ + do { \ + SMC_outw( 0, ioaddr, MCAST_REG1 ); \ + SMC_outw( 0, ioaddr, MCAST_REG2 ); \ + SMC_outw( 0, ioaddr, MCAST_REG3 ); \ + SMC_outw( 0, ioaddr, MCAST_REG4 ); \ + } while (0) +#define SMC_SET_MCAST(x) \ + do { \ + unsigned char *mt = (x); \ + SMC_outw( mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1 ); \ + SMC_outw( mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2 ); \ + SMC_outw( mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3 ); \ + SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 ); \ + } while (0) + +#if SMC_CAN_USE_32BIT +/* + * Some setups just can't write 8 or 16 bits reliably when not aligned + * to a 32 bit boundary. I tell you that exists! + * We re-do the ones here that can be easily worked around if they can have + * their low parts written to 0 without adverse effects. + */ +#undef SMC_SELECT_BANK +#define SMC_SELECT_BANK(x) SMC_outl( (x)<<16, ioaddr, 12<> 16; \ + } while (0) +#else +#define SMC_PUT_PKT_HDR(status, length) \ + do { \ + SMC_outw( status, ioaddr, DATA_REG ); \ + SMC_outw( length, ioaddr, DATA_REG ); \ + } while (0) +#define SMC_GET_PKT_HDR(status, length) \ + do { \ + (status) = SMC_inw( ioaddr, DATA_REG ); \ + (length) = SMC_inw( ioaddr, DATA_REG ); \ + } while (0) +#endif + +#if SMC_CAN_USE_32BIT +#define SMC_PUSH_DATA(p, l) \ + do { \ + char *__ptr = (p); \ + int __len = (l); \ + if (__len >= 2 && (long)__ptr & 2) { \ + __len -= 2; \ + SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\ + } \ + SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2); \ + if (__len & 2) { \ + __ptr += (__len & ~3); \ + SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \ + } \ + } while (0) +#define SMC_PULL_DATA(p, l) \ + do { \ + char *__ptr = (p); \ + int __len = (l); \ + if ((long)__ptr & 2) { \ + /* \ + * We want 32bit alignment here. \ + * Since some buses perform a full 32bit \ + * fetch even for 16bit data we can't use \ + * SMC_inw() here. Back both source (on chip \ + * and destination) pointers of 2 bytes. \ + */ \ + (long)__ptr &= ~2; \ + __len += 2; \ + SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \ + } \ + __len += 2; \ + SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \ + } while (0) +#elif SMC_CAN_USE_16BIT +#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 ) +#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 ) +#elif SMC_CAN_USE_8BIT +#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l ) +#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l ) +#endif + +#if ! SMC_CAN_USE_16BIT +#define SMC_outw(x, ioaddr, reg) \ + do { \ + unsigned int __val16 = (x); \ + SMC_outb( __val16, ioaddr, reg ); \ + SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\ + } while (0) +#define SMC_inw(ioaddr, reg) \ + ({ \ + unsigned int __val16; \ + __val16 = SMC_inb( ioaddr, reg ); \ + __val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \ + __val16; \ + }) +#endif + + +#endif /* _SMC91X_H_ */ diff -Nru a/drivers/net/at1700.c b/drivers/net/at1700.c --- a/drivers/net/at1700.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/at1700.c 2004-06-13 23:56:44 -07:00 @@ -65,6 +65,8 @@ static char version[] __initdata = "at1700.c:v1.15 4/7/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; +#define DRV_NAME "at1700" + /* Tunable parameters. */ /* When to switch from the 64-entry multicast filter to Rx-all-multicast. */ @@ -322,11 +324,11 @@ struct net_local *lp = netdev_priv(dev); #ifndef CONFIG_X86_PC9800 - if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME)) return -EBUSY; #else for (i = 0; i < 0x2000; i += 0x0200) { - if (!request_region(ioaddr + i, 2, dev->name)) { + if (!request_region(ioaddr + i, 2, DRV_NAME)) { while (i > 0) { i -= 0x0200; release_region(ioaddr + i, 2); @@ -542,7 +544,7 @@ lp->jumpered = is_fmv18x; lp->mca_slot = slot; /* Snarf the interrupt vector now. */ - ret = request_irq(irq, &net_interrupt, 0, dev->name, dev); + ret = request_irq(irq, &net_interrupt, 0, DRV_NAME, dev); if (ret) { printk (" AT1700 at %#3x is unusable due to a conflict on" "IRQ %d.\n", ioaddr, irq); diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c --- a/drivers/net/cs89x0.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/cs89x0.c 2004-06-13 23:56:44 -07:00 @@ -141,6 +141,8 @@ static char version[] __initdata = "cs89x0.c: v2.4.3-pre1 Russell Nelson , Andrew Morton \n"; +#define DRV_NAME "cs89x0" + /* First, a few definitions that the brave might change. A zero-terminated list of I/O addresses to be probed. Some special flags.. Addr & 1 = Read back the address port, look for signature and reset @@ -261,7 +263,6 @@ } __setup("cs89x0_media=", media_fn); -#endif /* Check for a network adaptor of this type, and return '0' iff one exists. @@ -318,6 +319,7 @@ printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n"); return ERR_PTR(err); } +#endif static int readreg(struct net_device *dev, int portno) @@ -425,9 +427,9 @@ /* Grab the region so we can find another board if autoIRQ fails. */ /* WTF is going on here? */ - if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, dev->name)) { + if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, DRV_NAME)) { printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n", - dev->name, ioaddr, NETCARD_IO_EXTENT); + DRV_NAME, ioaddr, NETCARD_IO_EXTENT); retval = -EBUSY; goto out1; } diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c --- a/drivers/net/defxx.c 2004-06-13 23:56:43 -07:00 +++ b/drivers/net/defxx.c 2004-06-13 23:56:43 -07:00 @@ -219,6 +219,8 @@ static char version[] __devinitdata = "defxx.c:v1.06 2003/08/04 Lawrence V. Stefani and others\n"; +#define DRV_NAME "defxx" + #define DYNAMIC_BUFFERS 1 #define SKBUFF_RX_COPYBREAK 200 @@ -435,9 +437,9 @@ bp = dev->priv; - if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, dev->name)) { + if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, DRV_NAME)) { printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n", - dev->name, PFI_K_CSR_IO_LEN, ioaddr); + DRV_NAME, PFI_K_CSR_IO_LEN, ioaddr); err = -EBUSY; goto err_out; } diff -Nru a/drivers/net/e100.c b/drivers/net/e100.c --- a/drivers/net/e100.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/e100.c 2004-06-13 23:56:44 -07:00 @@ -87,9 +87,8 @@ * cb_to_use is the next CB to use for queuing a command; cb_to_clean * is the next CB to check for completion; cb_to_send is the first * CB to start on in case of a previous failure to resume. CB clean - * up happens in interrupt context in response to a CU interrupt, or - * in dev->poll in the case where NAPI is enabled. cbs_avail keeps - * track of number of free CB resources available. + * up happens in interrupt context in response to a CU interrupt. + * cbs_avail keeps track of number of free CB resources available. * * Hardware padding of short packets to minimum packet size is * enabled. 82557 pads with 7Eh, while the later controllers pad @@ -112,9 +111,8 @@ * replacement RFDs cannot be allocated, or the RU goes non-active, * the RU must be restarted. Frame arrival generates an interrupt, * and Rx indication and re-allocation happen in the same context, - * therefore no locking is required. If NAPI is enabled, this work - * happens in dev->poll. A software-generated interrupt is gen- - * erated from the watchdog to recover from a failed allocation + * therefore no locking is required. A software-generated interrupt + * is generated from the watchdog to recover from a failed allocation * senario where all Rx resources have been indicated and none re- * placed. * @@ -126,8 +124,6 @@ * supported. Tx Scatter/Gather is not supported. Jumbo Frames is * not supported (hardware limitation). * - * NAPI support is enabled with CONFIG_E100_NAPI. - * * MagicPacket(tm) WoL support is enabled/disabled via ethtool. * * Thanks to JC (jchapman@katalix.com) for helping with @@ -158,7 +154,7 @@ #define DRV_NAME "e100" -#define DRV_VERSION "3.0.18" +#define DRV_VERSION "3.0.22-NAPI" #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 1999-2004 Intel Corporation" #define PFX DRV_NAME ": " @@ -1463,11 +1459,7 @@ nic->net_stats.rx_packets++; nic->net_stats.rx_bytes += actual_size; nic->netdev->last_rx = jiffies; -#ifdef CONFIG_E100_NAPI netif_receive_skb(skb); -#else - netif_rx(skb); -#endif if(work_done) (*work_done)++; } @@ -1562,20 +1554,12 @@ if(stat_ack & stat_ack_rnr) nic->ru_running = 0; -#ifdef CONFIG_E100_NAPI e100_disable_irq(nic); netif_rx_schedule(netdev); -#else - if(stat_ack & stat_ack_rx) - e100_rx_clean(nic, NULL, 0); - if(stat_ack & stat_ack_tx) - e100_tx_clean(nic); -#endif return IRQ_HANDLED; } -#ifdef CONFIG_E100_NAPI static int e100_poll(struct net_device *netdev, int *budget) { struct nic *nic = netdev_priv(netdev); @@ -1598,7 +1582,6 @@ return 1; } -#endif #ifdef CONFIG_NET_POLL_CONTROLLER static void e100_netpoll(struct net_device *netdev) @@ -2135,10 +2118,8 @@ SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); netdev->tx_timeout = e100_tx_timeout; netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; -#ifdef CONFIG_E100_NAPI netdev->poll = e100_poll; netdev->weight = E100_NAPI_WEIGHT; -#endif #ifdef CONFIG_NET_POLL_CONTROLLER netdev->poll_controller = e100_netpoll; #endif diff -Nru a/drivers/net/e2100.c b/drivers/net/e2100.c --- a/drivers/net/e2100.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/e2100.c 2004-06-13 23:56:44 -07:00 @@ -51,6 +51,8 @@ #include "8390.h" +#define DRV_NAME "e2100" + static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0}; /* Offsets from the base_addr. @@ -144,6 +146,7 @@ release_region(dev->base_addr, E21_IO_EXTENT); } +#ifndef MODULE struct net_device * __init e2100_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -168,6 +171,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init e21_probe1(struct net_device *dev, int ioaddr) { @@ -175,7 +179,7 @@ unsigned char *station_addr = dev->dev_addr; static unsigned version_printed; - if (!request_region(ioaddr, E21_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, E21_IO_EXTENT, DRV_NAME)) return -EBUSY; /* First check the station address for the Ctron prefix. */ diff -Nru a/drivers/net/eepro.c b/drivers/net/eepro.c --- a/drivers/net/eepro.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/eepro.c 2004-06-13 23:56:44 -07:00 @@ -151,6 +151,8 @@ #include #include +#define DRV_NAME "eepro" + #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) ) /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */ #define SLOW_DOWN inb(0x80) @@ -577,6 +579,7 @@ return -ENODEV; } +#ifndef MODULE struct net_device * __init eepro_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct eepro_local)); @@ -603,6 +606,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static void __init printEEPROMInfo(short ioaddr, struct net_device *dev) { @@ -745,7 +749,7 @@ int ioaddr = dev->base_addr; /* Grab the region so we can find another board if autoIRQ fails. */ - if (!request_region(ioaddr, EEPRO_IO_EXTENT, dev->name)) { + if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { if (!autoprobe) printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n", ioaddr); diff -Nru a/drivers/net/eexpress.c b/drivers/net/eexpress.c --- a/drivers/net/eexpress.c 2004-06-13 23:56:43 -07:00 +++ b/drivers/net/eexpress.c 2004-06-13 23:56:43 -07:00 @@ -423,6 +423,7 @@ return -ENODEV; } +#ifndef MODULE struct net_device * __init express_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); @@ -443,6 +444,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /* * open and initialize the adapter, ready for use diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c --- a/drivers/net/epic100.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/epic100.c 2004-06-13 23:56:44 -07:00 @@ -80,8 +80,6 @@ These may be modified when a driver module is loaded.*/ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 32; /* Used to pass the full-duplex flag, etc. */ #define MAX_UNITS 8 /* More are supported, limit only on options */ @@ -99,9 +97,9 @@ Making the Tx ring too large decreases the effectiveness of channel bonding and packet priority. There are no ill effects from too-large receive rings. */ -#define TX_RING_SIZE 16 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ -#define RX_RING_SIZE 32 +#define TX_RING_SIZE 256 +#define TX_QUEUE_LEN 240 /* Limit ring entries actually used. */ +#define RX_RING_SIZE 256 #define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct epic_tx_desc) #define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct epic_rx_desc) @@ -158,12 +156,10 @@ MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); -MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)"); -MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt"); MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex"); MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)"); @@ -295,6 +291,12 @@ StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80, }; +#define EpicRemoved 0xffffffff /* Chip failed or removed (CardBus) */ + +#define EpicNapiEvent (TxEmpty | TxDone | \ + RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull) +#define EpicNormalEvent (0x0000ffff & ~EpicNapiEvent) + static u16 media2miictl[16] = { 0, 0x0C00, 0x0C00, 0x2000, 0x0100, 0x2100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -333,9 +335,12 @@ /* Ring pointers. */ spinlock_t lock; /* Group with Tx control cache line. */ + spinlock_t napi_lock; + unsigned int reschedule_in_poll; unsigned int cur_tx, dirty_tx; unsigned int cur_rx, dirty_rx; + u32 irq_mask; unsigned int rx_buf_sz; /* Based on MTU+slack. */ struct pci_dev *pci_dev; /* PCI bus location. */ @@ -362,7 +367,8 @@ static void epic_tx_timeout(struct net_device *dev); static void epic_init_ring(struct net_device *dev); static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int epic_rx(struct net_device *dev); +static int epic_rx(struct net_device *dev, int budget); +static int epic_poll(struct net_device *dev, int *budget); static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; @@ -381,7 +387,7 @@ int irq; struct net_device *dev; struct epic_private *ep; - int i, option = 0, duplex = 0; + int i, ret, option = 0, duplex = 0; void *ring_space; dma_addr_t ring_dma; @@ -395,29 +401,33 @@ card_idx++; - i = pci_enable_device(pdev); - if (i) - return i; + ret = pci_enable_device(pdev); + if (ret) + goto out; irq = pdev->irq; if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) { printk (KERN_ERR "card %d: no PCI region space\n", card_idx); - return -ENODEV; + ret = -ENODEV; + goto err_out_disable; } pci_set_master(pdev); + ret = pci_request_regions(pdev, DRV_NAME); + if (ret < 0) + goto err_out_disable; + + ret = -ENOMEM; + dev = alloc_etherdev(sizeof (*ep)); if (!dev) { printk (KERN_ERR "card %d: no memory for eth device\n", card_idx); - return -ENOMEM; + goto err_out_free_res; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_request_regions(pdev, DRV_NAME)) - goto err_out_free_netdev; - #ifdef USE_IO_OPS ioaddr = pci_resource_start (pdev, 0); #else @@ -425,7 +435,7 @@ ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1)); if (!ioaddr) { printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx); - goto err_out_free_res; + goto err_out_free_netdev; } #endif @@ -462,7 +472,9 @@ dev->base_addr = ioaddr; dev->irq = irq; - spin_lock_init (&ep->lock); + spin_lock_init(&ep->lock); + spin_lock_init(&ep->napi_lock); + ep->reschedule_in_poll = 0; /* Bring the chip out of low-power mode. */ outl(0x4200, ioaddr + GENCTL); @@ -492,6 +504,9 @@ ep->pci_dev = pdev; ep->chip_id = chip_idx; ep->chip_flags = pci_id_tbl[chip_idx].drv_flags; + ep->irq_mask = + (ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) + | CntFull | TxUnderrun | EpicNapiEvent; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but @@ -546,10 +561,12 @@ dev->ethtool_ops = &netdev_ethtool_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->tx_timeout = &epic_tx_timeout; + dev->poll = epic_poll; + dev->weight = 64; - i = register_netdev(dev); - if (i) - goto err_out_unmap_tx; + ret = register_netdev(dev); + if (ret < 0) + goto err_out_unmap_rx; printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq); @@ -557,19 +574,24 @@ printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x.\n", dev->dev_addr[i]); - return 0; +out: + return ret; +err_out_unmap_rx: + pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma); err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma); err_out_iounmap: #ifndef USE_IO_OPS iounmap(ioaddr); -err_out_free_res: -#endif - pci_release_regions(pdev); err_out_free_netdev: +#endif free_netdev(dev); - return -ENODEV; +err_out_free_res: + pci_release_regions(pdev); +err_out_disable: + pci_disable_device(pdev); + goto out; } /* Serial EEPROM section. */ @@ -595,6 +617,38 @@ #define EE_READ256_CMD (6 << 8) #define EE_ERASE_CMD (7 << 6) +static void epic_disable_int(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(0x00000000, ioaddr + INTMASK); +} + +static inline void __epic_pci_commit(long ioaddr) +{ +#ifndef USE_IO_OPS + inl(ioaddr + INTMASK); +#endif +} + +static inline void epic_napi_irq_off(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK); + __epic_pci_commit(ioaddr); +} + +static inline void epic_napi_irq_on(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + /* No need to commit possible posted write */ + outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK); +} + static int __devinit read_eeprom(long ioaddr, int location) { int i; @@ -755,9 +809,8 @@ /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); if (debug > 1) printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x " @@ -798,7 +851,7 @@ } /* Remove the packets on the Rx queue. */ - epic_rx(dev); + epic_rx(dev, RX_RING_SIZE); } static void epic_restart(struct net_device *dev) @@ -844,9 +897,9 @@ /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); + printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x" " interrupt %4.4x.\n", dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL), @@ -932,7 +985,6 @@ int i; ep->tx_full = 0; - ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; ep->dirty_tx = ep->cur_tx = 0; ep->cur_rx = ep->dirty_rx = 0; ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); @@ -1032,6 +1084,76 @@ return 0; } +static void epic_tx_error(struct net_device *dev, struct epic_private *ep, + int status) +{ + struct net_device_stats *stats = &ep->stats; + +#ifndef final_version + /* There was an major error, log it. */ + if (debug > 1) + printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", + dev->name, status); +#endif + stats->tx_errors++; + if (status & 0x1050) + stats->tx_aborted_errors++; + if (status & 0x0008) + stats->tx_carrier_errors++; + if (status & 0x0040) + stats->tx_window_errors++; + if (status & 0x0010) + stats->tx_fifo_errors++; +} + +static void epic_tx(struct net_device *dev, struct epic_private *ep) +{ + unsigned int dirty_tx, cur_tx; + + /* + * Note: if this lock becomes a problem we can narrow the locked + * region at the cost of occasionally grabbing the lock more times. + */ + cur_tx = ep->cur_tx; + for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) { + struct sk_buff *skb; + int entry = dirty_tx % TX_RING_SIZE; + int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + + if (txstatus & DescOwn) + break; /* It still hasn't been Txed */ + + if (likely(txstatus & 0x0001)) { + ep->stats.collisions += (txstatus >> 8) & 15; + ep->stats.tx_packets++; + ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; + } else + epic_tx_error(dev, ep, txstatus); + + /* Free the original skb. */ + skb = ep->tx_skbuff[entry]; + pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + ep->tx_skbuff[entry] = 0; + } + +#ifndef final_version + if (cur_tx - dirty_tx > TX_RING_SIZE) { + printk(KERN_WARNING + "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, cur_tx, ep->tx_full); + dirty_tx += TX_RING_SIZE; + } +#endif + ep->dirty_tx = dirty_tx; + if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { + /* The ring is no longer full, allow new TX entries. */ + ep->tx_full = 0; + netif_wake_queue(dev); + } +} + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -1039,135 +1161,71 @@ struct net_device *dev = dev_instance; struct epic_private *ep = dev->priv; long ioaddr = dev->base_addr; - int status, boguscnt = max_interrupt_work; unsigned int handled = 0; + int status; - do { - status = inl(ioaddr + INTSTAT); - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(status & 0x00007fff, ioaddr + INTSTAT); - - if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " - "intstat=%#8.8x.\n", - dev->name, status, (int)inl(ioaddr + INTSTAT)); - - if ((status & IntrSummary) == 0) - break; - handled = 1; + status = inl(ioaddr + INTSTAT); + /* Acknowledge all of the current interrupt sources ASAP. */ + outl(status & EpicNormalEvent, ioaddr + INTSTAT); - if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow)) - epic_rx(dev); + if (debug > 4) { + printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " + "intstat=%#8.8x.\n", dev->name, status, + (int)inl(ioaddr + INTSTAT)); + } - if (status & (TxEmpty | TxDone)) { - unsigned int dirty_tx, cur_tx; + if ((status & IntrSummary) == 0) + goto out; - /* Note: if this lock becomes a problem we can narrow the locked - region at the cost of occasionally grabbing the lock more - times. */ - spin_lock(&ep->lock); - cur_tx = ep->cur_tx; - dirty_tx = ep->dirty_tx; - for (; cur_tx - dirty_tx > 0; dirty_tx++) { - struct sk_buff *skb; - int entry = dirty_tx % TX_RING_SIZE; - int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + handled = 1; - if (txstatus & DescOwn) - break; /* It still hasn't been Txed */ + if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) { + spin_lock(&ep->napi_lock); + if (netif_rx_schedule_prep(dev)) { + epic_napi_irq_off(dev, ep); + __netif_rx_schedule(dev); + } else + ep->reschedule_in_poll++; + spin_unlock(&ep->napi_lock); + } + status &= ~EpicNapiEvent; - if ( ! (txstatus & 0x0001)) { - /* There was an major error, log it. */ -#ifndef final_version - if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); -#endif - ep->stats.tx_errors++; - if (txstatus & 0x1050) ep->stats.tx_aborted_errors++; - if (txstatus & 0x0008) ep->stats.tx_carrier_errors++; - if (txstatus & 0x0040) ep->stats.tx_window_errors++; - if (txstatus & 0x0010) ep->stats.tx_fifo_errors++; - } else { - ep->stats.collisions += (txstatus >> 8) & 15; - ep->stats.tx_packets++; - ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; - } - - /* Free the original skb. */ - skb = ep->tx_skbuff[entry]; - pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); - ep->tx_skbuff[entry] = 0; - } + /* Check uncommon events all at once. */ + if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) { + if (status == EpicRemoved) + goto out; -#ifndef final_version - if (cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, cur_tx, ep->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - ep->dirty_tx = dirty_tx; - if (ep->tx_full - && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { - /* The ring is no longer full, allow new TX entries. */ - ep->tx_full = 0; - spin_unlock(&ep->lock); - netif_wake_queue(dev); - } else - spin_unlock(&ep->lock); - } + /* Always update the error counts to avoid overhead later. */ + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - /* Check uncommon events all at once. */ - if (status & (CntFull | TxUnderrun | RxOverflow | RxFull | - PCIBusErr170 | PCIBusErr175)) { - if (status == 0xffffffff) /* Chip failed or removed (CardBus). */ - break; - /* Always update the error counts to avoid overhead later. */ - ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); - ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); - ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - - if (status & TxUnderrun) { /* Tx FIFO underflow. */ - ep->stats.tx_fifo_errors++; - outl(ep->tx_threshold += 128, ioaddr + TxThresh); - /* Restart the transmit process. */ - outl(RestartTx, ioaddr + COMMAND); - } - if (status & RxOverflow) { /* Missed a Rx frame. */ - ep->stats.rx_errors++; - } - if (status & (RxOverflow | RxFull)) - outw(RxQueued, ioaddr + COMMAND); - if (status & PCIBusErr170) { - printk(KERN_ERR "%s: PCI Bus Error! EPIC status %4.4x.\n", - dev->name, status); - epic_pause(dev); - epic_restart(dev); - } - /* Clear all error sources. */ - outl(status & 0x7f18, ioaddr + INTSTAT); + if (status & TxUnderrun) { /* Tx FIFO underflow. */ + ep->stats.tx_fifo_errors++; + outl(ep->tx_threshold += 128, ioaddr + TxThresh); + /* Restart the transmit process. */ + outl(RestartTx, ioaddr + COMMAND); } - if (--boguscnt < 0) { - printk(KERN_ERR "%s: Too much work at interrupt, " - "IntrStatus=0x%8.8x.\n", - dev->name, status); - /* Clear all interrupt sources. */ - outl(0x0001ffff, ioaddr + INTSTAT); - break; + if (status & PCIBusErr170) { + printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n", + dev->name, status); + epic_pause(dev); + epic_restart(dev); } - } while (1); + /* Clear all error sources. */ + outl(status & 0x7f18, ioaddr + INTSTAT); + } - if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, status); +out: + if (debug > 3) { + printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n", + dev->name, status); + } return IRQ_RETVAL(handled); } -static int epic_rx(struct net_device *dev) +static int epic_rx(struct net_device *dev, int budget) { struct epic_private *ep = dev->priv; int entry = ep->cur_rx % RX_RING_SIZE; @@ -1177,6 +1235,10 @@ if (debug > 4) printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry, ep->rx_ring[entry].rxstatus); + + if (rx_work_limit > budget) + rx_work_limit = budget; + /* If we own the next entry, it's a new packet. Send it up. */ while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) { int status = le32_to_cpu(ep->rx_ring[entry].rxstatus); @@ -1218,13 +1280,8 @@ ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); -#if 1 /* HAS_IP_COPYSUM */ eth_copy_and_sum(skb, ep->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), ep->rx_skbuff[entry]->tail, - pkt_len); -#endif pci_dma_sync_single_for_device(ep->pci_dev, ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, @@ -1237,7 +1294,7 @@ ep->rx_skbuff[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + netif_receive_skb(skb); dev->last_rx = jiffies; ep->stats.rx_packets++; ep->stats.rx_bytes += pkt_len; @@ -1265,6 +1322,65 @@ return work_done; } +static void epic_rx_err(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + int status; + + status = inl(ioaddr + INTSTAT); + + if (status == EpicRemoved) + return; + if (status & RxOverflow) /* Missed a Rx frame. */ + ep->stats.rx_errors++; + if (status & (RxOverflow | RxFull)) + outw(RxQueued, ioaddr + COMMAND); +} + +static int epic_poll(struct net_device *dev, int *budget) +{ + struct epic_private *ep = dev->priv; + int work_done, orig_budget; + long ioaddr = dev->base_addr; + + orig_budget = (*budget > dev->quota) ? dev->quota : *budget; + +rx_action: + + epic_tx(dev, ep); + + work_done = epic_rx(dev, *budget); + + epic_rx_err(dev, ep); + + *budget -= work_done; + dev->quota -= work_done; + + if (netif_running(dev) && (work_done < orig_budget)) { + unsigned long flags; + int more; + + /* A bit baroque but it avoids a (space hungry) spin_unlock */ + + spin_lock_irqsave(&ep->napi_lock, flags); + + more = ep->reschedule_in_poll; + if (!more) { + __netif_rx_complete(dev); + outl(EpicNapiEvent, ioaddr + INTSTAT); + epic_napi_irq_on(dev, ep); + } else + ep->reschedule_in_poll--; + + spin_unlock_irqrestore(&ep->napi_lock, flags); + + if (more) + goto rx_action; + } + + return (work_done >= orig_budget); +} + static int epic_close(struct net_device *dev) { long ioaddr = dev->base_addr; @@ -1279,9 +1395,13 @@ dev->name, (int)inl(ioaddr + INTSTAT)); del_timer_sync(&ep->timer); - epic_pause(dev); + + epic_disable_int(dev, ep); + free_irq(dev->irq, dev); + epic_pause(dev); + /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { skb = ep->rx_skbuff[i]; @@ -1502,6 +1622,7 @@ #endif pci_release_regions(pdev); free_netdev(dev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); /* pci_power_off(pdev, -1); */ } diff -Nru a/drivers/net/es3210.c b/drivers/net/es3210.c --- a/drivers/net/es3210.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/es3210.c 2004-06-13 23:56:44 -07:00 @@ -161,6 +161,7 @@ release_region(dev->base_addr, ES_IO_EXTENT); } +#ifndef MODULE struct net_device * __init es_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -185,6 +186,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init es_probe1(struct net_device *dev, int ioaddr) { diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c --- a/drivers/net/eth16i.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/eth16i.c 2004-06-13 23:56:44 -07:00 @@ -458,6 +458,7 @@ return -ENODEV; } +#ifndef MODULE struct net_device * __init eth16i_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct eth16i_local)); @@ -483,6 +484,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init eth16i_probe1(struct net_device *dev, int ioaddr) { @@ -491,7 +493,7 @@ int retval; /* Let's grab the region */ - if (!request_region(ioaddr, ETH16I_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, ETH16I_IO_EXTENT, cardname)) return -EBUSY; /* @@ -538,9 +540,9 @@ /* Try to obtain interrupt vector */ - if ((retval = request_irq(dev->irq, (void *)ð16i_interrupt, 0, dev->name, dev))) { - printk(KERN_WARNING "%s: %s at %#3x, but is unusable due conflicting IRQ %d.\n", - dev->name, cardname, ioaddr, dev->irq); + if ((retval = request_irq(dev->irq, (void *)ð16i_interrupt, 0, cardname, dev))) { + printk(KERN_WARNING "%s at %#3x, but is unusable due to conflicting IRQ %d.\n", + cardname, ioaddr, dev->irq); goto out; } diff -Nru a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c --- a/drivers/net/ewrk3.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ewrk3.c 2004-06-13 23:56:44 -07:00 @@ -341,6 +341,7 @@ mdelay(1);\ } +#ifndef MODULE struct net_device * __init ewrk3_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct ewrk3_private)); @@ -364,6 +365,7 @@ return ERR_PTR(err); } +#endif static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq) { @@ -1269,7 +1271,7 @@ for (; (i < maxSlots) && (dev != NULL); iobase += EWRK3_IOP_INC, i++) { - if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name)) { + if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME)) { if (DevicePresent(iobase) == 0) { int irq = dev->irq; ret = ewrk3_hw_init(dev, iobase); @@ -1310,7 +1312,7 @@ for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { if (EISA_signature(name, EISA_ID) == 0) { - if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name) && + if (request_region(iobase, EWRK3_TOTAL_SIZE, DRV_NAME) && DevicePresent(iobase) == 0) { int irq = dev->irq; ret = ewrk3_hw_init(dev, iobase); diff -Nru a/drivers/net/fealnx.c b/drivers/net/fealnx.c --- a/drivers/net/fealnx.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/fealnx.c 2004-06-13 23:56:44 -07:00 @@ -858,11 +858,16 @@ { struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; + int i; writel(0x00000001, ioaddr + BCR); /* Reset */ if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) return -EAGAIN; + + for (i = 0; i < 3; i++) + writew(((unsigned short*)dev->dev_addr)[i], + ioaddr + PAR0 + i*2); init_ring(dev); diff -Nru a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c --- a/drivers/net/fmv18x.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/fmv18x.c 2004-06-13 23:56:44 -07:00 @@ -57,6 +57,8 @@ #include #include +#define DRV_NAME "fmv18x" + static unsigned fmv18x_probe_list[] __initdata = { 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0 }; @@ -192,7 +194,7 @@ That means we have to be careful with the register values we probe for. */ - if (!request_region(ioaddr, FMV18X_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, FMV18X_IO_EXTENT, DRV_NAME)) return -EBUSY; dev->irq = irq; @@ -224,7 +226,7 @@ } /* Snarf the interrupt vector now. */ - retval = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, &net_interrupt, 0, DRV_NAME, dev); if (retval) { printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on" "IRQ %d.\n", ioaddr, dev->irq); diff -Nru a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c --- a/drivers/net/forcedeth.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/forcedeth.c 2004-06-13 23:56:44 -07:00 @@ -81,6 +81,7 @@ * superfluous timer interrupts from the nic. */ #define FORCEDETH_VERSION "0.25" +#define DRV_NAME "forcedeth" #include #include @@ -1424,7 +1425,7 @@ pci_set_master(pci_dev); - err = pci_request_regions(pci_dev, dev->name); + err = pci_request_regions(pci_dev, DRV_NAME); if (err < 0) goto out_disable; diff -Nru a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c --- a/drivers/net/hp-plus.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/hp-plus.c 2004-06-13 23:56:44 -07:00 @@ -37,6 +37,8 @@ #include "8390.h" +#define DRV_NAME "hp-plus" + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int hpplus_portlist[] __initdata = {0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}; @@ -142,6 +144,7 @@ release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); } +#ifndef MODULE struct net_device * __init hp_plus_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -166,6 +169,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /* Do the interesting part of the probe at a single address. */ static int __init hpp_probe1(struct net_device *dev, int ioaddr) @@ -176,7 +180,7 @@ int mem_start; static unsigned version_printed; - if (!request_region(ioaddr, HP_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME)) return -EBUSY; /* Check for the HP+ signature, 50 48 0x 53. */ diff -Nru a/drivers/net/hp.c b/drivers/net/hp.c --- a/drivers/net/hp.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/hp.c 2004-06-13 23:56:44 -07:00 @@ -37,6 +37,8 @@ #include "8390.h" +#define DRV_NAME "hp" + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int hppclan_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0}; @@ -106,6 +108,7 @@ release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); } +#ifndef MODULE struct net_device * __init hp_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -130,6 +133,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init hp_probe1(struct net_device *dev, int ioaddr) { @@ -137,7 +141,7 @@ const char *name; static unsigned version_printed; - if (!request_region(ioaddr, HP_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME)) return -EBUSY; /* Check for the HP physical address, 08 00 09 xx xx xx. */ @@ -182,7 +186,7 @@ outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE); outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE); if (irq == probe_irq_off(cookie) /* It's a good IRQ line! */ - && request_irq (irq, ei_interrupt, 0, dev->name, dev) == 0) { + && request_irq (irq, ei_interrupt, 0, DRV_NAME, dev) == 0) { printk(" selecting IRQ %d.\n", irq); dev->irq = *irqp; break; @@ -197,7 +201,7 @@ } else { if (dev->irq == 2) dev->irq = 9; - if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { + if ((retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) { printk (" unable to get IRQ %d.\n", dev->irq); goto out; } diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c --- a/drivers/net/hp100.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/hp100.c 2004-06-13 23:56:44 -07:00 @@ -386,6 +386,7 @@ } +#ifndef MODULE struct net_device * __init hp100_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); @@ -420,6 +421,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init hp100_probe1(struct net_device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev) diff -Nru a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c --- a/drivers/net/ibmlana.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ibmlana.c 2004-06-13 23:56:44 -07:00 @@ -98,6 +98,8 @@ #undef DEBUG +#define DRV_NAME "ibmlana" + /* ------------------------------------------------------------------------ * global static data - not more since we can handle multiple boards and * have to pack all state info into the device struct! @@ -952,8 +954,8 @@ printk(KERN_INFO "%s: IBM LAN Adapter/A found in slot %d\n", dev->name, slot + 1); /* try to obtain I/O range */ - if (!request_region(iobase, IBM_LANA_IORANGE, dev->name)) { - printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", dev->name, iobase); + if (!request_region(iobase, IBM_LANA_IORANGE, DRV_NAME)) { + printk(KERN_ERR "%s: cannot allocate I/O range at %#x!\n", DRV_NAME, iobase); startslot = slot + 1; return -EBUSY; } diff -Nru a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c --- a/drivers/net/isa-skeleton.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/isa-skeleton.c 2004-06-13 23:56:44 -07:00 @@ -161,6 +161,7 @@ release_region(dev->base_addr, NETCARD_IO_EXTENT); } +#ifndef MODULE struct net_device * __init netcard_probe(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); @@ -185,6 +186,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif /* * This is the real probe routine. Linux has a history of friendly device diff -Nru a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c --- a/drivers/net/jazzsonic.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/jazzsonic.c 2004-06-13 23:56:44 -07:00 @@ -37,6 +37,8 @@ #include #include +#define DRV_NAME "jazzsonic" + #define SREGS_PAD(n) u16 n; #include "sonic.h" @@ -151,7 +153,7 @@ int err = -ENODEV; int i; - if (!request_region(base_addr, 0x100, dev->name)) + if (!request_region(base_addr, 0x100, DRV_NAME)) return -EBUSY; /* * get the Silicon Revision ID. If this is one of the known diff -Nru a/drivers/net/lance.c b/drivers/net/lance.c --- a/drivers/net/lance.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/lance.c 2004-06-13 23:56:44 -07:00 @@ -432,6 +432,7 @@ return -ENODEV; } +#ifndef MODULE struct net_device * __init lance_probe(int unit) { struct net_device *dev = alloc_etherdev(0); @@ -456,6 +457,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options) { diff -Nru a/drivers/net/lne390.c b/drivers/net/lne390.c --- a/drivers/net/lne390.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/lne390.c 2004-06-13 23:56:44 -07:00 @@ -49,6 +49,8 @@ #include "8390.h" +#define DRV_NAME "lne390" + static int lne390_probe1(struct net_device *dev, int ioaddr); static int lne390_open(struct net_device *dev); @@ -112,7 +114,7 @@ SET_MODULE_OWNER(dev); if (ioaddr > 0x1ff) { /* Check a single specified location. */ - if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME)) return -EBUSY; ret = lne390_probe1(dev, ioaddr); if (ret) @@ -131,7 +133,7 @@ /* EISA spec allows for up to 16 slots, but 8 is typical. */ for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME)) continue; if (lne390_probe1(dev, ioaddr) == 0) return 0; @@ -151,6 +153,7 @@ iounmap((void *)dev->mem_start); } +#ifndef MODULE struct net_device * __init lne390_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -175,6 +178,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init lne390_probe1(struct net_device *dev, int ioaddr) { @@ -228,7 +232,7 @@ } printk(" IRQ %d,", dev->irq); - if ((ret = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { + if ((ret = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) { printk (" unable to get IRQ %d.\n", dev->irq); return ret; } diff -Nru a/drivers/net/lp486e.c b/drivers/net/lp486e.c --- a/drivers/net/lp486e.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/lp486e.c 2004-06-13 23:56:44 -07:00 @@ -75,6 +75,8 @@ #include #include +#define DRV_NAME "lp486e" + /* debug print flags */ #define LOG_SRCDST 0x80000000 #define LOG_STATINT 0x40000000 @@ -970,7 +972,7 @@ return -ENODEV; probed++; - if (!request_region(IOADDR, LP486E_TOTAL_SIZE, dev->name)) { + if (!request_region(IOADDR, LP486E_TOTAL_SIZE, DRV_NAME)) { printk(KERN_ERR "lp486e: IO address 0x%x in use\n", IOADDR); return -EBUSY; } diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c --- a/drivers/net/natsemi.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/natsemi.c 2004-06-13 23:56:44 -07:00 @@ -766,7 +766,7 @@ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - i = pci_request_regions(pdev, dev->name); + i = pci_request_regions(pdev, DRV_NAME); if (i) goto err_pci_request_regions; @@ -1798,14 +1798,9 @@ np->rx_dma[entry], buflen, PCI_DMA_FROMDEVICE); -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - np->rx_skbuff[entry]->tail, pkt_len); -#endif pci_dma_sync_single_for_device(np->pci_dev, np->rx_dma[entry], buflen, diff -Nru a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c --- a/drivers/net/ne-h8300.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ne-h8300.c 2004-06-13 23:56:44 -07:00 @@ -34,6 +34,8 @@ #include "8390.h" +#define DRV_NAME "ne-h8300" + /* Some defines that people can play with if so inclined. */ /* Do we perform extra sanity checks on stuff ? */ @@ -156,6 +158,7 @@ release_region(dev->base_addr, NE_IO_EXTENT); } +#ifndef MODULE struct net_device * __init ne_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -187,6 +190,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ne_probe1(struct net_device *dev, int ioaddr) { @@ -200,7 +204,7 @@ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); unsigned char bus_width; - if (!request_region(ioaddr, NE_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME)) return -EBUSY; reg0 = inb_p(ioaddr); diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c --- a/drivers/net/ne.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ne.c 2004-06-13 23:56:44 -07:00 @@ -55,6 +55,8 @@ #include "8390.h" +#define DRV_NAME "ne" + /* Some defines that people can play with if so inclined. */ /* Do we support clones that don't adhere to 14,15 of the SAprom ? */ @@ -203,6 +205,7 @@ release_region(dev->base_addr, NE_IO_EXTENT); } +#ifndef MODULE struct net_device * __init ne_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -227,6 +230,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ne_probe_isapnp(struct net_device *dev) { @@ -284,7 +288,7 @@ int reg0, ret; static unsigned version_printed; - if (!request_region(ioaddr, NE_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME)) return -EBUSY; reg0 = inb_p(ioaddr); diff -Nru a/drivers/net/ne2.c b/drivers/net/ne2.c --- a/drivers/net/ne2.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ne2.c 2004-06-13 23:56:44 -07:00 @@ -82,6 +82,8 @@ #include "8390.h" +#define DRV_NAME "ne2" + /* Some defines that people can play with if so inclined. */ /* Do we perform extra sanity checks on stuff ? */ @@ -284,6 +286,7 @@ release_region(dev->base_addr, NE_IO_EXTENT); } +#ifndef MODULE struct net_device * __init ne2_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -308,6 +311,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int ne2_procinfo(char *buf, int slot, struct net_device *dev) { @@ -368,7 +372,7 @@ irq = irqs[(POS & 0x60)>>5]; } - if (!request_region(base_addr, NE_IO_EXTENT, dev->name)) + if (!request_region(base_addr, NE_IO_EXTENT, DRV_NAME)) return -EBUSY; #ifdef DEBUG @@ -470,7 +474,7 @@ /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (retval) { printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, retval); diff -Nru a/drivers/net/ne2k_cbus.c b/drivers/net/ne2k_cbus.c --- a/drivers/net/ne2k_cbus.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ne2k_cbus.c 2004-06-13 23:56:44 -07:00 @@ -37,6 +37,8 @@ #include "8390.h" +#define DRV_NAME "ne2k_cbus" + /* Some defines that people can play with if so inclined. */ /* Do we support clones that don't adhere to 14,15 of the SAprom ? */ @@ -187,6 +189,7 @@ ne2k_cbus_destroy(dev); } +#ifndef MODULE struct net_device * __init ne_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -211,6 +214,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq) { @@ -263,7 +267,7 @@ for (rlist = hw->regionlist; rlist->range; rlist++) if (!request_region(ioaddr + rlist->start, - rlist->range, dev->name)) { + rlist->range, DRV_NAME)) { ret = -EBUSY; goto err_out; } diff -Nru a/drivers/net/ne3210.c b/drivers/net/ne3210.c --- a/drivers/net/ne3210.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ne3210.c 2004-06-13 23:56:44 -07:00 @@ -45,6 +45,8 @@ #include "8390.h" +#define DRV_NAME "ne3210" + static int ne3210_open(struct net_device *dev); static int ne3210_close(struct net_device *dev); @@ -111,13 +113,13 @@ device->driver_data = dev; ioaddr = edev->base_addr; - if (!request_region(ioaddr, NE3210_IO_EXTENT, dev->name)) { + if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) { retval = -EBUSY; goto out; } if (!request_region(ioaddr + NE3210_CFG1, - NE3210_CFG_EXTENT, dev->name)) { + NE3210_CFG_EXTENT, DRV_NAME)) { retval = -EBUSY; goto out1; } @@ -140,7 +142,7 @@ dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07]; printk(".\nne3210.c: using IRQ %d, ", dev->irq); - retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (retval) { printk (" unable to get IRQ %d.\n", dev->irq); goto out2; @@ -163,7 +165,7 @@ } } - if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, dev->name)) { + if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, DRV_NAME)) { printk ("ne3210.c: Unable to request shared memory at physical address %#lx\n", phys_mem); goto out3; diff -Nru a/drivers/net/ni52.c b/drivers/net/ni52.c --- a/drivers/net/ni52.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ni52.c 2004-06-13 23:56:44 -07:00 @@ -124,6 +124,8 @@ #include "ni52.h" +#define DRV_NAME "ni52" + #define DEBUG /* debug on */ #define SYSBUSVAL 1 /* 8 Bit */ @@ -424,7 +426,7 @@ dev->mem_start = memstart; dev->mem_end = memend; - if (!request_region(ioaddr, NI52_TOTAL_SIZE, dev->name)) + if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME)) return -EBUSY; if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c --- a/drivers/net/ns83820.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/ns83820.c 2004-06-13 23:56:44 -07:00 @@ -113,6 +113,8 @@ #include #include +#define DRV_NAME "ns83820" + /* Global parameters. See MODULE_PARM near the bottom. */ static int ihr = 2; static int reset_phy = 0; @@ -1851,7 +1853,7 @@ 0); err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ, - ndev->name, ndev); + DRV_NAME, ndev); if (err) { printk(KERN_INFO "ns83820: unable to register irq %d\n", pci_dev->irq); diff -Nru a/drivers/net/oaknet.c b/drivers/net/oaknet.c --- a/drivers/net/oaknet.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/oaknet.c 2004-06-13 23:56:44 -07:00 @@ -164,7 +164,7 @@ ret = -EAGAIN; if (request_irq(dev->irq, ei_interrupt, 0, name, dev)) { printk("%s: unable to request interrupt %d.\n", - dev->name, dev->irq); + name, dev->irq); goto out_region; } diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c --- a/drivers/net/r8169.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/r8169.c 2004-06-13 23:56:44 -07:00 @@ -7,7 +7,7 @@ Feb 4 2002 - created initially by ShuChen . May 20 2002 - Add link status force-mode and TBI mode support. ========================================================================= - 1. The media can be forced in 5 modes. + 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. Command: 'insmod r8169 media = SET_MEDIA' Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex. @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,14 @@ #define dprintk(fmt, args...) do {} while (0) #endif /* RTL8169_DEBUG */ +#ifdef CONFIG_R8169_NAPI +#define rtl8169_rx_skb netif_receive_skb +#define rtl8169_rx_quota(count, quota) min(count, quota) +#else +#define rtl8169_rx_skb netif_rx +#define rtl8169_rx_quota(count, quota) count +#endif + /* media options */ #define MAX_UNITS 8 static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; @@ -90,15 +99,16 @@ #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ +#define R8169_NAPI_WEIGHT 64 #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 64 /* Number of Rx descriptor registers */ +#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ #define RX_BUF_SIZE 1536 /* Rx Buffer size */ #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) #define RTL_MIN_IO_SIZE 0x80 #define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (HZ) +#define RTL8169_PHY_TIMEOUT (10*HZ) /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) @@ -194,7 +204,7 @@ SWInt = 0x0100, TxDescUnavail = 0x80, RxFIFOOver = 0x40, - RxUnderrun = 0x20, + LinkChg = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, @@ -233,6 +243,14 @@ TxInterFrameGapShift = 24, TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ + /* TBICSR p.28 */ + TBIReset = 0x80000000, + TBILoopback = 0x40000000, + TBINwEnable = 0x20000000, + TBINwRestart = 0x10000000, + TBILinkOk = 0x02000000, + TBINwComplete = 0x01000000, + /* CPlusCmd p.31 */ RxVlan = (1 << 6), RxChkSum = (1 << 5), @@ -306,10 +324,10 @@ }; struct rtl8169_private { - void *mmio_addr; /* memory map physical address */ + void *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ + spinlock_t lock; /* spin lock flag */ int chipset; int mac_version; int phy_version; @@ -317,15 +335,23 @@ u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ u32 dirty_rx; u32 dirty_tx; - struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ - struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ + struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */ + struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffers */ struct timer_list timer; - unsigned long phy_link_down_cnt; u16 cp_cmd; + u16 intr_mask; + int phy_auto_nego_reg; + int phy_1000_ctrl_reg; + + int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); + void (*get_settings)(struct net_device *, struct ethtool_cmd *); + void (*phy_reset_enable)(void *); + unsigned int (*phy_reset_pending)(void *); + unsigned int (*link_ok)(void *); }; MODULE_AUTHOR("Realtek"); @@ -344,9 +370,14 @@ static void rtl8169_set_rx_mode(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev); static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev); +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget); +#endif static const u16 rtl8169_intr_mask = - RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; + LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; +static const u16 rtl8169_napi_event = + RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr; static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); @@ -364,11 +395,9 @@ for (i = 2000; i > 0; i--) { // Check if the RTL8169 has completed writing to the specified MII register - if (!(RTL_R32(PHYAR) & 0x80000000)) { + if (!(RTL_R32(PHYAR) & 0x80000000)) break; - } else { - udelay(100); - } + udelay(100); } } @@ -390,18 +419,264 @@ return value; } +static unsigned int rtl8169_tbi_reset_pending(void *ioaddr) +{ + return RTL_R32(TBICSR) & TBIReset; +} + +static unsigned int rtl8169_xmii_reset_pending(void *ioaddr) +{ + return mdio_read(ioaddr, 0) & 0x8000; +} + +static unsigned int rtl8169_tbi_link_ok(void *ioaddr) +{ + return RTL_R32(TBICSR) & TBILinkOk; +} + +static unsigned int rtl8169_xmii_link_ok(void *ioaddr) +{ + return RTL_R8(PHYstatus) & LinkStatus; +} + +static void rtl8169_tbi_reset_enable(void *ioaddr) +{ + RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); +} + +static void rtl8169_xmii_reset_enable(void *ioaddr) +{ + unsigned int val; + + val = (mdio_read(ioaddr, PHY_CTRL_REG) | 0x8000) & 0xffff; + mdio_write(ioaddr, PHY_CTRL_REG, val); +} + +static void rtl8169_check_link_status(struct net_device *dev, + struct rtl8169_private *tp, void *ioaddr) +{ + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + if (tp->link_ok(ioaddr)) { + netif_carrier_on(dev); + printk(KERN_INFO PFX "%s: link up\n", dev->name); + } else + netif_carrier_off(dev); + spin_unlock_irqrestore(&tp->lock, flags); +} + +static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) +{ + struct { + u16 speed; + u8 duplex; + u8 autoneg; + u8 media; + } link_settings[] = { + { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half }, + { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full }, + { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half }, + { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full }, + { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full }, + /* Make TBI happy */ + { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff } + }, *p; + unsigned char option; + + option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff; + + if ((option != 0xff) && !idx) + printk(KERN_WARNING PFX "media option is deprecated.\n"); + + for (p = link_settings; p->media != 0xff; p++) { + if (p->media == option) + break; + } + *autoneg = p->autoneg; + *speed = p->speed; + *duplex = p->duplex; +} + static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); strcpy(info->driver, RTL8169_DRIVER_NAME); strcpy(info->version, RTL8169_VERSION ); strcpy(info->bus_info, pci_name(tp->pci_dev)); } +static int rtl8169_set_speed_tbi(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + int ret = 0; + u32 reg; + + reg = RTL_R32(TBICSR); + if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && + (duplex == DUPLEX_FULL)) { + RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); + } else if (autoneg == AUTONEG_ENABLE) + RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); + else { + printk(KERN_WARNING PFX + "%s: incorrect speed setting refused in TBI mode\n", + dev->name); + ret = -EOPNOTSUPP; + } + + return ret; +} + +static int rtl8169_set_speed_xmii(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + int auto_nego, giga_ctrl; + + auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); + auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full); + giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG); + giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null); + + if (autoneg == AUTONEG_ENABLE) { + auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full); + giga_ctrl |= PHY_Cap_1000_Full; + } else { + if (speed == SPEED_10) + auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full; + else if (speed == SPEED_100) + auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full; + else if (speed == SPEED_1000) + giga_ctrl |= PHY_Cap_1000_Full; + + if (duplex == DUPLEX_HALF) + auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); + } + + tp->phy_auto_nego_reg = auto_nego; + tp->phy_1000_ctrl_reg = giga_ctrl; + + mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego); + mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl); + mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego | + PHY_Restart_Auto_Nego); + return 0; +} + +static int rtl8169_set_speed(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + int ret; + + ret = tp->set_speed(dev, autoneg, speed, duplex); + + if (netif_running(dev) && (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) + mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); + + return ret; +} + +static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&tp->lock, flags); + ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); + spin_unlock_irqrestore(&tp->lock, flags); + + return ret; +} + +static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + u32 status; + + cmd->supported = + SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; + cmd->port = PORT_FIBRE; + cmd->transceiver = XCVR_INTERNAL; + + status = RTL_R32(TBICSR); + cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; + cmd->autoneg = !!(status & TBINwEnable); + + cmd->speed = SPEED_1000; + cmd->duplex = DUPLEX_FULL; /* Always set */ +} + +static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + u8 status; + + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP; + + cmd->autoneg = 1; + cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; + + if (tp->phy_auto_nego_reg & PHY_Cap_10_Half) + cmd->advertising |= ADVERTISED_10baseT_Half; + if (tp->phy_auto_nego_reg & PHY_Cap_10_Full) + cmd->advertising |= ADVERTISED_10baseT_Full; + if (tp->phy_auto_nego_reg & PHY_Cap_100_Half) + cmd->advertising |= ADVERTISED_100baseT_Half; + if (tp->phy_auto_nego_reg & PHY_Cap_100_Full) + cmd->advertising |= ADVERTISED_100baseT_Full; + if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full) + cmd->advertising |= ADVERTISED_1000baseT_Full; + + status = RTL_R8(PHYstatus); + + if (status & _1000bpsF) + cmd->speed = SPEED_1000; + else if (status & _100bps) + cmd->speed = SPEED_100; + else if (status & _10bps) + cmd->speed = SPEED_10; + + cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? + DUPLEX_FULL : DUPLEX_HALF; +} + +static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + + tp->get_settings(dev, cmd); + + spin_unlock_irqrestore(&tp->lock, flags); + return 0; +} + + static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_settings = rtl8169_get_settings, + .set_settings = rtl8169_set_settings, }; static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum, @@ -500,7 +775,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; struct { u16 regs[5]; /* Beware of bit-sign propagation */ @@ -566,61 +841,47 @@ mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0 } -static void rtl8169_hw_phy_reset(struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - int i, val; - - printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name); - - val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff; - mdio_write(ioaddr, 0, val); - - for (i = 50; i >= 0; i--) { - if (!(mdio_read(ioaddr, 0) & 0x8000)) - break; - udelay(100); /* Gross */ - } - - if (i < 0) { - printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n", - dev->name); - } -} - static void rtl8169_phy_timer(unsigned long __opaque) { struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; void *ioaddr = tp->mmio_addr; + unsigned long timeout = RTL8169_PHY_TIMEOUT; assert(tp->mac_version > RTL_GIGA_MAC_VER_B); assert(tp->phy_version < RTL_GIGA_PHY_VER_G); - if (RTL_R8(PHYstatus) & LinkStatus) - tp->phy_link_down_cnt = 0; - else { - tp->phy_link_down_cnt++; - if (tp->phy_link_down_cnt >= 12) { - int reg; - - // If link on 1000, perform phy reset. - reg = mdio_read(ioaddr, PHY_1000_CTRL_REG); - if (reg & PHY_Cap_1000_Full) - rtl8169_hw_phy_reset(dev); + if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) + return; - tp->phy_link_down_cnt = 0; - } + spin_lock_irq(&tp->lock); + + if (tp->phy_reset_pending(ioaddr)) { + /* + * A busy loop could burn quite a few cycles on nowadays CPU. + * Let's delay the execution of the timer for a few ticks. + */ + timeout = HZ/10; + goto out_mod_timer; } - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); + if (tp->link_ok(ioaddr)) + goto out_unlock; + + printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name); + + tp->phy_reset_enable(ioaddr); + +out_mod_timer: + mod_timer(timer, jiffies + timeout); +out_unlock: + spin_unlock_irq(&tp->lock); } static inline void rtl8169_delete_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || @@ -628,21 +889,17 @@ return; del_timer_sync(timer); - - tp->phy_link_down_cnt = 0; } static inline void rtl8169_request_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || (tp->phy_version >= RTL_GIGA_PHY_VER_G)) return; - tp->phy_link_down_cnt = 0; - init_timer(timer); timer->expires = jiffies + RTL8169_PHY_TIMEOUT; timer->data = (unsigned long)(dev); @@ -681,7 +938,7 @@ // enable device (incl. PCI PM wakeup and hotplug setup) rc = pci_enable_device(pdev); if (rc) { - printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name); goto err_out; } @@ -693,7 +950,8 @@ pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { - printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); + printk(KERN_ERR PFX + "Cannot find PowerManagement capability, aborting.\n"); goto err_out_free_res; } @@ -716,9 +974,10 @@ goto err_out_disable; } - rc = pci_request_regions(pdev, dev->name); + rc = pci_request_regions(pdev, MODULENAME); if (rc) { - printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: could not request regions.\n", + pdev->slot_name); goto err_out_disable; } @@ -800,8 +1059,9 @@ void *ioaddr = NULL; static int board_idx = -1; static int printed_version = 0; + u8 autoneg, duplex; + u16 speed; int i, rc; - int option = -1, Cap10_100 = 0, Cap1000 = 0; assert(pdev != NULL); assert(ent != NULL); @@ -822,6 +1082,22 @@ assert(dev != NULL); assert(tp != NULL); + if (RTL_R8(PHYstatus) & TBI_Enable) { + tp->set_speed = rtl8169_set_speed_tbi; + tp->get_settings = rtl8169_gset_tbi; + tp->phy_reset_enable = rtl8169_tbi_reset_enable; + tp->phy_reset_pending = rtl8169_tbi_reset_pending; + tp->link_ok = rtl8169_tbi_link_ok; + + tp->phy_1000_ctrl_reg = PHY_Cap_1000_Full; /* Implied by TBI */ + } else { + tp->set_speed = rtl8169_set_speed_xmii; + tp->get_settings = rtl8169_gset_xmii; + tp->phy_reset_enable = rtl8169_xmii_reset_enable; + tp->phy_reset_pending = rtl8169_xmii_reset_pending; + tp->link_ok = rtl8169_xmii_link_ok; + } + // Get MAC address. FIXME: read EEPROM for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); @@ -836,9 +1112,12 @@ dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; -// dev->do_ioctl = mii_ioctl; - - tp = dev->priv; // private data // +#ifdef CONFIG_R8169_NAPI + dev->poll = rtl8169_poll; + dev->weight = R8169_NAPI_WEIGHT; + printk(KERN_INFO PFX "NAPI enabled\n"); +#endif + tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; @@ -885,95 +1164,12 @@ mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 } - // if TBI is not endbled - if (!(RTL_R8(PHYstatus) & TBI_Enable)) { - int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); - - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - // Force RTL8169 in 10/100/1000 Full/Half mode. - if (option > 0) { - printk(KERN_INFO "%s: Force-mode Enabled.\n", - dev->name); - Cap10_100 = 0, Cap1000 = 0; - switch (option) { - case _10_Half: - Cap10_100 = PHY_Cap_10_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _10_Full: - Cap10_100 = PHY_Cap_10_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Half: - Cap10_100 = PHY_Cap_100_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _1000_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_1000_Full; - break; - default: - break; - } - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000); - } else { - printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", - dev->name); - - // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, - PHY_Cap_100_Full_Or_Less | (val & 0x1f)); - - // enable 1000 Full Mode - mdio_write(ioaddr, PHY_1000_CTRL_REG, - PHY_Cap_1000_Full); - - } - - // Enable auto-negotiation and restart auto-nigotiation - mdio_write(ioaddr, PHY_CTRL_REG, - PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); - udelay(100); - - // wait for auto-negotiation process - for (i = 10000; i > 0; i--) { - //check if auto-negotiation complete - if (mdio_read(ioaddr, PHY_STAT_REG) & - PHY_Auto_Neco_Comp) { - udelay(100); - option = RTL_R8(PHYstatus); - if (option & _1000bpsF) { - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation.\n", - dev->name); - } else { - printk(KERN_INFO - "%s: %sMbps %s-duplex operation.\n", - dev->name, - (option & _100bps) ? "100" : - "10", - (option & FullDup) ? "Full" : - "Half"); - } - break; - } else { - udelay(100); - } - } // end for-loop to wait for auto-negotiation process - - } else { - udelay(100); - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", - dev->name, - (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); + rtl8169_link_option(board_idx, &autoneg, &speed, &duplex); - } + rtl8169_set_speed(dev, autoneg, speed, duplex); + + if (RTL_R8(PHYstatus) & TBI_Enable) + printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); return 0; } @@ -982,7 +1178,7 @@ rtl8169_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); assert(dev != NULL); assert(tp != NULL); @@ -1001,7 +1197,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; @@ -1042,7 +1238,7 @@ static int rtl8169_open(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; int retval; @@ -1074,6 +1270,8 @@ rtl8169_hw_start(dev); rtl8169_request_timer(dev); + + rtl8169_check_link_status(dev, tp, tp->mmio_addr); out: return retval; @@ -1091,7 +1289,7 @@ static void rtl8169_hw_start(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u32 i; @@ -1102,8 +1300,7 @@ for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; - else - udelay(10); + udelay(10); } RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -1114,8 +1311,8 @@ RTL_W16(RxMaxSize, RxPacketMaxSize); // Set Rx Config register - i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset]. - RxConfigMask); + i = rtl8169_rx_config | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, i); /* Set DMA burst size and Interframe Gap Time */ @@ -1126,7 +1323,8 @@ RTL_W16(CPlusCmd, tp->cp_cmd); if (tp->mac_version == RTL_GIGA_MAC_VER_D) { - dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n"); + dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. " + "Bit-3 and bit-14 MUST be 1\n"); tp->cp_cmd |= (1 << 14) | PCIMulRW; RTL_W16(CPlusCmd, tp->cp_cmd); } @@ -1151,7 +1349,6 @@ RTL_W16(IntrMask, rtl8169_intr_mask); netif_start_queue(dev); - } static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) @@ -1248,7 +1445,7 @@ static int rtl8169_init_ring(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); tp->cur_rx = tp->dirty_rx = 0; tp->cur_tx = tp->dirty_tx = 0; @@ -1302,10 +1499,11 @@ static void rtl8169_tx_timeout(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u8 tmp8; + printk(KERN_INFO "%s: TX Timeout\n", dev->name); /* disable Tx, if not already */ tmp8 = RTL_R8(ChipCmd); if (tmp8 & CmdTxEnb) @@ -1328,9 +1526,9 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; - int entry = tp->cur_tx % NUM_TX_DESC; + unsigned int entry = tp->cur_tx % NUM_TX_DESC; u32 len = skb->len; if (unlikely(skb->len < ETH_ZLEN)) { @@ -1340,10 +1538,9 @@ len = ETH_ZLEN; } - spin_lock_irq(&tp->lock); - if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) { dma_addr_t mapping; + u32 status; mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); @@ -1351,24 +1548,30 @@ tp->Tx_skbuff[entry] = skb; tp->TxDescArray[entry].addr = cpu_to_le64(mapping); - tp->TxDescArray[entry].status = cpu_to_le32(OWNbit | FSbit | - LSbit | len | (EORbit * !((entry + 1) % NUM_TX_DESC))); + /* anti gcc 2.95.3 bugware */ + status = OWNbit | FSbit | LSbit | len | + (EORbit * !((entry + 1) % NUM_TX_DESC)); + tp->TxDescArray[entry].status = cpu_to_le32(status); RTL_W8(TxPoll, 0x40); //set polling bit dev->trans_start = jiffies; tp->cur_tx++; + smp_wmb(); } else goto err_drop; - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) { + u32 dirty = tp->dirty_tx; + netif_stop_queue(dev); + smp_rmb(); + if (dirty != tp->dirty_tx) + netif_wake_queue(dev); } -out: - spin_unlock_irq(&tp->lock); +out: return 0; err_drop: @@ -1382,17 +1585,18 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long dirty_tx, tx_left; + unsigned int dirty_tx, tx_left; assert(dev != NULL); assert(tp != NULL); assert(ioaddr != NULL); dirty_tx = tp->dirty_tx; + smp_rmb(); tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; + unsigned int entry = dirty_tx % NUM_TX_DESC; struct sk_buff *skb = tp->Tx_skbuff[entry]; u32 status; @@ -1415,6 +1619,7 @@ if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; + smp_wmb(); if (netif_queue_stopped(dev)) netif_wake_queue(dev); } @@ -1442,11 +1647,11 @@ return ret; } -static void +static int rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long cur_rx, rx_left; + unsigned int cur_rx, rx_left, count; int delta; assert(dev != NULL); @@ -1455,9 +1660,10 @@ cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; + rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); while (rx_left > 0) { - int entry = cur_rx % NUM_RX_DESC; + unsigned int entry = cur_rx % NUM_RX_DESC; u32 status; rmb(); @@ -1494,7 +1700,7 @@ skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + rtl8169_rx_skb(skb); dev->last_rx = jiffies; tp->stats.rx_bytes += pkt_size; @@ -1505,13 +1711,15 @@ rx_left--; } + count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (delta > 0) - tp->dirty_rx += delta; - else if (delta < 0) + if (delta < 0) { printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); + delta = 0; + } + tp->dirty_rx += delta; /* * FIXME: until there is periodic timer to try and refill the ring, @@ -1522,6 +1730,8 @@ */ if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); + + return count; } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ @@ -1529,7 +1739,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); int boguscnt = max_interrupt_work; void *ioaddr = tp->mmio_addr; int status = 0; @@ -1543,26 +1753,37 @@ break; handled = 1; -/* - if (status & RxUnderrun) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; -*/ + + status &= tp->intr_mask; RTL_W16(IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status); if (!(status & rtl8169_intr_mask)) break; + if (status & LinkChg) + rtl8169_check_link_status(dev, tp, ioaddr); + +#ifdef CONFIG_R8169_NAPI + RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); + tp->intr_mask = ~rtl8169_napi_event; + + if (likely(netif_rx_schedule_prep(dev))) + __netif_rx_schedule(dev); + else { + printk(KERN_INFO "%s: interrupt %x taken in poll\n", + dev->name, status); + } + break; +#else // Rx interrupt - if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) { + if (status & (RxOK | RxOverflow | RxFIFOOver)) { rtl8169_rx_interrupt(dev, tp, ioaddr); } // Tx interrupt - if (status & (TxOK | TxErr)) { - spin_lock(&tp->lock); + if (status & (TxOK | TxErr)) rtl8169_tx_interrupt(dev, tp, ioaddr); - spin_unlock(&tp->lock); - } +#endif boguscnt--; } while (boguscnt > 0); @@ -1576,10 +1797,40 @@ return IRQ_RETVAL(handled); } +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget) +{ + unsigned int work_done, work_to_do = min(*budget, dev->quota); + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + + work_done = rtl8169_rx_interrupt(dev, tp, ioaddr); + rtl8169_tx_interrupt(dev, tp, ioaddr); + + *budget -= work_done; + dev->quota -= work_done; + + if ((work_done < work_to_do) || !netif_running(dev)) { + netif_rx_complete(dev); + tp->intr_mask = 0xffff; + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + RTL_W16(IntrMask, rtl8169_intr_mask); + } + + return (work_done >= work_to_do); +} +#endif + static int rtl8169_close(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; void *ioaddr = tp->mmio_addr; @@ -1621,7 +1872,7 @@ static void rtl8169_set_rx_mode(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ @@ -1655,10 +1906,8 @@ spin_lock_irqsave(&tp->lock, flags); - tmp = - rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & - rtl_chip_info[tp->chipset]. - RxConfigMask); + tmp = rtl8169_rx_config | rx_mode | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, tmp); RTL_W32(MAR0 + 0, mc_filter[0]); @@ -1675,7 +1924,7 @@ */ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; diff -Nru a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c --- a/drivers/net/smc-mca.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/smc-mca.c 2004-06-13 23:56:44 -07:00 @@ -51,6 +51,8 @@ #include "8390.h" #include "smc-mca.h" +#define DRV_NAME "smc-mca" + static int ultramca_open(struct net_device *dev); static void ultramca_reset_8390(struct net_device *dev); static void ultramca_get_8390_hdr(struct net_device *dev, @@ -265,7 +267,7 @@ goto err_unclaim; } - if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) { + if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) { rc = -ENODEV; goto err_unclaim; } diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c --- a/drivers/net/smc-ultra.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/smc-ultra.c 2004-06-13 23:56:44 -07:00 @@ -72,6 +72,8 @@ #include "8390.h" +#define DRV_NAME "smc-ultra" + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int ultra_portlist[] __initdata = {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0}; @@ -178,6 +180,7 @@ release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT); } +#ifndef MODULE struct net_device * __init ultra_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -202,6 +205,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init ultra_probe1(struct net_device *dev, int ioaddr) { @@ -215,7 +219,7 @@ unsigned char idreg = inb(ioaddr + 7); unsigned char reg4 = inb(ioaddr + 4) & 0x7f; - if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) return -EBUSY; /* Check the ID nibble. */ diff -Nru a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c --- a/drivers/net/smc-ultra32.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/smc-ultra32.c 2004-06-13 23:56:44 -07:00 @@ -61,6 +61,8 @@ #include "8390.h" +#define DRV_NAME "smc-ultra32" + static int ultra32_probe1(struct net_device *dev, int ioaddr); static int ultra32_open(struct net_device *dev); static void ultra32_reset_8390(struct net_device *dev); @@ -163,7 +165,7 @@ unsigned char reg4; const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"}; - if (!request_region(ioaddr, ULTRA32_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, ULTRA32_IO_EXTENT, DRV_NAME)) return -EBUSY; if (inb(ioaddr + ULTRA32_IDPORT) == 0xff || diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c --- a/drivers/net/smc9194.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/smc9194.c 2004-06-13 23:56:44 -07:00 @@ -78,6 +78,8 @@ #include "smc9194.h" +#define DRV_NAME "smc9194" + /*------------------------------------------------------------------------ . . Configuration options, for the experienced user to change. @@ -843,7 +845,7 @@ word memory_cfg_register; /* Grab the region so that no one else tries to probe our ioports. */ - if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) + if (!request_region(ioaddr, SMC_IO_EXTENT, DRV_NAME)) return -EBUSY; dev->irq = irq; @@ -1001,9 +1003,9 @@ memset(dev->priv, 0, sizeof(struct smc_local)); /* Grab the IRQ */ - retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); + retval = request_irq(dev->irq, &smc_interrupt, 0, DRV_NAME, dev); if (retval) { - printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, + printk("%s: unable to get IRQ %d (irqval=%d).\n", DRV_NAME, dev->irq, retval); goto err_out; } diff -Nru a/drivers/net/starfire.c b/drivers/net/starfire.c --- a/drivers/net/starfire.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/starfire.c 2004-06-13 23:56:44 -07:00 @@ -880,7 +880,7 @@ irq = pdev->irq; - if (pci_request_regions (pdev, dev->name)) { + if (pci_request_regions (pdev, DRV_NAME)) { printk(KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx); goto err_out_free_netdev; } diff -Nru a/drivers/net/stnic.c b/drivers/net/stnic.c --- a/drivers/net/stnic.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/stnic.c 2004-06-13 23:56:44 -07:00 @@ -28,6 +28,8 @@ #include "8390.h" +#define DRV_NAME "stnic" + #define byte unsigned char #define half unsigned short #define word unsigned int @@ -130,7 +132,7 @@ /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - err = request_irq (dev->irq, ei_interrupt, 0, dev->name, dev); + err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (err) { printk (KERN_EMERG " unable to get IRQ %d.\n", dev->irq); free_netdev(dev); diff -Nru a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c --- a/drivers/net/sun3_82586.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/sun3_82586.c 2004-06-13 23:56:44 -07:00 @@ -53,6 +53,8 @@ #include "sun3_82586.h" +#define DRV_NAME "sun3_82586" + #define DEBUG /* debug on */ #define SYSBUSVAL 0 /* 16 Bit */ #define SUN3_82586_TOTAL_SIZE PAGE_SIZE @@ -336,7 +338,7 @@ { int i, size, retval; - if (!request_region(ioaddr, SUN3_82586_TOTAL_SIZE, dev->name)) + if (!request_region(ioaddr, SUN3_82586_TOTAL_SIZE, DRV_NAME)) return -EBUSY; /* copy in the ethernet address from the prom */ diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c --- a/drivers/net/sungem.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/sungem.c 2004-06-13 23:56:44 -07:00 @@ -2717,7 +2717,7 @@ gp = dev->priv; - err = pci_request_regions(pdev, dev->name); + err = pci_request_regions(pdev, DRV_NAME); if (err) { printk(KERN_ERR PFX "Cannot obtain PCI resources, " "aborting.\n"); diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c --- a/drivers/net/sunhme.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/sunhme.c 2004-06-13 23:56:44 -07:00 @@ -68,6 +68,8 @@ #include "sunhme.h" +#define DRV_NAME "sunhme" + static int macaddr[6]; /* accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */ @@ -3085,7 +3087,7 @@ printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n"); goto err_out_clear_quattro; } - if (pci_request_regions(pdev, dev->name)) { + if (pci_request_regions(pdev, DRV_NAME)) { printk(KERN_ERR "happymeal(PCI): Cannot obtain PCI resources, " "aborting.\n"); goto err_out_clear_quattro; diff -Nru a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig --- a/drivers/net/tulip/Kconfig 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/tulip/Kconfig 2004-06-13 23:56:44 -07:00 @@ -71,10 +71,17 @@ config TULIP_NAPI bool "Use NAPI RX polling " depends on TULIP - ---help--- - This is of useful for servers and routers dealing with high network loads. - - See . + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. If in doubt, say N. diff -Nru a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c --- a/drivers/net/tulip/winbond-840.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/tulip/winbond-840.c 2004-06-13 23:56:44 -07:00 @@ -1292,14 +1292,8 @@ pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); - /* Call copy + cksum if available. */ -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail, - pkt_len); -#endif pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c --- a/drivers/net/via-rhine.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/via-rhine.c 2004-06-13 23:56:44 -07:00 @@ -354,59 +354,46 @@ second only the 1234 card. */ -enum pci_flags_bit { - PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, - PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, +enum rhine_revs { + VT86C100A = 0x00, + VT6102 = 0x40, + VT8231 = 0x50, /* Integrated MAC */ + VT8233 = 0x60, /* Integrated MAC */ + VT8235 = 0x74, /* Integrated MAC */ + VT8237 = 0x78, /* Integrated MAC */ + VTunknown0 = 0x7C, + VT6105 = 0x80, + VT6105_B0 = 0x83, + VT6105L = 0x8A, + VT6107 = 0x8C, + VTunknown1 = 0x8E, + VT6105M = 0x90, }; -enum rhine_chips { - VT86C100A = 0, - VT6102, - VT6105, - VT6105M -}; - -struct rhine_chip_info { - const char *name; - u16 pci_flags; - int io_size; - int drv_flags; -}; - - -enum chip_capability_flags { - CanHaveMII=1, HasESIPhy=2, HasDavicomPhy=4, - ReqTxAlign=0x10, HasWOL=0x20, +enum rhine_quirks { + rqWOL = 0x0001, /* Wake-On-LAN support */ + rqForceReset = 0x0002, + rqDavicomPhy = 0x0020, + rq6patterns = 0x0040, /* 6 instead of 4 patterns for WOL */ + rqStatusWBRace = 0x0080, /* Tx Status Writeback Error possible */ + rqRhineI = 0x0100, /* See comment below */ }; +/* + * rqRhineI: VT86C100A (aka Rhine-I) uses different bits to enable + * MMIO as well as for the collision counter and the Tx FIFO underflow + * indicator. In addition, Tx and Rx buffers need to 4 byte aligned. + */ -#ifdef USE_MMIO -#define RHINE_IOTYPE (PCI_USES_MEM | PCI_USES_MASTER | PCI_ADDR1) -#else -#define RHINE_IOTYPE (PCI_USES_IO | PCI_USES_MASTER | PCI_ADDR0) -#endif /* Beware of PCI posted writes */ #define IOSYNC do { readb(dev->base_addr + StationAddr); } while (0) -/* directly indexed by enum rhine_chips, above */ -static struct rhine_chip_info rhine_chip_info[] __devinitdata = -{ - { "VIA VT86C100A Rhine", RHINE_IOTYPE, 128, - CanHaveMII | ReqTxAlign | HasDavicomPhy }, - { "VIA VT6102 Rhine-II", RHINE_IOTYPE, 256, - CanHaveMII | HasWOL }, - { "VIA VT6105 Rhine-III", RHINE_IOTYPE, 256, - CanHaveMII | HasWOL }, - { "VIA VT6105M Rhine-III", RHINE_IOTYPE, 256, - CanHaveMII | HasWOL }, -}; - static struct pci_device_id rhine_pci_tbl[] = { - {0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT86C100A}, - {0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6102}, - {0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105}, /* 6105{,L,LOM} */ - {0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105M}, - {0,} /* terminate list */ + {0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT86C100A */ + {0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6102 */ + {0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* 6105{,L,LOM} */ + {0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6105M */ + { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, rhine_pci_tbl); @@ -421,8 +408,10 @@ MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74, ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B, RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81, - StickyHW=0x83, IntrStatus2=0x84, WOLcrClr=0xA4, WOLcgClr=0xA7, - PwrcsrClr=0xAC, + StickyHW=0x83, IntrStatus2=0x84, + WOLcrSet=0xA0, WOLcrClr=0xA4, WOLcrClr1=0xA6, + WOLcgClr=0xA7, + PwrcsrSet=0xA8, PwrcsrSet1=0xA9, PwrcsrClr=0xAC, PwrcsrClr1=0xAD, }; /* Bits in ConfigD */ @@ -514,7 +503,7 @@ spinlock_t lock; /* Frequently used values: keep some adjacent for cache effect. */ - int chip_id, drv_flags; + u32 quirks; struct rx_desc *rx_head_desc; unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int cur_tx, dirty_tx; @@ -522,7 +511,6 @@ u16 chip_cmd; /* Current setting for ChipCmd */ /* These values are keep track of the transceiver/media in use. */ - unsigned int default_port:4; /* Last dev->if_port value. */ u8 tx_thresh, rx_thresh; /* MII transceiver section. */ @@ -557,12 +545,41 @@ intr_status = readw(ioaddr + IntrStatus); /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */ - if (rp->chip_id == VT6102) + if (rp->quirks & rqStatusWBRace) intr_status |= readb(ioaddr + IntrStatus2) << 16; return intr_status; } -static void wait_for_reset(struct net_device *dev, int chip_id, char *name) +/* + * Get power related registers into sane state. + * Returns content of power-event (WOL) registers. + */ +static void rhine_power_init(struct net_device *dev) +{ + long ioaddr = dev->base_addr; + struct rhine_private *rp = netdev_priv(dev); + + if (rp->quirks & rqWOL) { + /* Make sure chip is in power state D0 */ + writeb(readb(ioaddr + StickyHW) & 0xFC, ioaddr + StickyHW); + + /* Disable "force PME-enable" */ + writeb(0x80, ioaddr + WOLcgClr); + + /* Clear power-event config bits (WOL) */ + writeb(0xFF, ioaddr + WOLcrClr); + /* More recent cards can manage two additional patterns */ + if (rp->quirks & rq6patterns) + writeb(0x03, ioaddr + WOLcrClr1); + + /* Clear power-event status bits */ + writeb(0xFF, ioaddr + PwrcsrClr); + if (rp->quirks & rq6patterns) + writeb(0x03, ioaddr + PwrcsrClr1); + } +} + +static void wait_for_reset(struct net_device *dev, u32 quirks, char *name) { long ioaddr = dev->base_addr; int boguscnt = 20; @@ -574,7 +591,7 @@ "Trying harder.\n", name); /* Rhine-II needs to be forced sometimes */ - if (chip_id == VT6102) + if (quirks & rqForceReset) writeb(0x40, ioaddr + MiscCmd); /* VT86C100A may need long delay after reset (dlink) */ @@ -590,10 +607,10 @@ } #ifdef USE_MMIO -static void __devinit enable_mmio(long ioaddr, int chip_id) +static void __devinit enable_mmio(long ioaddr, u32 quirks) { int n; - if (chip_id == VT86C100A) { + if (quirks & rqRhineI) { /* More recent docs say that this bit is reserved ... */ n = inb(ioaddr + ConfigA) | 0x20; outb(n, ioaddr + ConfigA); @@ -628,16 +645,18 @@ { struct net_device *dev; struct rhine_private *rp; - int i, option; - int chip_id = (int) ent->driver_data; + int i, option, rc; + u8 pci_rev; + u32 quirks; static int card_idx = -1; long ioaddr; long memaddr; int io_size; - int pci_flags; + int phy, phy_idx = 0; #ifdef USE_MMIO long ioaddr0; #endif + const char *name; /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -648,14 +667,34 @@ card_idx++; option = card_idx < MAX_UNITS ? options[card_idx] : 0; - io_size = rhine_chip_info[chip_id].io_size; - pci_flags = rhine_chip_info[chip_id].pci_flags; + pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); + + io_size = 256; + if (pci_rev < VT6102) { + quirks = rqRhineI | rqDavicomPhy; + io_size = 128; + name = "VT86C100A Rhine"; + } + else { + quirks = rqWOL | rqForceReset; + if (pci_rev < VT6105) { + name = "Rhine II"; + quirks |= rqStatusWBRace; /* Rhine-II exclusive */ + } + else { + name = "Rhine III"; + if (pci_rev >= VT6105_B0) + quirks |= rq6patterns; + } + } - if (pci_enable_device(pdev)) + rc = pci_enable_device(pdev); + if (rc) goto err_out; /* this should always be supported */ - if (pci_set_dma_mask(pdev, 0xffffffff)) { + rc = pci_set_dma_mask(pdev, 0xffffffff); + if (rc) { printk(KERN_ERR "32-bit PCI DMA addresses not supported by " "the card!?\n"); goto err_out; @@ -664,6 +703,7 @@ /* sanity check */ if ((pci_resource_len(pdev, 0) < io_size) || (pci_resource_len(pdev, 1) < io_size)) { + rc = -EIO; printk(KERN_ERR "Insufficient PCI resources, aborting\n"); goto err_out; } @@ -671,11 +711,11 @@ ioaddr = pci_resource_start(pdev, 0); memaddr = pci_resource_start(pdev, 1); - if (pci_flags & PCI_USES_MASTER) - pci_set_master(pdev); + pci_set_master(pdev); dev = alloc_etherdev(sizeof(*rp)); if (dev == NULL) { + rc = -ENOMEM; printk(KERN_ERR "init_ethernet failed for card #%d\n", card_idx); goto err_out; @@ -683,15 +723,17 @@ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_request_regions(pdev, shortname)) + rc = pci_request_regions(pdev, shortname); + if (rc) goto err_out_free_netdev; #ifdef USE_MMIO ioaddr0 = ioaddr; - enable_mmio(ioaddr0, chip_id); + enable_mmio(ioaddr0, quirks); ioaddr = (long) ioremap(memaddr, io_size); if (!ioaddr) { + rc = -EIO; printk(KERN_ERR "ioremap failed for device %s, region 0x%X " "@ 0x%lX\n", pci_name(pdev), io_size, memaddr); goto err_out_free_res; @@ -704,36 +746,21 @@ unsigned char a = inb(ioaddr0+reg); unsigned char b = readb(ioaddr+reg); if (a != b) { + rc = -EIO; printk(KERN_ERR "MMIO do not match PIO [%02x] " "(%02x != %02x)\n", reg, a, b); goto err_out_unmap; } } #endif /* USE_MMIO */ + dev->base_addr = ioaddr; - /* D-Link provided reset code (with comment additions) */ - if (rhine_chip_info[chip_id].drv_flags & HasWOL) { - unsigned char byOrgValue; - - /* clear sticky bit before reset & read ethernet address */ - byOrgValue = readb(ioaddr + StickyHW); - byOrgValue = byOrgValue & 0xFC; - writeb(byOrgValue, ioaddr + StickyHW); - - /* (bits written are cleared?) */ - /* disable force PME-enable */ - writeb(0x80, ioaddr + WOLcgClr); - /* disable power-event config bit */ - writeb(0xFF, ioaddr + WOLcrClr); - /* clear power status (undocumented in vt6102 docs?) */ - writeb(0xFF, ioaddr + PwrcsrClr); - } + rhine_power_init(dev); /* Reset the chip to erase previous misconfiguration. */ writew(CmdReset, ioaddr + ChipCmd); - dev->base_addr = ioaddr; - wait_for_reset(dev, chip_id, shortname); + wait_for_reset(dev, quirks, shortname); /* Reload the station address from the EEPROM. */ #ifdef USE_MMIO @@ -741,7 +768,7 @@ /* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO. If reload_eeprom() was done first this could be avoided, but it is not known if that still works with the "win98-reboot" problem. */ - enable_mmio(ioaddr0, chip_id); + enable_mmio(ioaddr0, quirks); #else reload_eeprom(ioaddr); #endif @@ -750,11 +777,12 @@ dev->dev_addr[i] = readb(ioaddr + StationAddr + i); if (!is_valid_ether_addr(dev->dev_addr)) { + rc = -EIO; printk(KERN_ERR "Invalid MAC address for card #%d\n", card_idx); goto err_out_unmap; } - if (chip_id == VT6102) { + if (quirks & rqWOL) { /* * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA * turned on. it makes MAC receive magic packet @@ -772,9 +800,8 @@ rp = netdev_priv(dev); spin_lock_init(&rp->lock); - rp->chip_id = chip_id; - rp->drv_flags = rhine_chip_info[chip_id].drv_flags; rp->pdev = pdev; + rp->quirks = quirks; rp->mii_if.dev = dev; rp->mii_if.mdio_read = mdio_read; rp->mii_if.mdio_write = mdio_write; @@ -797,19 +824,18 @@ #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = rhine_poll; #endif - if (rp->drv_flags & ReqTxAlign) + if (rp->quirks & rqRhineI) dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; /* dev->name not defined before register_netdev()! */ - i = register_netdev(dev); - if (i) + rc = register_netdev(dev); + if (rc) goto err_out_unmap; /* The lower four bits are the media type. */ if (option > 0) { if (option & 0x220) rp->mii_if.full_duplex = 1; - rp->default_port = option & 15; } if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) rp->mii_if.full_duplex = 1; @@ -820,9 +846,14 @@ rp->mii_if.force_media = 1; } - printk(KERN_INFO "%s: %s at 0x%lx, ", - dev->name, rhine_chip_info[chip_id].name, - (pci_flags & PCI_USES_IO) ? ioaddr : memaddr); + printk(KERN_INFO "%s: VIA %s at 0x%lx, ", + dev->name, name, +#ifdef USE_MMIO + memaddr +#else + ioaddr +#endif + ); for (i = 0; i < 5; i++) printk("%2.2x:", dev->dev_addr[i]); @@ -830,41 +861,35 @@ pci_set_drvdata(pdev, dev); - if (rp->drv_flags & CanHaveMII) { - int phy, phy_idx = 0; - rp->phys[0] = 1; /* Standard for this chip. */ - for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) { - int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - rp->phys[phy_idx++] = phy; - rp->mii_if.advertising = mdio_read(dev, phy, 4); - printk(KERN_INFO "%s: MII PHY found at address " - "%d, status 0x%4.4x advertising %4.4x " - "Link %4.4x.\n", dev->name, phy, - mii_status, rp->mii_if.advertising, - mdio_read(dev, phy, 5)); - - /* set IFF_RUNNING */ - if (mii_status & BMSR_LSTATUS) - netif_carrier_on(dev); - else - netif_carrier_off(dev); + rp->phys[0] = 1; /* Standard for this chip. */ + for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) { + int mii_status = mdio_read(dev, phy, 1); + if (mii_status != 0xffff && mii_status != 0x0000) { + rp->phys[phy_idx++] = phy; + rp->mii_if.advertising = mdio_read(dev, phy, 4); + printk(KERN_INFO "%s: MII PHY found at address " + "%d, status 0x%4.4x advertising %4.4x " + "Link %4.4x.\n", dev->name, phy, + mii_status, rp->mii_if.advertising, + mdio_read(dev, phy, 5)); + + /* set IFF_RUNNING */ + if (mii_status & BMSR_LSTATUS) + netif_carrier_on(dev); + else + netif_carrier_off(dev); - break; - } + break; } - rp->mii_cnt = phy_idx; - rp->mii_if.phy_id = rp->phys[0]; } + rp->mii_cnt = phy_idx; + rp->mii_if.phy_id = rp->phys[0]; /* Allow forcing the media type. */ if (option > 0) { if (option & 0x220) rp->mii_if.full_duplex = 1; - rp->default_port = option & 0x3ff; if (option & 0x330) { - /* FIXME: shouldn't someone check this variable? */ - /* rp->medialock = 1; */ printk(KERN_INFO " Forcing %dMbs %s-duplex " "operation.\n", (option & 0x300 ? 100 : 10), @@ -887,7 +912,7 @@ err_out_free_netdev: free_netdev(dev); err_out: - return -ENODEV; + return rc; } static int alloc_ring(struct net_device* dev) @@ -904,7 +929,7 @@ printk(KERN_ERR "Could not allocate DMA memory.\n"); return -ENOMEM; } - if (rp->drv_flags & ReqTxAlign) { + if (rp->quirks & rqRhineI) { rp->tx_bufs = pci_alloc_consistent(rp->pdev, PKT_BUF_SZ * TX_RING_SIZE, &rp->tx_bufs_dma); @@ -1063,9 +1088,6 @@ rp->rx_thresh = 0x60; /* Written in rhine_set_rx_mode(). */ rp->mii_if.full_duplex = 0; - if (dev->if_port == 0) - dev->if_port = rp->default_port; - writel(rp->rx_ring_dma, ioaddr + RxRingPtr); writel(rp->tx_ring_dma, ioaddr + TxRingPtr); @@ -1087,9 +1109,8 @@ /* The LED outputs of various MII xcvrs should be configured. */ /* For NS or Mison phys, turn on bit 1 in register 0x17 */ - /* For ESI phys, turn on bit 7 in register 0x17. */ mdio_write(dev, rp->phys[0], 0x17, mdio_read(dev, rp->phys[0], 0x17) | - (rp->drv_flags & HasESIPhy) ? 0x0080 : 0x0001); + 0x0001); } /* Read and write over the MII Management Data I/O (MDIO) interface. */ @@ -1166,7 +1187,7 @@ return i; alloc_rbufs(dev); alloc_tbufs(dev); - wait_for_reset(dev, rp->chip_id, dev->name); + wait_for_reset(dev, rp->quirks, dev->name); init_registers(dev); if (debug > 2) printk(KERN_DEBUG "%s: Done rhine_open(), status %4.4x " @@ -1257,8 +1278,6 @@ dev->name, readw(ioaddr + IntrStatus), mdio_read(dev, rp->phys[0], MII_BMSR)); - dev->if_port = 0; - /* protect against concurrent rx interrupts */ disable_irq(rp->pdev->irq); @@ -1274,7 +1293,7 @@ alloc_rbufs(dev); /* Reinitialize the hardware. */ - wait_for_reset(dev, rp->chip_id, dev->name); + wait_for_reset(dev, rp->quirks, dev->name); init_registers(dev); spin_unlock(&rp->lock); @@ -1305,7 +1324,7 @@ rp->tx_skbuff[entry] = skb; - if ((rp->drv_flags & ReqTxAlign) && + if ((rp->quirks & rqRhineI) && (((long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)) { /* Must use alignment buffer. */ if (skb->len > PKT_BUF_SZ) { @@ -1454,7 +1473,7 @@ if (txstatus & 0x0200) rp->stats.tx_window_errors++; if (txstatus & 0x0100) rp->stats.tx_aborted_errors++; if (txstatus & 0x0080) rp->stats.tx_heartbeat_errors++; - if (((rp->chip_id == VT86C100A) && txstatus & 0x0002) || + if (((rp->quirks & rqRhineI) && txstatus & 0x0002) || (txstatus & 0x0800) || (txstatus & 0x1000)) { rp->stats.tx_fifo_errors++; rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); @@ -1462,7 +1481,7 @@ } /* Transmitter restarted in 'abnormal' handler. */ } else { - if (rp->chip_id == VT86C100A) + if (rp->quirks & rqRhineI) rp->stats.collisions += (txstatus >> 3) & 0x0F; else rp->stats.collisions += txstatus & 0x0F; @@ -1563,15 +1582,10 @@ eth_copy_and_sum is memcpy for all archs so this is kind of pointless right now ... or? */ -#if HAS_IP_COPYSUM /* Call copy + cksum if available. */ eth_copy_and_sum(skb, rp->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - rp->rx_skbuff[entry]->tail, pkt_len); -#endif pci_dma_sync_single_for_device(rp->pdev, rp->rx_skbuff_dma[entry], rp->rx_buf_sz, @@ -1679,7 +1693,7 @@ if (intr_status & (IntrLinkChange)) { if (readb(ioaddr + MIIStatus) & 0x02) { /* Link failed, restart autonegotiation. */ - if (rp->drv_flags & HasDavicomPhy) + if (rp->quirks & rqRhineI) mdio_write(dev, rp->phys[0], MII_BMCR, 0x3300); } else rhine_check_duplex(dev); @@ -1805,9 +1819,6 @@ struct rhine_private *rp = netdev_priv(dev); int rc; - if (!(rp->drv_flags & CanHaveMII)) - return -EINVAL; - spin_lock_irq(&rp->lock); rc = mii_ethtool_gset(&rp->mii_if, cmd); spin_unlock_irq(&rp->lock); @@ -1820,9 +1831,6 @@ struct rhine_private *rp = netdev_priv(dev); int rc; - if (!(rp->drv_flags & CanHaveMII)) - return -EINVAL; - spin_lock_irq(&rp->lock); rc = mii_ethtool_sset(&rp->mii_if, cmd); spin_unlock_irq(&rp->lock); @@ -1834,18 +1842,12 @@ { struct rhine_private *rp = netdev_priv(dev); - if (!(rp->drv_flags & CanHaveMII)) - return -EINVAL; - return mii_nway_restart(&rp->mii_if); } static u32 netdev_get_link(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); - - if (!(rp->drv_flags & CanHaveMII)) - return 0; /* -EINVAL */ return mii_link_ok(&rp->mii_if); } diff -Nru a/drivers/net/wd.c b/drivers/net/wd.c --- a/drivers/net/wd.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wd.c 2004-06-13 23:56:44 -07:00 @@ -43,6 +43,8 @@ #include "8390.h" +#define DRV_NAME "wd" + /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int wd_portlist[] __initdata = {0x300, 0x280, 0x380, 0x240, 0}; @@ -131,6 +133,7 @@ release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT); } +#ifndef MODULE struct net_device * __init wd_probe(int unit) { struct net_device *dev = alloc_ei_netdev(); @@ -155,6 +158,7 @@ free_netdev(dev); return ERR_PTR(err); } +#endif static int __init wd_probe1(struct net_device *dev, int ioaddr) { @@ -300,7 +304,7 @@ /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - i = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev); if (i) { printk (" unable to get IRQ %d.\n", dev->irq); return i; diff -Nru a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c --- a/drivers/net/wireless/prism54/isl_38xx.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/isl_38xx.c 2004-06-13 23:56:44 -07:00 @@ -25,17 +25,11 @@ #include #include -#include "isl_38xx.h" -#include - #include #include -#include -#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE) -#error No Firmware Loading configured in the kernel ! -#endif - +#include "prismcompat.h" +#include "isl_38xx.h" #include "islpci_dev.h" #include "islpci_mgt.h" @@ -233,130 +227,6 @@ ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP); isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG); udelay(ISL38XX_WRITEIO_DELAY); -} - -int -isl38xx_upload_firmware(char *fw_id, _REQ_FW_DEV_T dev, void *device_base, - dma_addr_t host_address) -{ - u32 reg, rc; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_ERROR_MESSAGES, "isl38xx_upload_firmware(0x%lx, 0x%lx)\n", - (long) device_base, (long) host_address); -#endif - - /* clear the RAMBoot and the Reset bit */ - reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - reg &= ~ISL38XX_CTRL_STAT_RESET; - reg &= ~ISL38XX_CTRL_STAT_RAMBOOT; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* set the Reset bit without reading the register ! */ - reg |= ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* clear the Reset bit */ - reg &= ~ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - - /* wait a while for the device to reboot */ - mdelay(50); - - { - const struct firmware *fw_entry = 0; - long fw_len; - const u32 *fw_ptr; - - rc = request_firmware(&fw_entry, fw_id, dev); - if (rc) { - printk(KERN_ERR - "%s: request_firmware() failed for '%s'\n", - "prism54", fw_id); - return rc; - } - /* prepare the Direct Memory Base register */ - reg = ISL38XX_DEV_FIRMWARE_ADDRES; - - fw_ptr = (u32 *) fw_entry->data; - fw_len = fw_entry->size; - - if (fw_len % 4) { - printk(KERN_ERR - "%s: firmware '%s' size is not multiple of 32bit, aborting!\n", - "prism54", fw_id); - release_firmware(fw_entry); - return EILSEQ; /* Illegal byte sequence */; - } - - while (fw_len > 0) { - long _fw_len = - (fw_len > - ISL38XX_MEMORY_WINDOW_SIZE) ? - ISL38XX_MEMORY_WINDOW_SIZE : fw_len; - u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; - - /* set the cards base address for writting the data */ - isl38xx_w32_flush(device_base, reg, - ISL38XX_DIR_MEM_BASE_REG); - wmb(); /* be paranoid */ - - /* increment the write address for next iteration */ - reg += _fw_len; - fw_len -= _fw_len; - - /* write the data to the Direct Memory Window 32bit-wise */ - /* memcpy_toio() doesn't guarantee 32bit writes :-| */ - while (_fw_len > 0) { - /* use non-swapping writel() */ - __raw_writel(*fw_ptr, dev_fw_ptr); - fw_ptr++, dev_fw_ptr++; - _fw_len -= 4; - } - - /* flush PCI posting */ - (void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH); - wmb(); /* be paranoid again */ - - BUG_ON(_fw_len != 0); - } - - BUG_ON(fw_len != 0); - - release_firmware(fw_entry); - } - - /* now reset the device - * clear the Reset & ClkRun bit, set the RAMBoot bit */ - reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - reg &= ~ISL38XX_CTRL_STAT_CLKRUN; - reg &= ~ISL38XX_CTRL_STAT_RESET; - reg |= ISL38XX_CTRL_STAT_RAMBOOT; - isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* set the reset bit latches the host override and RAMBoot bits - * into the device for operation when the reset bit is reset */ - reg |= ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - /* don't do flush PCI posting here! */ - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* clear the reset bit should start the whole circus */ - reg &= ~ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - /* don't do flush PCI posting here! */ - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - return 0; } int diff -Nru a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h --- a/drivers/net/wireless/prism54/isl_38xx.h 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/isl_38xx.h 2004-06-13 23:56:44 -07:00 @@ -22,14 +22,6 @@ #include #include - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75)) -#include -# define _REQ_FW_DEV_T struct device * -#else -# define _REQ_FW_DEV_T char * -#endif - #include #define ISL38XX_CB_RX_QSIZE 8 @@ -173,7 +165,5 @@ void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void *); void isl38xx_trigger_device(int, void *); void isl38xx_interface_reset(void *, dma_addr_t); - -int isl38xx_upload_firmware(char *, _REQ_FW_DEV_T, void *, dma_addr_t); #endif /* _ISL_38XX_H */ diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c --- a/drivers/net/wireless/prism54/isl_ioctl.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/isl_ioctl.c 2004-06-13 23:56:44 -07:00 @@ -25,10 +25,10 @@ #include #include #include -#include #include +#include "prismcompat.h" #include "isl_ioctl.h" #include "islpci_mgt.h" #include "isl_oid.h" /* additional types and defs for isl38xx fw */ @@ -166,21 +166,13 @@ * for it save old values */ if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) { printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. " - "Using default mode\n", __FUNCTION__); + "Using default mode\n", __FUNCTION__); init_mode = CARD_DEFAULT_IW_MODE; } /* This sets all of the mode-dependent values */ prism54_mib_mode_helper(priv, init_mode); } -void -prism54_mib_init_work(islpci_private *priv) -{ - down_write(&priv->mib_sem); - mgt_commit(priv); - up_write(&priv->mib_sem); -} - /* this will be executed outside of atomic context thanks to * schedule_work(), thus we can as well use sleeping semaphore * locking */ @@ -195,16 +187,9 @@ if (down_interruptible(&priv->stats_sem)) return; -/* missing stats are : - * iwstatistics.qual.updated - * iwstatistics.discard.nwid - * iwstatistics.discard.fragment - * iwstatistics.discard.misc - * iwstatistics.miss.beacon */ - /* Noise floor. * I'm not sure if the unit is dBm. - * Note : If we are not connected, this value seems to be irrevelant. */ + * Note : If we are not connected, this value seems to be irrelevant. */ mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); priv->local_iwstatistics.qual.noise = r.u; @@ -216,8 +201,7 @@ data = r.ptr; /* copy this MAC to the bss */ - for (j = 0; j < 6; j++) - bss.address[j] = data[j]; + memcpy(bss.address, data, 6); kfree(data); /* now ask for the corresponding bss */ @@ -426,7 +410,6 @@ /* by default the card sets this to 20. */ sens = vwrq->disabled ? 20 : vwrq->value; - /* set the ed threshold. */ return mgt_set_request(priv, DOT11_OID_EDTHRESHOLD, 0, &sens); } @@ -505,7 +488,7 @@ return 0; /* Request the device for the supported frequencies - * not really revelant since some devices will report the 5 GHz band + * not really relevant since some devices will report the 5 GHz band * frequencies even if they don't support them. */ rvalue = @@ -515,21 +498,12 @@ range->num_channels = freq->nr; range->num_frequency = freq->nr; - /* Frequencies are not listed in the right order. The reordering is probably - * firmware dependant and thus should work for everyone. - */ m = min(IW_MAX_FREQUENCIES, (int) freq->nr); - for (i = 0; i < m - 12; i++) { - range->freq[i].m = freq->mhz[12 + i]; + for (i = 0; i < m; i++) { + range->freq[i].m = freq->mhz[i]; range->freq[i].e = 6; - range->freq[i].i = i + 1; + range->freq[i].i = channel_of_freq(freq->mhz[i]); } - for (i = m - 12; i < m; i++) { - range->freq[i].m = freq->mhz[i - m + 12]; - range->freq[i].e = 6; - range->freq[i].i = i + 23; - } - kfree(freq); rvalue |= mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r); @@ -544,9 +518,7 @@ i++; data++; } - range->num_bitrates = i; - kfree(r.ptr); return rvalue; @@ -585,7 +557,6 @@ int rvalue; rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); - memcpy(awrq->sa_data, r.ptr, 6); awrq->sa_family = ARPHRD_ETHER; kfree(r.ptr); @@ -658,8 +629,8 @@ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); /* Add frequency. (short) bss->channel is the frequency in MHz */ - iwe.u.freq.m = bss->channel; - iwe.u.freq.e = 6; + iwe.u.freq.m = channel_of_freq(bss->channel); + iwe.u.freq.e = 0; iwe.cmd = SIOCGIWFREQ; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); @@ -695,7 +666,6 @@ kfree(buf); } } - return current_ev; } @@ -722,7 +692,7 @@ /* Ask the device for a list of known bss. We can report at most * IW_MAX_AP=64 to the range struct. But the device won't repport anything - * if you change the value of MAXBSS=24. Anyway 24 AP It is probably enough. + * if you change the value of IWMAX_BSS=24. */ rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); bsslist = r.ptr; @@ -757,7 +727,7 @@ memcpy(essid.octets, extra, dwrq->length); } else essid.length = 0; - + if (priv->iw_mode != IW_MODE_MONITOR) return mgt_set_request(priv, DOT11_OID_SSID, 0, &essid); @@ -843,21 +813,21 @@ char *data; int ret, i; union oid_res_t r; - + if (vwrq->value == -1) { /* auto mode. No limit. */ profile = 1; return mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); } - + if ((ret = mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r))) return ret; - + rate = (u32) (vwrq->value / 500000); data = r.ptr; i = 0; - + while (data[i]) { if (rate && (data[i] == rate)) { break; @@ -868,14 +838,14 @@ data[i] |= 0x80; i++; } - + if (!data[i]) { return -EINVAL; } - + data[i] |= 0x80; data[i + 1] = 0; - + /* Now, check if we want a fixed or auto value */ if (vwrq->fixed) { data[0] = data[i]; @@ -890,14 +860,14 @@ i++; } printk("0\n"); -*/ +*/ profile = -1; ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data); ret |= mgt_set_request(priv, DOT11_OID_RATES, 0, data); - + kfree(r.ptr); - + return ret; } @@ -923,7 +893,7 @@ data = r.ptr; vwrq->fixed = (data[0] != 0) && (data[1] == 0); kfree(r.ptr); - + return 0; } @@ -979,8 +949,6 @@ * small frame <=> smaller than the rts threshold * This is not really the behavior expected by the wireless tool but it seems * to be a common behavior in other drivers. - * - * It seems that playing with this tends to hang the card -> DISABLED */ static int @@ -1012,18 +980,16 @@ lifetime = vwrq->value / 1024; /* now set what is requested */ - - if (slimit != 0) + if (slimit) rvalue = mgt_set_request(priv, DOT11_OID_SHORTRETRIES, 0, &slimit); - if (llimit != 0) + if (llimit) rvalue |= mgt_set_request(priv, DOT11_OID_LONGRETRIES, 0, &llimit); - if (lifetime != 0) + if (lifetime) rvalue |= mgt_set_request(priv, DOT11_OID_MAXTXLIFETIME, 0, &lifetime); - return rvalue; } @@ -1119,8 +1085,7 @@ } } } - - /* now read the flags */ + /* now read the flags */ if (dwrq->flags & IW_ENCODE_DISABLED) { /* Encoding disabled, * authen = DOT11_AUTH_OS; @@ -1269,13 +1234,8 @@ static int prism54_set_u32(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) + __u32 * uwrq, char *extra) { - /* - u32 *i = (int *) extra; - int param = *i; - int u = *(i + 1); - */ u32 oid = uwrq[0], u = uwrq[1]; return mgt_set_request((islpci_private *) ndev->priv, oid, 0, &u); @@ -1846,9 +1806,7 @@ 0); break; - /* Note : the following should never happen since we don't run the card in - * extended mode. - * Note : "mlme" is actually a "struct obj_mlmeex *" here, but this + /* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this * is backward compatible layout-wise with "struct obj_mlme". */ @@ -1893,7 +1851,8 @@ struct net_device *ndev = frame->ndev; enum oid_num_t n = mgt_oidtonum(frame->header->oid); - prism54_process_trap_helper(netdev_priv(ndev), n, frame->data); + if (n != OID_NUM_LAST) + prism54_process_trap_helper(netdev_priv(ndev), n, frame->data); islpci_mgt_release(frame); } @@ -1966,65 +1925,11 @@ } int -prism54_set_maxframeburst(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 max_burst; - - max_burst = (*uwrq) ? *uwrq : CARD_DEFAULT_MAXFRAMEBURST; - mgt_set_request(priv, DOT11_OID_MAXFRAMEBURST, 0, &max_burst); - - return -EINPROGRESS; /* Call commit handler */ -} - -int -prism54_get_maxframeburst(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_MAXFRAMEBURST, 0, NULL, &r); - *uwrq = r.u; - - return rvalue; -} - -int -prism54_set_profile(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 profile; - - profile = (*uwrq) ? *uwrq : CARD_DEFAULT_PROFILE; - mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); - - return -EINPROGRESS; /* Call commit handler */ -} - -int -prism54_get_profile(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_PROFILES, 0, NULL, &r); - *uwrq = r.u; - - return rvalue; -} - -int prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - + priv->priv_oid = *uwrq; printk("%s: oid 0x%08X\n", ndev->name, *uwrq); @@ -2033,15 +1938,15 @@ int prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); struct islpci_mgmtframe *response = NULL; int ret = -EIO, response_op = PIMFOR_OP_ERROR; - + printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid); data->length = 0; - + if (islpci_get_state(priv) >= PRV_STATE_INIT) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, @@ -2065,21 +1970,21 @@ printk("%s: len: %i\n", ndev->name, data->length); } } - + return ret; } int prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); struct islpci_mgmtframe *response = NULL; int ret = 0, response_op = PIMFOR_OP_ERROR; - + printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid, data->length); - + if (islpci_get_state(priv) >= PRV_STATE_INIT) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, @@ -2094,11 +1999,11 @@ } if (ret || response_op == PIMFOR_OP_ERROR) { printk("%s: EIO\n", ndev->name); - ret = -EIO; + ret = -EIO; } } - - return ret; + + return (ret ? ret : -EINPROGRESS); } static int @@ -2196,7 +2101,7 @@ #define PRISM54_DBG_GET_OID SIOCIWFIRSTPRIV+15 #define PRISM54_DBG_SET_OID SIOCIWFIRSTPRIV+16 -#define PRISM54_GET_OID SIOCIWFIRSTPRIV+17 +#define PRISM54_GET_OID SIOCIWFIRSTPRIV+17 #define PRISM54_SET_OID_U32 SIOCIWFIRSTPRIV+18 #define PRISM54_SET_OID_STR SIOCIWFIRSTPRIV+20 #define PRISM54_SET_OID_ADDR SIOCIWFIRSTPRIV+22 @@ -2204,16 +2109,16 @@ #define PRISM54_GET_PRISMHDR SIOCIWFIRSTPRIV+23 #define PRISM54_SET_PRISMHDR SIOCIWFIRSTPRIV+24 -#define IWPRIV_SET_U32(n,x) { n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x } -#define IWPRIV_SET_SSID(n,x) { n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x } -#define IWPRIV_SET_ADDR(n,x) { n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "set_"x } -#define IWPRIV_GET(n,x) { n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "get_"x } +#define IWPRIV_SET_U32(n,x) { n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_SET_SSID(n,x) { n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_SET_ADDR(n,x) { n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_GET(n,x) { n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "g_"x } #define IWPRIV_U32(n,x) IWPRIV_SET_U32(n,x), IWPRIV_GET(n,x) #define IWPRIV_SSID(n,x) IWPRIV_SET_SSID(n,x), IWPRIV_GET(n,x) #define IWPRIV_ADDR(n,x) IWPRIV_SET_ADDR(n,x), IWPRIV_GET(n,x) -/* Note : limited to 128 private ioctls */ +/* Note : limited to 128 private ioctls (wireless tools 26) */ static const struct iw_priv_args prism54_private_args[] = { /*{ cmd, set_args, get_args, name } */ @@ -2241,7 +2146,7 @@ {PRISM54_DBG_OID, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dbg_oid"}, {PRISM54_DBG_GET_OID, 0, IW_PRIV_TYPE_BYTE | 256, "dbg_get_oid"}, - {PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_get_oid"}, + {PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_set_oid"}, /* --- sub-ioctls handlers --- */ {PRISM54_GET_OID, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, ""}, @@ -2268,7 +2173,7 @@ IWPRIV_U32(DOT11_OID_AUTHENABLE, "authenable"), IWPRIV_U32(DOT11_OID_PRIVACYINVOKED, "privinvok"), IWPRIV_U32(DOT11_OID_EXUNENCRYPTED, "exunencrypt"), - + IWPRIV_U32(DOT11_OID_REKEYTHRESHOLD, "rekeythresh"), IWPRIV_U32(DOT11_OID_MAXTXLIFETIME, "maxtxlife"), @@ -2351,5 +2256,6 @@ int prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) { + return -EOPNOTSUPP; } diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h --- a/drivers/net/wireless/prism54/isl_ioctl.h 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/isl_ioctl.h 2004-06-13 23:56:44 -07:00 @@ -30,7 +30,6 @@ #define SUPPORTED_WIRELESS_EXT 16 void prism54_mib_init(islpci_private *); -void prism54_mib_init_work(islpci_private *); struct iw_statistics *prism54_get_wireless_stats(struct net_device *); void prism54_update_stats(islpci_private *); diff -Nru a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c --- a/drivers/net/wireless/prism54/islpci_dev.c 2004-06-13 23:56:43 -07:00 +++ b/drivers/net/wireless/prism54/islpci_dev.c 2004-06-13 23:56:44 -07:00 @@ -30,6 +30,7 @@ #include +#include "prismcompat.h" #include "isl_38xx.h" #include "isl_ioctl.h" #include "islpci_dev.h" @@ -37,12 +38,6 @@ #include "islpci_eth.h" #include "oid_mgt.h" -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) -#define prism54_synchronize_irq(irq) synchronize_irq() -#else -#define prism54_synchronize_irq(irq) synchronize_irq(irq) -#endif - #define ISL3877_IMAGE_FILE "isl3877" #define ISL3890_IMAGE_FILE "isl3890" @@ -55,6 +50,125 @@ * ndev->set_mac_address. Jean II */ const unsigned char dummy_mac[6] = { 0x00, 0x30, 0xB4, 0x00, 0x00, 0x00 }; +static int +isl_upload_firmware(islpci_private *priv) +{ + u32 reg, rc; + void *device_base = priv->device_base; + + /* clear the RAMBoot and the Reset bit */ + reg = readl(device_base + ISL38XX_CTRL_STAT_REG); + reg &= ~ISL38XX_CTRL_STAT_RESET; + reg &= ~ISL38XX_CTRL_STAT_RAMBOOT; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* set the Reset bit without reading the register ! */ + reg |= ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* clear the Reset bit */ + reg &= ~ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + wmb(); + + /* wait a while for the device to reboot */ + mdelay(50); + + { + const struct firmware *fw_entry = 0; + long fw_len; + const u32 *fw_ptr; + + rc = request_firmware(&fw_entry, priv->firmware, PRISM_FW_PDEV); + if (rc) { + printk(KERN_ERR + "%s: request_firmware() failed for '%s'\n", + "prism54", priv->firmware); + return rc; + } + /* prepare the Direct Memory Base register */ + reg = ISL38XX_DEV_FIRMWARE_ADDRES; + + fw_ptr = (u32 *) fw_entry->data; + fw_len = fw_entry->size; + + if (fw_len % 4) { + printk(KERN_ERR + "%s: firmware '%s' size is not multiple of 32bit, aborting!\n", + "prism54", priv->firmware); + release_firmware(fw_entry); + return EILSEQ; /* Illegal byte sequence */; + } + + while (fw_len > 0) { + long _fw_len = + (fw_len > + ISL38XX_MEMORY_WINDOW_SIZE) ? + ISL38XX_MEMORY_WINDOW_SIZE : fw_len; + u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; + + /* set the cards base address for writting the data */ + isl38xx_w32_flush(device_base, reg, + ISL38XX_DIR_MEM_BASE_REG); + wmb(); /* be paranoid */ + + /* increment the write address for next iteration */ + reg += _fw_len; + fw_len -= _fw_len; + + /* write the data to the Direct Memory Window 32bit-wise */ + /* memcpy_toio() doesn't guarantee 32bit writes :-| */ + while (_fw_len > 0) { + /* use non-swapping writel() */ + __raw_writel(*fw_ptr, dev_fw_ptr); + fw_ptr++, dev_fw_ptr++; + _fw_len -= 4; + } + + /* flush PCI posting */ + (void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH); + wmb(); /* be paranoid again */ + + BUG_ON(_fw_len != 0); + } + + BUG_ON(fw_len != 0); + + release_firmware(fw_entry); + } + + /* now reset the device + * clear the Reset & ClkRun bit, set the RAMBoot bit */ + reg = readl(device_base + ISL38XX_CTRL_STAT_REG); + reg &= ~ISL38XX_CTRL_STAT_CLKRUN; + reg &= ~ISL38XX_CTRL_STAT_RESET; + reg |= ISL38XX_CTRL_STAT_RAMBOOT; + isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG); + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* set the reset bit latches the host override and RAMBoot bits + * into the device for operation when the reset bit is reset */ + reg |= ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + /* don't do flush PCI posting here! */ + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + /* clear the reset bit should start the whole circus */ + reg &= ~ISL38XX_CTRL_STAT_RESET; + writel(reg, device_base + ISL38XX_CTRL_STAT_REG); + /* don't do flush PCI posting here! */ + wmb(); + udelay(ISL38XX_WRITEIO_DELAY); + + return 0; +} + /****************************************************************************** Device Interrupt Handler ******************************************************************************/ @@ -74,7 +188,9 @@ if (reg & ISL38XX_CTRL_STAT_SLEEPMODE) /* device is in sleep mode, IRQ was generated by someone else */ { - printk(KERN_DEBUG "Assuming someone else called the IRQ\n"); +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); +#endif return IRQ_NONE; } @@ -324,14 +440,7 @@ printk(KERN_DEBUG "%s: uploading firmware...\n", priv->ndev->name); - rc = isl38xx_upload_firmware(priv->firmware, -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75)) - &priv->pdev->dev, -#else - pci_name(priv->pdev), -#endif - priv->device_base, - priv->device_host_address); + rc = isl_upload_firmware(priv); if (rc) { /* error uploading the firmware */ printk(KERN_ERR "%s: could not upload firmware ('%s')\n", @@ -357,15 +466,8 @@ int result = -ETIME; int count; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - /* This is 2.6 specific, nicer, shorter, but not in 2.4 yet */ DEFINE_WAIT(wait); prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE); -#else - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&priv->reset_done, &wait); -#endif /* now the last step is to reset the interface */ isl38xx_interface_reset(priv->device_base, priv->device_host_address); @@ -390,13 +492,7 @@ } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - /* 2.6 specific too */ finish_wait(&priv->reset_done, &wait); -#else - remove_wait_queue(&priv->reset_done, &wait); - set_current_state(TASK_RUNNING); -#endif if(result) return result; @@ -410,7 +506,9 @@ * the IRQ line until we know for sure the reset went through */ isl38xx_enable_common_interrupts(priv->device_base); - prism54_mib_init_work(priv); + down_write(&priv->mib_sem); + mgt_commit(priv); + up_write(&priv->mib_sem); islpci_set_state(priv, PRV_STATE_READY); @@ -448,9 +546,9 @@ /* reset the mgmt receive queue */ for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) { isl38xx_fragment *frag = &cb->rx_data_mgmt[counter]; - frag->size = MGMT_FRAME_SIZE; + frag->size = cpu_to_le16(MGMT_FRAME_SIZE); frag->flags = 0; - frag->address = priv->mgmt_rx[counter].pci_addr; + frag->address = cpu_to_le32(priv->mgmt_rx[counter].pci_addr); } for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { @@ -580,6 +678,7 @@ skb = NULL; goto out_free; } + skb_reserve(skb, (4 - (long) skb->data) & 0x03); /* add the new allocated sk_buff to the buffer array */ priv->data_low_rx[counter] = skb; diff -Nru a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h --- a/drivers/net/wireless/prism54/islpci_dev.h 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/islpci_dev.h 2004-06-13 23:56:44 -07:00 @@ -29,20 +29,6 @@ #include #include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) -# include -#else -# include -# define work_struct tq_struct -# define INIT_WORK INIT_TQUEUE -# define schedule_work schedule_task -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) -#define free_netdev(x) kfree(x) -#define pci_name(x) x->slot_name -#endif - #include "isl_38xx.h" #include "isl_oid.h" #include "islpci_mgt.h" @@ -187,7 +173,7 @@ islpci_state_t state; int state_off; /* enumeration of off-state, if 0 then * we're not in any off-state */ - + /* WPA stuff */ int wpa; /* WPA mode enabled */ struct list_head bss_wpa_list; @@ -209,12 +195,6 @@ islpci_state_t islpci_set_state(islpci_private *priv, islpci_state_t new_state); #define ISLPCI_TX_TIMEOUT (2*HZ) - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,75)) -# define irqreturn_t void -# define IRQ_HANDLED -# define IRQ_NONE -#endif irqreturn_t islpci_interrupt(int, void *, struct pt_regs *); diff -Nru a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c --- a/drivers/net/wireless/prism54/islpci_eth.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/islpci_eth.c 2004-06-13 23:56:44 -07:00 @@ -26,6 +26,7 @@ #include #include +#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_eth.h" #include "islpci_mgt.h" @@ -104,7 +105,7 @@ /* check whether the destination queue has enough fragments for the frame */ curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]); - if (curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE) { + if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) { printk(KERN_ERR "%s: transmit device queue full when awake\n", ndev->name); netif_stop_queue(ndev); @@ -120,7 +121,7 @@ /* Check alignment and WDS frame formatting. The start of the packet should * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes * and add WDS address information */ - if (((long) skb->data & 0x03) | init_wds) { + if (unlikely(((long) skb->data & 0x03) | init_wds)) { /* get the number of bytes to add and re-allign */ offset = (4 - (long) skb->data) & 0x03; offset += init_wds ? 6 : 0; @@ -191,7 +192,7 @@ pci_map_address = pci_map_single(priv->pdev, (void *) skb->data, skb->len, PCI_DMA_TODEVICE); - if (pci_map_address == 0) { + if (unlikely(pci_map_address == 0)) { printk(KERN_WARNING "%s: cannot map buffer to PCI\n", ndev->name); @@ -207,7 +208,7 @@ priv->data_low_tx[index] = skb; /* set the proper fragment start address and size information */ fragment->size = cpu_to_le16(frame_size); - fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ + fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ fragment->address = cpu_to_le32(pci_map_address); curr_frag++; @@ -217,7 +218,7 @@ cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ] = cpu_to_le32(curr_frag); if (curr_frag - priv->free_data_tx + ISL38XX_MIN_QTHRESHOLD - > ISL38XX_CB_TX_QSIZE) { + > ISL38XX_CB_TX_QSIZE) { /* stop sends from upper layers */ netif_stop_queue(ndev); @@ -238,7 +239,7 @@ return 0; - drop_free: + drop_free: /* free the skbuf structure before aborting */ dev_kfree_skb(skb); skb = NULL; @@ -261,9 +262,9 @@ if (priv->ndev->type == ARPHRD_IEEE80211_PRISM) { struct avs_80211_1_header *avs; /* extract the relevant data from the header */ - u32 clock = hdr->clock; + u32 clock = le32_to_cpu(hdr->clock); u8 rate = hdr->rate; - u16 freq = be16_to_cpu(hdr->freq); + u16 freq = le16_to_cpu(hdr->freq); u8 rssi = hdr->rssi; skb_pull(*skb, sizeof (struct rfmon_header)); @@ -274,7 +275,7 @@ avs_80211_1_header), 0, GFP_ATOMIC); if (newskb) { - kfree_skb(*skb); + dev_kfree_skb_irq(*skb); *skb = newskb; } else return -1; @@ -286,21 +287,21 @@ (struct avs_80211_1_header *) skb_push(*skb, sizeof (struct avs_80211_1_header)); - - avs->version = htonl(P80211CAPTURE_VERSION); - avs->length = htonl(sizeof (struct avs_80211_1_header)); - avs->mactime = __cpu_to_be64(clock); - avs->hosttime = __cpu_to_be64(jiffies); - avs->phytype = htonl(6); /*OFDM: 6 for (g), 8 for (a) */ - avs->channel = htonl(channel_of_freq(freq)); - avs->datarate = htonl(rate * 5); - avs->antenna = htonl(0); /*unknown */ - avs->priority = htonl(0); /*unknown */ - avs->ssi_type = htonl(2); /*2: dBm, 3: raw RSSI */ - avs->ssi_signal = htonl(rssi); - avs->ssi_noise = htonl(priv->local_iwstatistics.qual.noise); /*better than 'undefined', I assume */ - avs->preamble = htonl(0); /*unknown */ - avs->encoding = htonl(0); /*unknown */ + + avs->version = cpu_to_be32(P80211CAPTURE_VERSION); + avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); + avs->mactime = cpu_to_be64(le64_to_cpu(clock)); + avs->hosttime = cpu_to_be64(jiffies); + avs->phytype = cpu_to_be32(6); /*OFDM: 6 for (g), 8 for (a) */ + avs->channel = cpu_to_be32(channel_of_freq(freq)); + avs->datarate = cpu_to_be32(rate * 5); + avs->antenna = cpu_to_be32(0); /*unknown */ + avs->priority = cpu_to_be32(0); /*unknown */ + avs->ssi_type = cpu_to_be32(3); /*2: dBm, 3: raw RSSI */ + avs->ssi_signal = cpu_to_be32(rssi & 0x7f); + avs->ssi_noise = cpu_to_be32(priv->local_iwstatistics.qual.noise); /*better than 'undefined', I assume */ + avs->preamble = cpu_to_be32(0); /*unknown */ + avs->encoding = cpu_to_be32(0); /*unknown */ } else skb_pull(*skb, sizeof (struct rfmon_header)); @@ -381,10 +382,10 @@ skb->dev = ndev; /* take care of monitor mode and spy monitoring. */ - if (priv->iw_mode == IW_MODE_MONITOR) + if (unlikely(priv->iw_mode == IW_MODE_MONITOR)) discard = islpci_monitor_rx(priv, &skb); else { - if (skb->data[2 * ETH_ALEN] == 0) { + if (unlikely(skb->data[2 * ETH_ALEN] == 0)) { /* The packet has a rx_annex. Read it for spy monitoring, Then * remove it, while keeping the 2 leading MAC addr. */ @@ -417,8 +418,8 @@ skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], skb->data[5]); #endif - if (discard) { - dev_kfree_skb(skb); + if (unlikely(discard)) { + dev_kfree_skb_irq(skb); skb = NULL; } else netif_rx(skb); @@ -433,11 +434,13 @@ index - priv->free_data_rx < ISL38XX_CB_RX_QSIZE) { /* allocate an sk_buff for received data frames storage * include any required allignment operations */ - if (skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2), skb == NULL) { + skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); + if (unlikely(skb == NULL)) { /* error allocating an sk_buff structure elements */ DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); break; } + skb_reserve(skb, (4 - (long) skb->data) & 0x03); /* store the new skb structure pointer */ index = index % ISL38XX_CB_RX_QSIZE; priv->data_low_rx[index] = skb; @@ -453,13 +456,13 @@ pci_map_single(priv->pdev, (void *) skb->data, MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); - if (priv->pci_map_rx_address[index] == (dma_addr_t) NULL) { + if (unlikely(priv->pci_map_rx_address[index] == (dma_addr_t) NULL)) { /* error mapping the buffer to device accessable memory address */ DEBUG(SHOW_ERROR_MESSAGES, "Error mapping DMA address\n"); /* free the skbuf structure before aborting */ - dev_kfree_skb((struct sk_buff *) skb); + dev_kfree_skb_irq((struct sk_buff *) skb); skb = NULL; break; } @@ -484,10 +487,10 @@ void islpci_do_reset_and_wake(void *data) { - islpci_private *priv = (islpci_private *) data; - islpci_reset(priv, 1); - netif_wake_queue(priv->ndev); - priv->reset_task_pending = 0; + islpci_private *priv = (islpci_private *) data; + islpci_reset(priv, 1); + netif_wake_queue(priv->ndev); + priv->reset_task_pending = 0; } void diff -Nru a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c --- a/drivers/net/wireless/prism54/islpci_hotplug.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/islpci_hotplug.c 2004-06-13 23:56:44 -07:00 @@ -24,12 +24,13 @@ #include #include /* For __init, __exit */ +#include "prismcompat.h" #include "islpci_dev.h" #include "islpci_mgt.h" /* for pc_debug */ #include "isl_oid.h" #define DRV_NAME "prism54" -#define DRV_VERSION "1.1" +#define DRV_VERSION "1.2" MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team "); MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter"); diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c --- a/drivers/net/wireless/prism54/islpci_mgt.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/islpci_mgt.c 2004-06-13 23:56:44 -07:00 @@ -22,12 +22,12 @@ #include #include #include -#include #include #include #include +#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_mgt.h" #include "isl_oid.h" /* additional types and defs for isl38xx fw */ @@ -63,7 +63,6 @@ Queue handling for management frames ******************************************************************************/ - /* * Helper function to create a PIMFOR management frame header. */ @@ -86,8 +85,8 @@ { pimfor_header_t *h = data; - while ((void *) h < data + len) { - if(h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) { + while ((void *) h < data + len) { + if (h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) { le32_to_cpus(&h->oid); le32_to_cpus(&h->length); } else { @@ -108,8 +107,8 @@ islpci_mgmt_rx_fill(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); #if VERBOSE > SHOW_ERROR_MESSAGES @@ -124,7 +123,8 @@ if (buf->mem == NULL) { buf->mem = kmalloc(MGMT_FRAME_SIZE, GFP_ATOMIC); if (!buf->mem) { - printk(KERN_WARNING "Error allocating management frame.\n"); + printk(KERN_WARNING + "Error allocating management frame.\n"); return -ENOMEM; } buf->size = MGMT_FRAME_SIZE; @@ -133,24 +133,24 @@ buf->pci_addr = pci_map_single(priv->pdev, buf->mem, MGMT_FRAME_SIZE, PCI_DMA_FROMDEVICE); - if(!buf->pci_addr) { - printk(KERN_WARNING "Failed to make memory DMA'able\n."); + if (!buf->pci_addr) { + printk(KERN_WARNING + "Failed to make memory DMA'able\n."); return -ENOMEM; } } - /* be safe: always reset control block information */ + /* be safe: always reset control block information */ frag->size = cpu_to_le16(MGMT_FRAME_SIZE); frag->flags = 0; frag->address = cpu_to_le32(buf->pci_addr); curr++; - /* The fragment address in the control block must have - * been written before announcing the frame buffer to - * device */ + /* The fragment address in the control block must have + * been written before announcing the frame buffer to + * device */ wmb(); - cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = - cpu_to_le32(curr); + cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = cpu_to_le32(curr); } return 0; } @@ -168,7 +168,7 @@ { islpci_private *priv = netdev_priv(ndev); isl38xx_control_block *cb = - (isl38xx_control_block *) priv->control_block; + (isl38xx_control_block *) priv->control_block; void *p; int err = -EINVAL; unsigned long flags; @@ -242,25 +242,25 @@ priv->mgmt_tx[index] = buf; frag = &cb->tx_data_mgmt[index]; frag->size = cpu_to_le16(frag_len); - frag->flags = 0; /* for any other than the last fragment, set to 1 */ + frag->flags = 0; /* for any other than the last fragment, set to 1 */ frag->address = cpu_to_le32(buf.pci_addr); /* The fragment address in the control block must have * been written before announcing the frame buffer to * device */ wmb(); - cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag+1); + cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag + 1); spin_unlock_irqrestore(&priv->slock, flags); /* trigger the device */ islpci_trigger(priv); return 0; - error_unlock: + error_unlock: spin_unlock_irqrestore(&priv->slock, flags); - error_free: + error_free: kfree(buf.mem); - error: + error: return err; } @@ -274,50 +274,49 @@ { islpci_private *priv = netdev_priv(ndev); isl38xx_control_block *cb = - (isl38xx_control_block *) priv->control_block; + (isl38xx_control_block *) priv->control_block; u32 curr_frag; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n"); #endif - - /* Only once per interrupt, determine fragment range to - * process. This avoids an endless loop (i.e. lockup) if - * frames come in faster than we can process them. */ + /* Only once per interrupt, determine fragment range to + * process. This avoids an endless loop (i.e. lockup) if + * frames come in faster than we can process them. */ curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_RX_MGMTQ]); barrier(); - for ( ; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) { + for (; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) { pimfor_header_t *header; u32 index = priv->index_mgmt_rx % ISL38XX_CB_MGMT_QSIZE; struct islpci_membuf *buf = &priv->mgmt_rx[index]; u16 frag_len; int size; struct islpci_mgmtframe *frame; - - /* I have no idea (and no documentation) if flags != 0 - * is possible. Drop the frame, reuse the buffer. */ - if(le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) { - printk(KERN_WARNING "%s: unknown flags 0x%04x\n", - ndev->name, - le16_to_cpu(cb->rx_data_mgmt[index].flags)); - continue; - } + + /* I have no idea (and no documentation) if flags != 0 + * is possible. Drop the frame, reuse the buffer. */ + if (le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) { + printk(KERN_WARNING "%s: unknown flags 0x%04x\n", + ndev->name, + le16_to_cpu(cb->rx_data_mgmt[index].flags)); + continue; + } /* The device only returns the size of the header(s) here. */ frag_len = le16_to_cpu(cb->rx_data_mgmt[index].size); /* - * We appear to have no way to tell the device the - * size of a receive buffer. Thus, if this check - * triggers, we likely have kernel heap corruption. */ - if (frag_len > MGMT_FRAME_SIZE) { - printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\ -n", - ndev->name, frag_len, frag_len); - frag_len = MGMT_FRAME_SIZE; - } + * We appear to have no way to tell the device the + * size of a receive buffer. Thus, if this check + * triggers, we likely have kernel heap corruption. */ + if (frag_len > MGMT_FRAME_SIZE) { + printk(KERN_WARNING + "%s: Bogus packet size of %d (%#x).\n", + ndev->name, frag_len, frag_len); + frag_len = MGMT_FRAME_SIZE; + } /* Ensure the results of device DMA are visible to the CPU. */ pci_dma_sync_single(priv->pdev, buf->pci_addr, @@ -339,30 +338,32 @@ #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_PIMFOR_FRAMES, "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n", - header->operation, header->oid, header->device_id, + header->operation, header->oid, header->device_id, header->flags, header->length); /* display the buffer contents for debugging */ display_buffer((char *) header, PIMFOR_HEADER_SIZE); - display_buffer((char *) header + PIMFOR_HEADER_SIZE, header->length); + display_buffer((char *) header + PIMFOR_HEADER_SIZE, + header->length); #endif /* nobody sends these */ if (header->flags & PIMFOR_FLAG_APPLIC_ORIGIN) { - printk(KERN_DEBUG "%s: errant PIMFOR application frame\n", + printk(KERN_DEBUG + "%s: errant PIMFOR application frame\n", ndev->name); continue; } /* Determine frame size, skipping OID_INL_TUNNEL headers. */ size = PIMFOR_HEADER_SIZE + header->length; - frame = kmalloc(sizeof(struct islpci_mgmtframe) + size, + frame = kmalloc(sizeof (struct islpci_mgmtframe) + size, GFP_ATOMIC); if (!frame) { - printk(KERN_WARNING "%s: Out of memory, cannot handle oid 0x%08x\n", - + printk(KERN_WARNING + "%s: Out of memory, cannot handle oid 0x%08x\n", ndev->name, header->oid); - continue; + continue; } frame->ndev = ndev; memcpy(&frame->buf, header, size); @@ -382,7 +383,7 @@ header->oid, header->device_id, header->flags, header->length); #endif - + /* Create work to handle trap out of interrupt * context. */ INIT_WORK(&frame->ws, prism54_process_trap, frame); @@ -392,14 +393,13 @@ /* Signal the one waiting process that a response * has been received. */ if ((frame = xchg(&priv->mgmt_received, frame)) != NULL) { - printk(KERN_WARNING "%s: mgmt response not collected\n", + printk(KERN_WARNING + "%s: mgmt response not collected\n", ndev->name); kfree(frame); } - #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "Wake up Mgmt Queue\n"); + DEBUG(SHOW_TRACING, "Wake up Mgmt Queue\n"); #endif wake_up(&priv->mgmt_wqueue); } @@ -416,22 +416,22 @@ islpci_mgt_cleanup_transmit(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; u32 curr_frag; #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n"); #endif /* Only once per cleanup, determine fragment range to * process. This avoids an endless loop (i.e. lockup) if * the device became confused, incrementing device_curr_frag * rapidly. */ - curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); + curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); barrier(); - for ( ; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) { + for (; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) { int index = priv->index_mgmt_tx % ISL38XX_CB_MGMT_QSIZE; struct islpci_membuf *buf = &priv->mgmt_tx[index]; pci_unmap_single(priv->pdev, buf->pci_addr, buf->size, @@ -456,23 +456,14 @@ const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000; long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies; int err; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) DEFINE_WAIT(wait); -#else - DECLARE_WAITQUEUE(wait, current); -#endif if (down_interruptible(&priv->mgmt_sem)) return -ERESTARTSYS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) prepare_to_wait(&priv->mgmt_wqueue, &wait, TASK_UNINTERRUPTIBLE); -#else - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&priv->mgmt_wqueue, &wait); -#endif err = islpci_mgt_transmit(ndev, operation, oid, senddata, sendlen); - if(err) + if (err) goto out; err = -ETIMEDOUT; @@ -483,13 +474,24 @@ timeleft = schedule_timeout(wait_cycle_jiffies); frame = xchg(&priv->mgmt_received, NULL); if (frame) { - *recvframe = frame; - err = 0; - goto out; - } - if(timeleft == 0) { - printk(KERN_DEBUG "%s: timeout waiting for mgmt response %lu, trigging device\n", - ndev->name, timeout_left); + if (frame->header->oid == oid) { + *recvframe = frame; + err = 0; + goto out; + } else { + printk(KERN_DEBUG + "%s: expecting oid 0x%x, received 0x%x.\n", + ndev->name, (unsigned int) oid, + frame->header->oid); + kfree(frame); + frame = NULL; + } + } + if (timeleft == 0) { + printk(KERN_DEBUG + "%s: timeout waiting for mgmt response %lu, " + "triggering device\n", + ndev->name, timeout_left); islpci_trigger(priv); } timeout_left += timeleft - wait_cycle_jiffies; @@ -499,12 +501,7 @@ /* TODO: we should reset the device here */ out: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) finish_wait(&priv->mgmt_wqueue, &wait); -#else - remove_wait_queue(&priv->mgmt_wqueue, &wait); - set_current_state(TASK_RUNNING); -#endif up(&priv->mgmt_sem); return err; } diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h --- a/drivers/net/wireless/prism54/islpci_mgt.h 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/islpci_mgt.h 2004-06-13 23:56:44 -07:00 @@ -24,15 +24,6 @@ #include #include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) -# include -#else -# include -# define work_struct tq_struct -# define INIT_WORK INIT_TQUEUE -# define schedule_work schedule_task -#endif - /* * Function definitions */ @@ -43,7 +34,7 @@ #define TRACE(devname) K_DEBUG(SHOW_TRACING, VERBOSE, "%s: -> " __FUNCTION__ "()\n", devname) extern int pc_debug; -static const int init_wds = 0; /* help compiler optimize away dead code */ +const int init_wds = 0; /* help compiler optimize away dead code */ /* General driver definitions */ diff -Nru a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c --- a/drivers/net/wireless/prism54/oid_mgt.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/oid_mgt.c 2004-06-13 23:56:44 -07:00 @@ -16,6 +16,7 @@ * */ +#include "prismcompat.h" #include "islpci_dev.h" #include "islpci_mgt.h" #include "isl_oid.h" @@ -39,17 +40,13 @@ if ((f >= 2412) && (f <= 2484)) { while ((c < 14) && (f != frequency_list_bg[c])) c++; - if (c >= 14) - return 0; + return (c >= 14) ? 0 : ++c; } else if ((f >= (int) 5170) && (f <= (int) 5320)) { while ((c < 12) && (f != frequency_list_a[c])) c++; - if (c >= 12) - return 0; + return (c >= 12) ? 0 : (c + 37); } else return 0; - - return ++c; } #define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t} @@ -449,7 +446,7 @@ if (cache) down_write(&priv->mib_sem); - if (islpci_get_state(priv) >= PRV_STATE_INIT) { + if (islpci_get_state(priv) >= PRV_STATE_READY) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, _data, dlen, &response); if (!ret) { @@ -457,7 +454,7 @@ islpci_mgt_release(response); } if (ret || response_op == PIMFOR_OP_ERROR) - ret = -EIO; + ret = -EIO; } else if (!cache) ret = -EIO; @@ -482,7 +479,7 @@ int ret = -EIO; int reslen = 0; struct islpci_mgmtframe *response = NULL; - + int dlen; void *cache, *_res = NULL; u32 oid; @@ -503,11 +500,11 @@ if (cache) down_read(&priv->mib_sem); - if (islpci_get_state(priv) >= PRV_STATE_INIT) { + if (islpci_get_state(priv) >= PRV_STATE_READY) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, oid, data, dlen, &response); if (ret || !response || - response->header->operation == PIMFOR_OP_ERROR) { + response->header->operation == PIMFOR_OP_ERROR) { if (response) islpci_mgt_release(response); ret = -EIO; @@ -542,9 +539,9 @@ if (reslen > isl_oid[n].size) printk(KERN_DEBUG "mgt_get_request(0x%x): received data length was bigger " - "than expected (%d > %d). Memory is probably corrupted... ", + "than expected (%d > %d). Memory is probably corrupted...", oid, reslen, isl_oid[n].size); - + return ret; } @@ -564,11 +561,11 @@ while (j <= t->range) { response = NULL; ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, - oid, data, t->size, + oid, data, t->size, &response); if (response) { ret |= (response->header->operation == - PIMFOR_OP_ERROR); + PIMFOR_OP_ERROR); islpci_mgt_release(response); } j++; @@ -625,12 +622,32 @@ OID_INL_OUTPUTPOWER, }; +/* update the MAC addr. */ +static int +mgt_update_addr(islpci_private *priv) +{ + struct islpci_mgmtframe *res; + int ret; + + ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, + isl_oid[GEN_OID_MACADDRESS].oid, NULL, + isl_oid[GEN_OID_MACADDRESS].size, &res); + + if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR)) + memcpy(priv->ndev->dev_addr, res->data, 6); + else + ret = -EIO; + if (res) + islpci_mgt_release(res); + + return ret; +} + void mgt_commit(islpci_private *priv) { int rvalue; u32 u; - union oid_res_t r; if (islpci_get_state(priv) < PRV_STATE_INIT) return; @@ -646,21 +663,14 @@ u = OID_INL_MODE; rvalue |= mgt_commit_list(priv, &u, 1); + rvalue |= mgt_update_addr(priv); if (rvalue) { /* some request have failed. The device might be in an incoherent state. We should reset it ! */ printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the " - "device \n", priv->ndev->name); + "device \n", priv->ndev->name); } - - /* update the MAC addr. As it's not cached, no lock will be acquired by - * the mgt_get_request - */ - mgt_get_request(priv, GEN_OID_MACADDRESS, 0, NULL, &r); - memcpy(priv->ndev->dev_addr, r.ptr, 6); - kfree(r.ptr); - } /* This will tell you if you are allowed to answer a mlme(ex) request .*/ @@ -687,13 +697,13 @@ { int i; - for (i = 0; i < OID_NUM_LAST - 1; i++) + for (i = 0; i < OID_NUM_LAST; i++) if (isl_oid[i].oid == oid) return i; printk(KERN_DEBUG "looking for an unknown oid 0x%x", oid); - return 0; + return OID_NUM_LAST; } int @@ -713,8 +723,11 @@ case OID_TYPE_BSS:{ struct obj_bss *bss = r->ptr; return snprintf(str, PRIV_STR_SIZE, - "age=%u\nchannel=%u\n\ - capinfo=0x%X\nrates=0x%X\nbasic_rates=0x%X\n", bss->age, bss->channel, bss->capinfo, bss->rates, bss->basic_rates); + "age=%u\nchannel=%u\n" + "capinfo=0x%X\nrates=0x%X\n" + "basic_rates=0x%X\n", bss->age, + bss->channel, bss->capinfo, + bss->rates, bss->basic_rates); } break; case OID_TYPE_BSSLIST:{ @@ -723,7 +736,9 @@ k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); for (i = 0; i < list->nr; i++) k += snprintf(str + k, PRIV_STR_SIZE - k, - "bss[%u] : \nage=%u\nchannel=%u\ncapinfo=0x%X\nrates=0x%X\nbasic_rates=0x%X\n", + "bss[%u] : \nage=%u\nchannel=%u\n" + "capinfo=0x%X\nrates=0x%X\n" + "basic_rates=0x%X\n", i, list->bsslist[i].age, list->bsslist[i].channel, list->bsslist[i].capinfo, @@ -745,16 +760,17 @@ break; case OID_TYPE_MLME:{ struct obj_mlme *mlme = r->ptr; - return snprintf(str, PRIV_STR_SIZE, "id=0x%X\nstate=0x%X\n\ - code=0x%X\n", mlme->id, mlme->state, - mlme->code); + return snprintf(str, PRIV_STR_SIZE, + "id=0x%X\nstate=0x%X\ncode=0x%X\n", + mlme->id, mlme->state, mlme->code); } break; case OID_TYPE_MLMEEX:{ struct obj_mlmeex *mlme = r->ptr; - return snprintf(str, PRIV_STR_SIZE, "id=0x%X\nstate=0x%X\n\ - code=0x%X\nsize=0x%X\n", mlme->id, mlme->state, - mlme->code, mlme->size); + return snprintf(str, PRIV_STR_SIZE, + "id=0x%X\nstate=0x%X\n" + "code=0x%X\nsize=0x%X\n", mlme->id, + mlme->state, mlme->code, mlme->size); } break; case OID_TYPE_SSID:{ diff -Nru a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h --- a/drivers/net/wireless/prism54/oid_mgt.h 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/wireless/prism54/oid_mgt.h 2004-06-13 23:56:44 -07:00 @@ -38,7 +38,7 @@ int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); int mgt_get_request(islpci_private *, enum oid_num_t, int, void *, - union oid_res_t *); + union oid_res_t *); int mgt_commit_list(islpci_private *, enum oid_num_t *, int); diff -Nru a/drivers/net/wireless/prism54/prismcompat.h b/drivers/net/wireless/prism54/prismcompat.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/net/wireless/prism54/prismcompat.h 2004-06-13 23:56:44 -07:00 @@ -0,0 +1,46 @@ +/* + * (C) 2004 Margit Schubert-While + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * Compatibility header file to aid support of different kernel versions + */ + +#ifdef PRISM54_COMPAT24 +#include "prismcompat24.h" +#else /* PRISM54_COMPAT24 */ + +#ifndef _PRISM_COMPAT_H +#define _PRISM_COMPAT_H + +#include +#include +#include +#include +#include +#include + +#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE) +#error Firmware Loading is not configured in the kernel ! +#endif + +#define prism54_synchronize_irq(irq) synchronize_irq(irq) + +#define PRISM_FW_PDEV &priv->pdev->dev + +#endif /* _PRISM_COMPAT_H */ +#endif /* PRISM54_COMPAT24 */ diff -Nru a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c --- a/drivers/net/yellowfin.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/yellowfin.c 2004-06-13 23:56:44 -07:00 @@ -448,7 +448,7 @@ np = dev->priv; - if (pci_request_regions(pdev, dev->name)) + if (pci_request_regions(pdev, DRV_NAME)) goto err_out_free_netdev; pci_set_master (pdev); @@ -1201,13 +1201,8 @@ break; skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the IP header */ -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, rx_skb->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - rx_skb->tail, pkt_len); -#endif pci_dma_sync_single_for_device(yp->pci_dev, desc->addr, yp->rx_buf_sz, PCI_DMA_FROMDEVICE); diff -Nru a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c --- a/drivers/net/zorro8390.c 2004-06-13 23:56:44 -07:00 +++ b/drivers/net/zorro8390.c 2004-06-13 23:56:44 -07:00 @@ -36,6 +36,8 @@ #include "8390.h" +#define DRV_NAME "zorro8390" + #define NE_BASE (dev->base_addr) #define NE_CMD (0x00*2) #define NE_DATAPORT (0x10*2) /* NatSemi-defined port window offset. */ @@ -115,7 +117,7 @@ if (!dev) return -ENOMEM; SET_MODULE_OWNER(dev); - if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) { + if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) { free_netdev(dev); return -EBUSY; } @@ -198,7 +200,7 @@ dev->irq = IRQ_AMIGA_PORTS; /* Install the Interrupt handler */ - i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, dev->name, dev); + i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, DRV_NAME, dev); if (i) return i; for(i = 0; i < ETHER_ADDR_LEN; i++) {