]> Pileus Git - ~andy/linux/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 25 Apr 2008 19:28:28 +0000 (12:28 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 25 Apr 2008 19:28:28 +0000 (12:28 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (48 commits)
  net: Fix wrong interpretation of some copy_to_user() results.
  xfrm: alg_key_len & alg_icv_len should be unsigned
  [netdrvr] tehuti: move ioctl perm check closer to function start
  ipv6: Fix typo in net/ipv6/Kconfig
  via-velocity: fix vlan receipt
  tg3: sparse cleanup
  forcedeth: realtek phy crossover detection
  ibm_newemac: Increase MDIO timeouts
  gianfar: Fix skb allocation strategy
  netxen: reduce stack usage of netxen_nic_flash_print
  smc911x: test after postfix decrement fails in smc911x_{reset,drop_pkt}
  net drivers: fix platform driver hotplug/coldplug
  forcedeth: new backoff implementation
  ehea: make things static
  phylib: Add support for board-level PHY fixups
  [netdrvr] atlx: code movement: move atl1 parameter parsing
  atlx: remove flash vendor parameter
  korina: misc cleanup
  korina: fix misplaced return statement
  WAN: Fix confusing insmod error code for C101 too.
  ...

67 files changed:
Documentation/networking/phy.txt
drivers/net/arm/at91_ether.c
drivers/net/arm/ep93xx_eth.c
drivers/net/atlx/atl1.c
drivers/net/atlx/atlx.c
drivers/net/ax88796.c
drivers/net/bfin_mac.c
drivers/net/cpmac.c
drivers/net/dm9000.c
drivers/net/e1000e/82571.c
drivers/net/e1000e/defines.h
drivers/net/e1000e/e1000.h
drivers/net/e1000e/es2lan.c
drivers/net/e1000e/ethtool.c
drivers/net/e1000e/hw.h
drivers/net/e1000e/netdev.c
drivers/net/e1000e/phy.c
drivers/net/ehea/ehea_main.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/ibm_newemac/core.c
drivers/net/ibm_newemac/core.h
drivers/net/ibm_newemac/mal.c
drivers/net/ibm_newemac/rgmii.c
drivers/net/ibm_newemac/tah.c
drivers/net/ibm_newemac/zmii.c
drivers/net/igb/igb_main.c
drivers/net/irda/ali-ircc.c
drivers/net/irda/pxaficp_ir.c
drivers/net/irda/sa1100_ir.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/jazzsonic.c
drivers/net/korina.c
drivers/net/macb.c
drivers/net/meth.c
drivers/net/mv643xx_eth.c
drivers/net/netx-eth.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/niu.c
drivers/net/niu.h
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sgiseeq.c
drivers/net/smc911x.c
drivers/net/smc91x.c
drivers/net/sni_82596.c
drivers/net/tehuti.c
drivers/net/tg3.c
drivers/net/tsi108_eth.c
drivers/net/typhoon.c
drivers/net/ucc_geth.c
drivers/net/via-velocity.c
drivers/net/wan/c101.c
drivers/net/wan/hdlc_fr.c
include/linux/phy.h
include/linux/xfrm.h
net/can/raw.c
net/core/ethtool.c
net/dccp/probe.c
net/ipv4/tcp_probe.c
net/ipv6/Kconfig
net/ipv6/raw.c
net/key/af_key.c
net/tipc/socket.c

index 0bc95eab151288d5ba11c2bca8fdc24c2d0c56c8..8df6a7b0e66cdfd3b1de96ed038a062b71be8008 100644 (file)
@@ -1,7 +1,7 @@
 
 -------
 PHY Abstraction Layer
-(Updated 2006-11-30)
+(Updated 2008-04-08)
 
 Purpose
 
@@ -291,3 +291,39 @@ Writing a PHY driver
  Feel free to look at the Marvell, Cicada, and Davicom drivers in
  drivers/net/phy/ for examples (the lxt and qsemi drivers have
  not been tested as of this writing)
+
+Board Fixups
+
+ Sometimes the specific interaction between the platform and the PHY requires
+ special handling.  For instance, to change where the PHY's clock input is,
+ or to add a delay to account for latency issues in the data path.  In order
+ to support such contingencies, the PHY Layer allows platform code to register
+ fixups to be run when the PHY is brought up (or subsequently reset).
+
+ When the PHY Layer brings up a PHY it checks to see if there are any fixups
+ registered for it, matching based on UID (contained in the PHY device's phy_id
+ field) and the bus identifier (contained in phydev->dev.bus_id).  Both must
+ match, however two constants, PHY_ANY_ID and PHY_ANY_UID, are provided as
+ wildcards for the bus ID and UID, respectively.
+
+ When a match is found, the PHY layer will invoke the run function associated
+ with the fixup.  This function is passed a pointer to the phy_device of
+ interest.  It should therefore only operate on that PHY.
+
+ The platform code can either register the fixup using phy_register_fixup():
+
+       int phy_register_fixup(const char *phy_id,
+               u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *));
+
+ Or using one of the two stubs, phy_register_fixup_for_uid() and
+ phy_register_fixup_for_id():
+
+ int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *));
+ int phy_register_fixup_for_id(const char *phy_id,
+               int (*run)(struct phy_device *));
+
+ The stubs set one of the two matching criteria, and set the other one to
+ match anything.
+
index 978e20a1791bda8239cbc213b0e0afebab4461b4..1e39e78f1778c5228d7e6345005e900a347ccbff 100644 (file)
@@ -1248,3 +1248,4 @@ module_exit(at91ether_exit)
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
 MODULE_AUTHOR("Andrew Victor");
+MODULE_ALIAS("platform:" DRV_NAME);
index 91a6590d107b181177a74e0bcd71003e9c4a906c..ecd8fc6146e9faa710351eb8765c8538807bcc51 100644 (file)
@@ -897,6 +897,7 @@ static struct platform_driver ep93xx_eth_driver = {
        .remove         = ep93xx_eth_remove,
        .driver         = {
                .name   = "ep93xx-eth",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -914,3 +915,4 @@ static void __exit ep93xx_eth_cleanup_module(void)
 module_init(ep93xx_eth_init_module);
 module_exit(ep93xx_eth_cleanup_module);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ep93xx-eth");
index 5586fc62468880a0df991cd72d461bf6e5ab77a3..0afe522b8f7b901e2a078ff33739a0a9866299c3 100644 (file)
 /* Temporary hack for merging atl1 and atl2 */
 #include "atlx.c"
 
+/*
+ * This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+#define ATL1_MAX_NIC 4
+
+#define OPTION_UNSET    -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED  1
+
+#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
+
+/*
+ * Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 100 (200us)
+ */
+static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int num_int_mod_timer;
+module_param_array_named(int_mod_timer, int_mod_timer, int,
+       &num_int_mod_timer, 0);
+MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
+
+#define DEFAULT_INT_MOD_CNT    100     /* 200us */
+#define MAX_INT_MOD_CNT                65000
+#define MIN_INT_MOD_CNT                50
+
+struct atl1_option {
+       enum { enable_option, range_option, list_option } type;
+       char *name;
+       char *err;
+       int def;
+       union {
+               struct {        /* range_option info */
+                       int min;
+                       int max;
+               } r;
+               struct {        /* list_option info */
+                       int nr;
+                       struct atl1_opt_list {
+                               int i;
+                               char *str;
+                       } *p;
+               } l;
+       } arg;
+};
+
+static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
+       struct pci_dev *pdev)
+{
+       if (*value == OPTION_UNSET) {
+               *value = opt->def;
+               return 0;
+       }
+
+       switch (opt->type) {
+       case enable_option:
+               switch (*value) {
+               case OPTION_ENABLED:
+                       dev_info(&pdev->dev, "%s enabled\n", opt->name);
+                       return 0;
+               case OPTION_DISABLED:
+                       dev_info(&pdev->dev, "%s disabled\n", opt->name);
+                       return 0;
+               }
+               break;
+       case range_option:
+               if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+                       dev_info(&pdev->dev, "%s set to %i\n", opt->name,
+                               *value);
+                       return 0;
+               }
+               break;
+       case list_option:{
+                       int i;
+                       struct atl1_opt_list *ent;
+
+                       for (i = 0; i < opt->arg.l.nr; i++) {
+                               ent = &opt->arg.l.p[i];
+                               if (*value == ent->i) {
+                                       if (ent->str[0] != '\0')
+                                               dev_info(&pdev->dev, "%s\n",
+                                                       ent->str);
+                                       return 0;
+                               }
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
+               opt->name, *value, opt->err);
+       *value = opt->def;
+       return -1;
+}
+
+/*
+ * atl1_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input.  If an invalid value is given, or if no user specified
+ * value exists, a default value is used.  The final value is stored
+ * in a variable in the adapter structure.
+ */
+void __devinit atl1_check_options(struct atl1_adapter *adapter)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       int bd = adapter->bd_number;
+       if (bd >= ATL1_MAX_NIC) {
+               dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
+               dev_notice(&pdev->dev, "using defaults for all values\n");
+       }
+       {                       /* Interrupt Moderate Timer */
+               struct atl1_option opt = {
+                       .type = range_option,
+                       .name = "Interrupt Moderator Timer",
+                       .err = "using default of "
+                               __MODULE_STRING(DEFAULT_INT_MOD_CNT),
+                       .def = DEFAULT_INT_MOD_CNT,
+                       .arg = {.r = {.min = MIN_INT_MOD_CNT,
+                                       .max = MAX_INT_MOD_CNT} }
+               };
+               int val;
+               if (num_int_mod_timer > bd) {
+                       val = int_mod_timer[bd];
+                       atl1_validate_option(&val, &opt, pdev);
+                       adapter->imt = (u16) val;
+               } else
+                       adapter->imt = (u16) (opt.def);
+       }
+}
+
 /*
  * atl1_pci_tbl - PCI Device ID Table
  */
index 4186326d1b9426d5c4f00c5324daf2919ceffeed..f06b854e2501b88ed7f3799bc53438357876add4 100644 (file)
@@ -253,181 +253,4 @@ static void atlx_restore_vlan(struct atlx_adapter *adapter)
        atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp);
 }
 
-/*
- * This is the only thing that needs to be changed to adjust the
- * maximum number of ports that the driver can manage.
- */
-#define ATL1_MAX_NIC 4
-
-#define OPTION_UNSET    -1
-#define OPTION_DISABLED 0
-#define OPTION_ENABLED  1
-
-#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
-
-/*
- * Interrupt Moderate Timer in units of 2 us
- *
- * Valid Range: 10-65535
- *
- * Default Value: 100 (200us)
- */
-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
-static int num_int_mod_timer;
-module_param_array_named(int_mod_timer, int_mod_timer, int,
-       &num_int_mod_timer, 0);
-MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
-
-/*
- * flash_vendor
- *
- * Valid Range: 0-2
- *
- * 0 - Atmel
- * 1 - SST
- * 2 - ST
- *
- * Default Value: 0
- */
-static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
-static int num_flash_vendor;
-module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0);
-MODULE_PARM_DESC(flash_vendor, "SPI flash vendor");
-
-#define DEFAULT_INT_MOD_CNT    100     /* 200us */
-#define MAX_INT_MOD_CNT                65000
-#define MIN_INT_MOD_CNT                50
-
-#define FLASH_VENDOR_DEFAULT   0
-#define FLASH_VENDOR_MIN       0
-#define FLASH_VENDOR_MAX       2
-
-struct atl1_option {
-       enum { enable_option, range_option, list_option } type;
-       char *name;
-       char *err;
-       int def;
-       union {
-               struct {        /* range_option info */
-                       int min;
-                       int max;
-               } r;
-               struct {        /* list_option info */
-                       int nr;
-                       struct atl1_opt_list {
-                               int i;
-                               char *str;
-                       } *p;
-               } l;
-       } arg;
-};
-
-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
-       struct pci_dev *pdev)
-{
-       if (*value == OPTION_UNSET) {
-               *value = opt->def;
-               return 0;
-       }
-
-       switch (opt->type) {
-       case enable_option:
-               switch (*value) {
-               case OPTION_ENABLED:
-                       dev_info(&pdev->dev, "%s enabled\n", opt->name);
-                       return 0;
-               case OPTION_DISABLED:
-                       dev_info(&pdev->dev, "%s disabled\n", opt->name);
-                       return 0;
-               }
-               break;
-       case range_option:
-               if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-                       dev_info(&pdev->dev, "%s set to %i\n", opt->name,
-                               *value);
-                       return 0;
-               }
-               break;
-       case list_option:{
-                       int i;
-                       struct atl1_opt_list *ent;
-
-                       for (i = 0; i < opt->arg.l.nr; i++) {
-                               ent = &opt->arg.l.p[i];
-                               if (*value == ent->i) {
-                                       if (ent->str[0] != '\0')
-                                               dev_info(&pdev->dev, "%s\n",
-                                                       ent->str);
-                                       return 0;
-                               }
-                       }
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       dev_info(&pdev->dev, "invalid %s specified (%i) %s\n",
-               opt->name, *value, opt->err);
-       *value = opt->def;
-       return -1;
-}
-
-/*
- * atl1_check_options - Range Checking for Command Line Parameters
- * @adapter: board private structure
- *
- * This routine checks all command line parameters for valid user
- * input.  If an invalid value is given, or if no user specified
- * value exists, a default value is used.  The final value is stored
- * in a variable in the adapter structure.
- */
-void __devinit atl1_check_options(struct atl1_adapter *adapter)
-{
-       struct pci_dev *pdev = adapter->pdev;
-       int bd = adapter->bd_number;
-       if (bd >= ATL1_MAX_NIC) {
-               dev_notice(&pdev->dev, "no configuration for board#%i\n", bd);
-               dev_notice(&pdev->dev, "using defaults for all values\n");
-       }
-       {                       /* Interrupt Moderate Timer */
-               struct atl1_option opt = {
-                       .type = range_option,
-                       .name = "Interrupt Moderator Timer",
-                       .err = "using default of "
-                               __MODULE_STRING(DEFAULT_INT_MOD_CNT),
-                       .def = DEFAULT_INT_MOD_CNT,
-                       .arg = {.r = {.min = MIN_INT_MOD_CNT,
-                                       .max = MAX_INT_MOD_CNT} }
-               };
-               int val;
-               if (num_int_mod_timer > bd) {
-                       val = int_mod_timer[bd];
-                       atl1_validate_option(&val, &opt, pdev);
-                       adapter->imt = (u16) val;
-               } else
-                       adapter->imt = (u16) (opt.def);
-       }
-
-       {                       /* Flash Vendor */
-               struct atl1_option opt = {
-                       .type = range_option,
-                       .name = "SPI Flash Vendor",
-                       .err = "using default of "
-                               __MODULE_STRING(FLASH_VENDOR_DEFAULT),
-                       .def = DEFAULT_INT_MOD_CNT,
-                       .arg = {.r = {.min = FLASH_VENDOR_MIN,
-                                       .max = FLASH_VENDOR_MAX} }
-               };
-               int val;
-               if (num_flash_vendor > bd) {
-                       val = flash_vendor[bd];
-                       atl1_validate_option(&val, &opt, pdev);
-                       adapter->hw.flash_vendor = (u8) val;
-               } else
-                       adapter->hw.flash_vendor = (u8) (opt.def);
-       }
-}
-
 #endif /* ATLX_C */
index 194949afacd05142655f7d1a42e00b8b894f6697..0b4adf4a0f7da9ab772ca84bc1d4738ca034c263 100644 (file)
@@ -1005,3 +1005,4 @@ module_exit(axdrv_exit);
 MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ax88796");
index 717dcc1aa1e97acb8bfddf2e44e97cc51cb8a8f7..4fec8581bfd7bb80e5c7a49ae7c548532f263cf7 100644 (file)
@@ -47,6 +47,7 @@
 MODULE_AUTHOR(DRV_AUTHOR);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION(DRV_DESC);
+MODULE_ALIAS("platform:bfin_mac");
 
 #if defined(CONFIG_BFIN_MAC_USE_L1)
 # define bfin_mac_alloc(dma_handle, size)  l1_data_sram_zalloc(size)
@@ -1089,8 +1090,9 @@ static struct platform_driver bfin_mac_driver = {
        .resume = bfin_mac_resume,
        .suspend = bfin_mac_suspend,
        .driver = {
-                  .name = DRV_NAME,
-                  },
+               .name = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
 };
 
 static int __init bfin_mac_init(void)
@@ -1106,3 +1108,4 @@ static void __exit bfin_mac_cleanup(void)
 }
 
 module_exit(bfin_mac_cleanup);
+
index 9da7ff437031fec11854152851c344608ec183ff..2b5740b3d1825dee5b91f9b3862060e71c266f8b 100644 (file)
@@ -42,6 +42,7 @@
 MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>");
 MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cpmac");
 
 static int debug_level = 8;
 static int dumb_switch;
@@ -1103,6 +1104,7 @@ static int __devexit cpmac_remove(struct platform_device *pdev)
 
 static struct platform_driver cpmac_driver = {
        .driver.name = "cpmac",
+       .driver.owner = THIS_MODULE,
        .probe = cpmac_probe,
        .remove = __devexit_p(cpmac_remove),
 };
index d63cc93f055dfd2be2c8a493a514b20a743fd9fa..e6fe2614ea6dc3a9f2db6928cce6393b75498475 100644 (file)
@@ -1418,3 +1418,4 @@ module_exit(dm9000_cleanup);
 MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
 MODULE_DESCRIPTION("Davicom DM9000 network driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:dm9000");
index 01c88664bad30934e11d3c7ad9d4164d8e73bf7e..462351ca2c81ac991a088b971a0bc46b1f51c5a7 100644 (file)
@@ -1326,12 +1326,10 @@ struct e1000_info e1000_82571_info = {
        .mac                    = e1000_82571,
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_JUMBO_FRAMES
-                                 | FLAG_HAS_STATS_PTC_PRC
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
                                  | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
-                                 | FLAG_HAS_STATS_ICR_ICT
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_RESET_OVERWRITES_LAA /* errata */
                                  | FLAG_TARC_SPEED_MODE_BIT /* errata */
@@ -1347,12 +1345,10 @@ struct e1000_info e1000_82572_info = {
        .mac                    = e1000_82572,
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_JUMBO_FRAMES
-                                 | FLAG_HAS_STATS_PTC_PRC
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
                                  | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
-                                 | FLAG_HAS_STATS_ICR_ICT
                                  | FLAG_TARC_SPEED_MODE_BIT, /* errata */
        .pba                    = 38,
        .get_variants           = e1000_get_variants_82571,
@@ -1365,11 +1361,9 @@ struct e1000_info e1000_82573_info = {
        .mac                    = e1000_82573,
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_JUMBO_FRAMES
-                                 | FLAG_HAS_STATS_PTC_PRC
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
                                  | FLAG_RX_CSUM_ENABLED
-                                 | FLAG_HAS_STATS_ICR_ICT
                                  | FLAG_HAS_SMART_POWER_DOWN
                                  | FLAG_HAS_AMT
                                  | FLAG_HAS_ERT
index 572cfd44397adcf6ff506b742aebc201b1c325b6..2a53875cddbf5601ab6da33b89f36caf3e6f8650 100644 (file)
 #define E1000_SWFW_EEP_SM   0x1
 #define E1000_SWFW_PHY0_SM  0x2
 #define E1000_SWFW_PHY1_SM  0x4
+#define E1000_SWFW_CSR_SM   0x8
 
 /* Device Control */
 #define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
 #define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
 #define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
 #define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
 #define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
 #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
 
 /* NVM Control */
 #define E1000_EECD_SK        0x00000001 /* NVM Clock */
index 5a89dff522641c5ea28351cb06e99c19e1092a65..38bfd0d261fee3f272f80415da323311eb8ddf43 100644 (file)
@@ -64,11 +64,14 @@ struct e1000_info;
 /* Tx/Rx descriptor defines */
 #define E1000_DEFAULT_TXD              256
 #define E1000_MAX_TXD                  4096
-#define E1000_MIN_TXD                  80
+#define E1000_MIN_TXD                  64
 
 #define E1000_DEFAULT_RXD              256
 #define E1000_MAX_RXD                  4096
-#define E1000_MIN_RXD                  80
+#define E1000_MIN_RXD                  64
+
+#define E1000_MIN_ITR_USECS            10 /* 100000 irq/sec */
+#define E1000_MAX_ITR_USECS            10000 /* 100    irq/sec */
 
 /* Early Receive defines */
 #define E1000_ERT_2048                 0x100
@@ -147,6 +150,18 @@ struct e1000_ring {
        struct e1000_queue_stats stats;
 };
 
+/* PHY register snapshot values */
+struct e1000_phy_regs {
+       u16 bmcr;               /* basic mode control register    */
+       u16 bmsr;               /* basic mode status register     */
+       u16 advertise;          /* auto-negotiation advertisement */
+       u16 lpa;                /* link partner ability register  */
+       u16 expansion;          /* auto-negotiation expansion reg */
+       u16 ctrl1000;           /* 1000BASE-T control register    */
+       u16 stat1000;           /* 1000BASE-T status register     */
+       u16 estatus;            /* extended status register       */
+};
+
 /* board specific private data structure */
 struct e1000_adapter {
        struct timer_list watchdog_timer;
@@ -202,8 +217,8 @@ struct e1000_adapter {
        /* Tx stats */
        u64 tpt_old;
        u64 colc_old;
-       u64 gotcl_old;
-       u32 gotcl;
+       u32 gotc;
+       u64 gotc_old;
        u32 tx_timeout_count;
        u32 tx_fifo_head;
        u32 tx_head_addr;
@@ -227,8 +242,8 @@ struct e1000_adapter {
        u64 hw_csum_err;
        u64 hw_csum_good;
        u64 rx_hdr_split;
-       u64 gorcl_old;
-       u32 gorcl;
+       u32 gorc;
+       u64 gorc_old;
        u32 alloc_rx_buff_failed;
        u32 rx_dma_failed;
 
@@ -250,6 +265,9 @@ struct e1000_adapter {
        struct e1000_phy_info phy_info;
        struct e1000_phy_stats phy_stats;
 
+       /* Snapshot of PHY registers */
+       struct e1000_phy_regs phy_regs;
+
        struct e1000_ring test_tx_ring;
        struct e1000_ring test_rx_ring;
        u32 test_icr;
@@ -286,8 +304,6 @@ struct e1000_info {
 #define FLAG_HAS_CTRLEXT_ON_LOAD          (1 << 5)
 #define FLAG_HAS_SWSM_ON_LOAD             (1 << 6)
 #define FLAG_HAS_JUMBO_FRAMES             (1 << 7)
-#define FLAG_HAS_STATS_ICR_ICT            (1 << 9)
-#define FLAG_HAS_STATS_PTC_PRC            (1 << 10)
 #define FLAG_HAS_SMART_POWER_DOWN         (1 << 11)
 #define FLAG_IS_QUAD_PORT_A               (1 << 12)
 #define FLAG_IS_QUAD_PORT                 (1 << 13)
@@ -433,6 +449,8 @@ extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
 extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                               u32 usec_interval, bool *success);
 extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw);
+extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
 extern s32 e1000e_check_downshift(struct e1000_hw *hw);
 
 static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
index d59a99ae44bee83b6afa7aff45315ae828f9c9b7..dc552d7d6fac5d083671f66c17b882fe505798ae 100644 (file)
@@ -41,6 +41,7 @@
 #define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL      0x00
 #define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL       0x02
 #define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL        0x10
+#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE         0x1F
 
 #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS   0x0008
 #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS   0x0800
@@ -48,6 +49,7 @@
 
 #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
 #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT  0x0000
+#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE                 0x2000
 
 #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
 #define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN       0x00010000
@@ -85,6 +87,9 @@
 /* Kumeran Mode Control Register (Page 193, Register 16) */
 #define GG82563_KMCR_PASS_FALSE_CARRIER                 0x0800
 
+/* Max number of times Kumeran read/write should be validated */
+#define GG82563_MAX_KMRN_RETRY  0x5
+
 /* Power Management Control Register (Page 193, Register 20) */
 #define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE     0x0001
                                           /* 1=Enable SERDES Electrical Idle */
@@ -270,6 +275,7 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
        u16 mask;
 
        mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
+       mask |= E1000_SWFW_CSR_SM;
 
        return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
 }
@@ -286,6 +292,8 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
        u16 mask;
 
        mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
+       mask |= E1000_SWFW_CSR_SM;
+
        e1000_release_swfw_sync_80003es2lan(hw, mask);
 }
 
@@ -410,20 +418,27 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        u32 page_select;
        u16 temp;
 
+       ret_val = e1000_acquire_phy_80003es2lan(hw);
+       if (ret_val)
+               return ret_val;
+
        /* Select Configuration Page */
-       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
+       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
                page_select = GG82563_PHY_PAGE_SELECT;
-       else
+       } else {
                /*
                 * Use Alternative Page Select register to access
                 * registers 30 and 31
                 */
                page_select = GG82563_PHY_PAGE_SELECT_ALT;
+       }
 
        temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
-       ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp);
-       if (ret_val)
+       ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
+       if (ret_val) {
+               e1000_release_phy_80003es2lan(hw);
                return ret_val;
+       }
 
        /*
         * The "ready" bit in the MDIC register may be incorrectly set
@@ -433,20 +448,21 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        udelay(200);
 
        /* ...and verify the command was successful. */
-       ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp);
+       ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
 
        if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
                ret_val = -E1000_ERR_PHY;
+               e1000_release_phy_80003es2lan(hw);
                return ret_val;
        }
 
        udelay(200);
 
-       ret_val = e1000e_read_phy_reg_m88(hw,
-                                        MAX_PHY_REG_ADDRESS & offset,
-                                        data);
+       ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
 
        udelay(200);
+       e1000_release_phy_80003es2lan(hw);
 
        return ret_val;
 }
@@ -467,20 +483,27 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        u32 page_select;
        u16 temp;
 
+       ret_val = e1000_acquire_phy_80003es2lan(hw);
+       if (ret_val)
+               return ret_val;
+
        /* Select Configuration Page */
-       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG)
+       if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
                page_select = GG82563_PHY_PAGE_SELECT;
-       else
+       } else {
                /*
                 * Use Alternative Page Select register to access
                 * registers 30 and 31
                 */
                page_select = GG82563_PHY_PAGE_SELECT_ALT;
+       }
 
        temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
-       ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp);
-       if (ret_val)
+       ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp);
+       if (ret_val) {
+               e1000_release_phy_80003es2lan(hw);
                return ret_val;
+       }
 
 
        /*
@@ -491,18 +514,20 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        udelay(200);
 
        /* ...and verify the command was successful. */
-       ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp);
+       ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
 
-       if (((u16)offset >> GG82563_PAGE_SHIFT) != temp)
+       if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
+               e1000_release_phy_80003es2lan(hw);
                return -E1000_ERR_PHY;
+       }
 
        udelay(200);
 
-       ret_val = e1000e_write_phy_reg_m88(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
-                                         data);
+       ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                           data);
 
        udelay(200);
+       e1000_release_phy_80003es2lan(hw);
 
        return ret_val;
 }
@@ -882,10 +907,10 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
        u32 ctrl_ext;
-       u16 data;
+       u32 i = 0;
+       u16 data, data2;
 
-       ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL,
-                                    &data);
+       ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
        if (ret_val)
                return ret_val;
 
@@ -893,8 +918,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
        /* Use 25MHz for both link down and 1000Base-T for Tx clock. */
        data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
 
-       ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL,
-                                     data);
+       ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
        if (ret_val)
                return ret_val;
 
@@ -954,6 +978,18 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
+       ret_val = e1000e_read_kmrn_reg(hw,
+                                      E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
+                                      &data);
+       if (ret_val)
+               return ret_val;
+       data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
+       ret_val = e1000e_write_kmrn_reg(hw,
+                                       E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
+                                       data);
+       if (ret_val)
+               return ret_val;
+
        ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data);
        if (ret_val)
                return ret_val;
@@ -983,9 +1019,18 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
                if (ret_val)
                        return ret_val;
 
-               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data);
-               if (ret_val)
-                       return ret_val;
+               do {
+                       ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                          &data);
+                       if (ret_val)
+                               return ret_val;
+
+                       ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                          &data2);
+                       if (ret_val)
+                               return ret_val;
+                       i++;
+               } while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY));
 
                data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
                ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data);
@@ -1074,7 +1119,8 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
 {
        s32 ret_val;
        u32 tipg;
-       u16 reg_data;
+       u32 i = 0;
+       u16 reg_data, reg_data2;
 
        reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
        ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
@@ -1088,9 +1134,16 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
        tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
        ew32(TIPG, tipg);
 
-       ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
-       if (ret_val)
-               return ret_val;
+       do {
+               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data2);
+               if (ret_val)
+                       return ret_val;
+               i++;
+       } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
 
        if (duplex == HALF_DUPLEX)
                reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
@@ -1112,8 +1165,9 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
 static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
 {
        s32 ret_val;
-       u16 reg_data;
+       u16 reg_data, reg_data2;
        u32 tipg;
+       u32 i = 0;
 
        reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
        ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
@@ -1127,9 +1181,16 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
        tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
        ew32(TIPG, tipg);
 
-       ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
-       if (ret_val)
-               return ret_val;
+       do {
+               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data2);
+               if (ret_val)
+                       return ret_val;
+               i++;
+       } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
 
        reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
        ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
@@ -1231,12 +1292,10 @@ struct e1000_info e1000_es2_info = {
        .mac                    = e1000_80003es2lan,
        .flags                  = FLAG_HAS_HW_VLAN_FILTER
                                  | FLAG_HAS_JUMBO_FRAMES
-                                 | FLAG_HAS_STATS_PTC_PRC
                                  | FLAG_HAS_WOL
                                  | FLAG_APME_IN_CTRL3
                                  | FLAG_RX_CSUM_ENABLED
                                  | FLAG_HAS_CTRLEXT_ON_LOAD
-                                 | FLAG_HAS_STATS_ICR_ICT
                                  | FLAG_RX_NEEDS_RESTART /* errata */
                                  | FLAG_TARC_SET_BIT_ZERO /* errata */
                                  | FLAG_APME_CHECK_PORT_B
index 6d1b257bbda6b37d3ea38b1034ef02f20b72f1a3..ce045acce63e99b79685e291a8993e3acd940508 100644 (file)
@@ -46,8 +46,8 @@ struct e1000_stats {
 static const struct e1000_stats e1000_gstrings_stats[] = {
        { "rx_packets", E1000_STAT(stats.gprc) },
        { "tx_packets", E1000_STAT(stats.gptc) },
-       { "rx_bytes", E1000_STAT(stats.gorcl) },
-       { "tx_bytes", E1000_STAT(stats.gotcl) },
+       { "rx_bytes", E1000_STAT(stats.gorc) },
+       { "tx_bytes", E1000_STAT(stats.gotc) },
        { "rx_broadcast", E1000_STAT(stats.bprc) },
        { "tx_broadcast", E1000_STAT(stats.bptc) },
        { "rx_multicast", E1000_STAT(stats.mprc) },
@@ -83,7 +83,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
        { "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
        { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
-       { "rx_long_byte_count", E1000_STAT(stats.gorcl) },
+       { "rx_long_byte_count", E1000_STAT(stats.gorc) },
        { "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
        { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
        { "rx_header_split", E1000_STAT(rx_hdr_split) },
@@ -1770,6 +1770,47 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
        return 0;
 }
 
+static int e1000_get_coalesce(struct net_device *netdev,
+                             struct ethtool_coalesce *ec)
+{
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+
+       if (adapter->itr_setting <= 3)
+               ec->rx_coalesce_usecs = adapter->itr_setting;
+       else
+               ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting;
+
+       return 0;
+}
+
+static int e1000_set_coalesce(struct net_device *netdev,
+                             struct ethtool_coalesce *ec)
+{
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+       struct e1000_hw *hw = &adapter->hw;
+
+       if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) ||
+           ((ec->rx_coalesce_usecs > 3) &&
+            (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) ||
+           (ec->rx_coalesce_usecs == 2))
+               return -EINVAL;
+
+       if (ec->rx_coalesce_usecs <= 3) {
+               adapter->itr = 20000;
+               adapter->itr_setting = ec->rx_coalesce_usecs;
+       } else {
+               adapter->itr = (1000000 / ec->rx_coalesce_usecs);
+               adapter->itr_setting = adapter->itr & ~3;
+       }
+
+       if (adapter->itr_setting != 0)
+               ew32(ITR, 1000000000 / (adapter->itr * 256));
+       else
+               ew32(ITR, 0);
+
+       return 0;
+}
+
 static int e1000_nway_reset(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1845,6 +1886,8 @@ static const struct ethtool_ops e1000_ethtool_ops = {
        .phys_id                = e1000_phys_id,
        .get_ethtool_stats      = e1000_get_ethtool_stats,
        .get_sset_count         = e1000e_get_sset_count,
+       .get_coalesce           = e1000_get_coalesce,
+       .set_coalesce           = e1000_set_coalesce,
 };
 
 void e1000e_set_ethtool_ops(struct net_device *netdev)
index 53f1ac6327fabcd92312ca3d4733c7bb5983f773..a930e6d9cf02bdd34d8beb88d67f84c47d8fb6d1 100644 (file)
@@ -592,10 +592,8 @@ struct e1000_hw_stats {
        u64 bprc;
        u64 mprc;
        u64 gptc;
-       u64 gorcl;
-       u64 gorch;
-       u64 gotcl;
-       u64 gotch;
+       u64 gorc;
+       u64 gotc;
        u64 rnbc;
        u64 ruc;
        u64 rfc;
@@ -604,10 +602,8 @@ struct e1000_hw_stats {
        u64 mgprc;
        u64 mgpdc;
        u64 mgptc;
-       u64 torl;
-       u64 torh;
-       u64 totl;
-       u64 toth;
+       u64 tor;
+       u64 tot;
        u64 tpr;
        u64 tpt;
        u64 ptc64;
index c8dc47fd132a47e74401a0c103efb23a18b97934..8991ab8911e2f506e1d2be85fbad7a7f4a8ad4fb 100644 (file)
@@ -46,7 +46,7 @@
 
 #include "e1000.h"
 
-#define DRV_VERSION "0.2.0"
+#define DRV_VERSION "0.2.1"
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -466,10 +466,10 @@ next_desc:
        if (cleaned_count)
                adapter->alloc_rx_buf(adapter, cleaned_count);
 
-       adapter->total_rx_packets += total_rx_packets;
        adapter->total_rx_bytes += total_rx_bytes;
-       adapter->net_stats.rx_packets += total_rx_packets;
+       adapter->total_rx_packets += total_rx_packets;
        adapter->net_stats.rx_bytes += total_rx_bytes;
+       adapter->net_stats.rx_packets += total_rx_packets;
        return cleaned;
 }
 
@@ -606,8 +606,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
        }
        adapter->total_tx_bytes += total_tx_bytes;
        adapter->total_tx_packets += total_tx_packets;
-       adapter->net_stats.tx_packets += total_tx_packets;
        adapter->net_stats.tx_bytes += total_tx_bytes;
+       adapter->net_stats.tx_packets += total_tx_packets;
        return cleaned;
 }
 
@@ -775,10 +775,10 @@ next_desc:
        if (cleaned_count)
                adapter->alloc_rx_buf(adapter, cleaned_count);
 
-       adapter->total_rx_packets += total_rx_packets;
        adapter->total_rx_bytes += total_rx_bytes;
-       adapter->net_stats.rx_packets += total_rx_packets;
+       adapter->total_rx_packets += total_rx_packets;
        adapter->net_stats.rx_bytes += total_rx_bytes;
+       adapter->net_stats.rx_packets += total_rx_packets;
        return cleaned;
 }
 
@@ -2506,56 +2506,27 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
 
        adapter->stats.crcerrs += er32(CRCERRS);
        adapter->stats.gprc += er32(GPRC);
-       adapter->stats.gorcl += er32(GORCL);
-       adapter->stats.gorch += er32(GORCH);
+       adapter->stats.gorc += er32(GORCL);
+       er32(GORCH); /* Clear gorc */
        adapter->stats.bprc += er32(BPRC);
        adapter->stats.mprc += er32(MPRC);
        adapter->stats.roc += er32(ROC);
 
-       if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) {
-               adapter->stats.prc64 += er32(PRC64);
-               adapter->stats.prc127 += er32(PRC127);
-               adapter->stats.prc255 += er32(PRC255);
-               adapter->stats.prc511 += er32(PRC511);
-               adapter->stats.prc1023 += er32(PRC1023);
-               adapter->stats.prc1522 += er32(PRC1522);
-               adapter->stats.symerrs += er32(SYMERRS);
-               adapter->stats.sec += er32(SEC);
-       }
-
        adapter->stats.mpc += er32(MPC);
        adapter->stats.scc += er32(SCC);
        adapter->stats.ecol += er32(ECOL);
        adapter->stats.mcc += er32(MCC);
        adapter->stats.latecol += er32(LATECOL);
        adapter->stats.dc += er32(DC);
-       adapter->stats.rlec += er32(RLEC);
        adapter->stats.xonrxc += er32(XONRXC);
        adapter->stats.xontxc += er32(XONTXC);
        adapter->stats.xoffrxc += er32(XOFFRXC);
        adapter->stats.xofftxc += er32(XOFFTXC);
-       adapter->stats.fcruc += er32(FCRUC);
        adapter->stats.gptc += er32(GPTC);
-       adapter->stats.gotcl += er32(GOTCL);
-       adapter->stats.gotch += er32(GOTCH);
+       adapter->stats.gotc += er32(GOTCL);
+       er32(GOTCH); /* Clear gotc */
        adapter->stats.rnbc += er32(RNBC);
        adapter->stats.ruc += er32(RUC);
-       adapter->stats.rfc += er32(RFC);
-       adapter->stats.rjc += er32(RJC);
-       adapter->stats.torl += er32(TORL);
-       adapter->stats.torh += er32(TORH);
-       adapter->stats.totl += er32(TOTL);
-       adapter->stats.toth += er32(TOTH);
-       adapter->stats.tpr += er32(TPR);
-
-       if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) {
-               adapter->stats.ptc64 += er32(PTC64);
-               adapter->stats.ptc127 += er32(PTC127);
-               adapter->stats.ptc255 += er32(PTC255);
-               adapter->stats.ptc511 += er32(PTC511);
-               adapter->stats.ptc1023 += er32(PTC1023);
-               adapter->stats.ptc1522 += er32(PTC1522);
-       }
 
        adapter->stats.mptc += er32(MPTC);
        adapter->stats.bptc += er32(BPTC);
@@ -2574,19 +2545,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
        adapter->stats.tsctc += er32(TSCTC);
        adapter->stats.tsctfc += er32(TSCTFC);
 
-       adapter->stats.iac += er32(IAC);
-
-       if (adapter->flags & FLAG_HAS_STATS_ICR_ICT) {
-               adapter->stats.icrxoc += er32(ICRXOC);
-               adapter->stats.icrxptc += er32(ICRXPTC);
-               adapter->stats.icrxatc += er32(ICRXATC);
-               adapter->stats.ictxptc += er32(ICTXPTC);
-               adapter->stats.ictxatc += er32(ICTXATC);
-               adapter->stats.ictxqec += er32(ICTXQEC);
-               adapter->stats.ictxqmtc += er32(ICTXQMTC);
-               adapter->stats.icrxdmtc += er32(ICRXDMTC);
-       }
-
        /* Fill out the OS statistics structure */
        adapter->net_stats.multicast = adapter->stats.mprc;
        adapter->net_stats.collisions = adapter->stats.colc;
@@ -2633,6 +2591,54 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
        spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
 }
 
+/**
+ * e1000_phy_read_status - Update the PHY register status snapshot
+ * @adapter: board private structure
+ **/
+static void e1000_phy_read_status(struct e1000_adapter *adapter)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       struct e1000_phy_regs *phy = &adapter->phy_regs;
+       int ret_val;
+       unsigned long irq_flags;
+
+
+       spin_lock_irqsave(&adapter->stats_lock, irq_flags);
+
+       if ((er32(STATUS) & E1000_STATUS_LU) &&
+           (adapter->hw.phy.media_type == e1000_media_type_copper)) {
+               ret_val  = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr);
+               ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr);
+               ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise);
+               ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa);
+               ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion);
+               ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000);
+               ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000);
+               ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus);
+               if (ret_val)
+                       ndev_warn(adapter->netdev,
+                                 "Error reading PHY register\n");
+       } else {
+               /*
+                * Do not read PHY registers if link is not up
+                * Set values to typical power-on defaults
+                */
+               phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX);
+               phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL |
+                            BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE |
+                            BMSR_ERCAP);
+               phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP |
+                                 ADVERTISE_ALL | ADVERTISE_CSMA);
+               phy->lpa = 0;
+               phy->expansion = EXPANSION_ENABLENPAGE;
+               phy->ctrl1000 = ADVERTISE_1000FULL;
+               phy->stat1000 = 0;
+               phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF);
+       }
+
+       spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
+}
+
 static void e1000_print_link_info(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
@@ -2745,6 +2751,7 @@ static void e1000_watchdog_task(struct work_struct *work)
                if (!netif_carrier_ok(netdev)) {
                        bool txb2b = 1;
                        /* update snapshot of PHY registers on LSC */
+                       e1000_phy_read_status(adapter);
                        mac->ops.get_link_up_info(&adapter->hw,
                                                   &adapter->link_speed,
                                                   &adapter->link_duplex);
@@ -2842,10 +2849,10 @@ link_up:
        mac->collision_delta = adapter->stats.colc - adapter->colc_old;
        adapter->colc_old = adapter->stats.colc;
 
-       adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
-       adapter->gorcl_old = adapter->stats.gorcl;
-       adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
-       adapter->gotcl_old = adapter->stats.gotcl;
+       adapter->gorc = adapter->stats.gorc - adapter->gorc_old;
+       adapter->gorc_old = adapter->stats.gorc;
+       adapter->gotc = adapter->stats.gotc - adapter->gotc_old;
+       adapter->gotc_old = adapter->stats.gotc;
 
        e1000e_update_adaptive(&adapter->hw);
 
@@ -3500,7 +3507,6 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct mii_ioctl_data *data = if_mii(ifr);
-       unsigned long irq_flags;
 
        if (adapter->hw.phy.media_type != e1000_media_type_copper)
                return -EOPNOTSUPP;
@@ -3512,13 +3518,40 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
        case SIOCGMIIREG:
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
-               spin_lock_irqsave(&adapter->stats_lock, irq_flags);
-               if (e1e_rphy(&adapter->hw, data->reg_num & 0x1F,
-                                  &data->val_out)) {
-                       spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
+               switch (data->reg_num & 0x1F) {
+               case MII_BMCR:
+                       data->val_out = adapter->phy_regs.bmcr;
+                       break;
+               case MII_BMSR:
+                       data->val_out = adapter->phy_regs.bmsr;
+                       break;
+               case MII_PHYSID1:
+                       data->val_out = (adapter->hw.phy.id >> 16);
+                       break;
+               case MII_PHYSID2:
+                       data->val_out = (adapter->hw.phy.id & 0xFFFF);
+                       break;
+               case MII_ADVERTISE:
+                       data->val_out = adapter->phy_regs.advertise;
+                       break;
+               case MII_LPA:
+                       data->val_out = adapter->phy_regs.lpa;
+                       break;
+               case MII_EXPANSION:
+                       data->val_out = adapter->phy_regs.expansion;
+                       break;
+               case MII_CTRL1000:
+                       data->val_out = adapter->phy_regs.ctrl1000;
+                       break;
+               case MII_STAT1000:
+                       data->val_out = adapter->phy_regs.stat1000;
+                       break;
+               case MII_ESTATUS:
+                       data->val_out = adapter->phy_regs.estatus;
+                       break;
+               default:
                        return -EIO;
                }
-               spin_unlock_irqrestore(&adapter->stats_lock, irq_flags);
                break;
        case SIOCSMIIREG:
        default:
@@ -3774,6 +3807,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
        }
        pci_set_master(pdev);
+       pci_restore_state(pdev);
 
        pci_enable_wake(pdev, PCI_D3hot, 0);
        pci_enable_wake(pdev, PCI_D3cold, 0);
@@ -3900,6 +3934,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
                goto err_pci_reg;
 
        pci_set_master(pdev);
+       pci_save_state(pdev);
 
        err = -ENOMEM;
        netdev = alloc_etherdev(sizeof(struct e1000_adapter));
index 3a4574caa75bb1fdcd824d5b3853141773fda532..e102332a6beed4e49588f2c37063a0429fef85f8 100644 (file)
@@ -116,7 +116,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
 }
 
 /**
- *  e1000_read_phy_reg_mdic - Read MDI control register
+ *  e1000e_read_phy_reg_mdic - Read MDI control register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
  *  @data: pointer to the read data
@@ -124,7 +124,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
  *  Reads the MDI control register in the PHY at offset and stores the
  *  information read to data.
  **/
-static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, mdic = 0;
@@ -150,7 +150,7 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
         * Increasing the time out as testing showed failures with
         * the lower time out
         */
-       for (i = 0; i < 64; i++) {
+       for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
                udelay(50);
                mdic = er32(MDIC);
                if (mdic & E1000_MDIC_READY)
@@ -170,14 +170,14 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 }
 
 /**
- *  e1000_write_phy_reg_mdic - Write MDI control register
+ *  e1000e_write_phy_reg_mdic - Write MDI control register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to write to
  *  @data: data to write to register at offset
  *
  *  Writes data to MDI control register in the PHY at offset.
  **/
-static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 {
        struct e1000_phy_info *phy = &hw->phy;
        u32 i, mdic = 0;
@@ -199,9 +199,13 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 
        ew32(MDIC, mdic);
 
-       /* Poll the ready bit to see if the MDI read completed */
-       for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) {
-               udelay(5);
+       /*
+        * Poll the ready bit to see if the MDI read completed
+        * Increasing the time out as testing showed failures with
+        * the lower time out
+        */
+       for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+               udelay(50);
                mdic = er32(MDIC);
                if (mdic & E1000_MDIC_READY)
                        break;
@@ -210,6 +214,10 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                hw_dbg(hw, "MDI Write did not complete\n");
                return -E1000_ERR_PHY;
        }
+       if (mdic & E1000_MDIC_ERROR) {
+               hw_dbg(hw, "MDI Error\n");
+               return -E1000_ERR_PHY;
+       }
 
        return 0;
 }
@@ -232,9 +240,8 @@ s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
        if (ret_val)
                return ret_val;
 
-       ret_val = e1000_read_phy_reg_mdic(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
-                                         data);
+       ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
 
        hw->phy.ops.release_phy(hw);
 
@@ -258,9 +265,8 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
        if (ret_val)
                return ret_val;
 
-       ret_val = e1000_write_phy_reg_mdic(hw,
-                                          MAX_PHY_REG_ADDRESS & offset,
-                                          data);
+       ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                           data);
 
        hw->phy.ops.release_phy(hw);
 
@@ -286,18 +292,17 @@ s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
                return ret_val;
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
-               ret_val = e1000_write_phy_reg_mdic(hw,
-                                                  IGP01E1000_PHY_PAGE_SELECT,
-                                                  (u16)offset);
+               ret_val = e1000e_write_phy_reg_mdic(hw,
+                                                   IGP01E1000_PHY_PAGE_SELECT,
+                                                   (u16)offset);
                if (ret_val) {
                        hw->phy.ops.release_phy(hw);
                        return ret_val;
                }
        }
 
-       ret_val = e1000_read_phy_reg_mdic(hw,
-                                         MAX_PHY_REG_ADDRESS & offset,
-                                         data);
+       ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                          data);
 
        hw->phy.ops.release_phy(hw);
 
@@ -322,18 +327,17 @@ s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
                return ret_val;
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
-               ret_val = e1000_write_phy_reg_mdic(hw,
-                                                  IGP01E1000_PHY_PAGE_SELECT,
-                                                  (u16)offset);
+               ret_val = e1000e_write_phy_reg_mdic(hw,
+                                                   IGP01E1000_PHY_PAGE_SELECT,
+                                                   (u16)offset);
                if (ret_val) {
                        hw->phy.ops.release_phy(hw);
                        return ret_val;
                }
        }
 
-       ret_val = e1000_write_phy_reg_mdic(hw,
-                                          MAX_PHY_REG_ADDRESS & offset,
-                                          data);
+       ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+                                           data);
 
        hw->phy.ops.release_phy(hw);
 
@@ -420,7 +424,9 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+       /* For newer PHYs this bit is downshift enable */
+       if (phy->type == e1000_phy_m88)
+               phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
 
        /*
         * Options:
@@ -463,7 +469,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       if (phy->revision < 4) {
+       if ((phy->type == e1000_phy_m88) && (phy->revision < 4)) {
                /*
                 * Force TX_CLK in the Extended PHY Specific Control Register
                 * to 25MHz clock.
@@ -518,8 +524,11 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
                return ret_val;
        }
 
-       /* Wait 15ms for MAC to configure PHY from NVM settings. */
-       msleep(15);
+       /*
+        * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
+        * timeout issues when LFS is enabled.
+        */
+       msleep(100);
 
        /* disable lplu d0 during driver init */
        ret_val = e1000_set_d0_lplu_state(hw, 0);
@@ -1152,9 +1161,7 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active)
 
        if (!active) {
                data &= ~IGP02E1000_PM_D3_LPLU;
-               ret_val = e1e_wphy(hw,
-                                            IGP02E1000_PHY_POWER_MGMT,
-                                            data);
+               ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
                if (ret_val)
                        return ret_val;
                /*
index 9ff7538b75952e94ef27d9660dd31fa00f75b605..f9bc21c74b59222a7c8775dfaba80a91d9abb626 100644 (file)
@@ -2611,7 +2611,7 @@ static int ehea_stop(struct net_device *dev)
        return ret;
 }
 
-void ehea_purge_sq(struct ehea_qp *orig_qp)
+static void ehea_purge_sq(struct ehea_qp *orig_qp)
 {
        struct ehea_qp qp = *orig_qp;
        struct ehea_qp_init_attr *init_attr = &qp.init_attr;
@@ -2625,7 +2625,7 @@ void ehea_purge_sq(struct ehea_qp *orig_qp)
        }
 }
 
-void ehea_flush_sq(struct ehea_port *port)
+static void ehea_flush_sq(struct ehea_port *port)
 {
        int i;
 
index 8c4214b0ee1f2ff7d6bc7f04bd497e07ef613f35..35f66d4a4595d5148f4affbc167897c60ca49792 100644 (file)
@@ -96,6 +96,7 @@
 #define DEV_HAS_PAUSEFRAME_TX_V2   0x10000  /* device supports tx pause frames version 2 */
 #define DEV_HAS_PAUSEFRAME_TX_V3   0x20000  /* device supports tx pause frames version 3 */
 #define DEV_NEED_TX_LIMIT          0x40000  /* device needs to limit tx */
+#define DEV_HAS_GEAR_MODE          0x80000  /* device supports gear mode */
 
 enum {
        NvRegIrqStatus = 0x000,
@@ -174,11 +175,13 @@ enum {
        NvRegReceiverStatus = 0x98,
 #define NVREG_RCVSTAT_BUSY     0x01
 
-       NvRegRandomSeed = 0x9c,
-#define NVREG_RNDSEED_MASK     0x00ff
-#define NVREG_RNDSEED_FORCE    0x7f00
-#define NVREG_RNDSEED_FORCE2   0x2d00
-#define NVREG_RNDSEED_FORCE3   0x7400
+       NvRegSlotTime = 0x9c,
+#define NVREG_SLOTTIME_LEGBF_ENABLED   0x80000000
+#define NVREG_SLOTTIME_10_100_FULL     0x00007f00
+#define NVREG_SLOTTIME_1000_FULL       0x0003ff00
+#define NVREG_SLOTTIME_HALF            0x0000ff00
+#define NVREG_SLOTTIME_DEFAULT         0x00007f00
+#define NVREG_SLOTTIME_MASK            0x000000ff
 
        NvRegTxDeferral = 0xA0,
 #define NVREG_TX_DEFERRAL_DEFAULT              0x15050f
@@ -201,6 +204,11 @@ enum {
 
        NvRegPhyInterface = 0xC0,
 #define PHY_RGMII              0x10000000
+       NvRegBackOffControl = 0xC4,
+#define NVREG_BKOFFCTRL_DEFAULT                        0x70000000
+#define NVREG_BKOFFCTRL_SEED_MASK              0x000003ff
+#define NVREG_BKOFFCTRL_SELECT                 24
+#define NVREG_BKOFFCTRL_GEAR                   12
 
        NvRegTxRingPhysAddr = 0x100,
        NvRegRxRingPhysAddr = 0x104,
@@ -352,6 +360,7 @@ union ring_type {
 
 #define NV_TX_LASTPACKET       (1<<16)
 #define NV_TX_RETRYERROR       (1<<19)
+#define NV_TX_RETRYCOUNT_MASK  (0xF<<20)
 #define NV_TX_FORCED_INTERRUPT (1<<24)
 #define NV_TX_DEFERRED         (1<<26)
 #define NV_TX_CARRIERLOST      (1<<27)
@@ -362,6 +371,7 @@ union ring_type {
 
 #define NV_TX2_LASTPACKET      (1<<29)
 #define NV_TX2_RETRYERROR      (1<<18)
+#define NV_TX2_RETRYCOUNT_MASK (0xF<<19)
 #define NV_TX2_FORCED_INTERRUPT        (1<<30)
 #define NV_TX2_DEFERRED                (1<<25)
 #define NV_TX2_CARRIERLOST     (1<<26)
@@ -473,16 +483,22 @@ union ring_type {
 #define DESC_VER_3     3
 
 /* PHY defines */
-#define PHY_OUI_MARVELL        0x5043
-#define PHY_OUI_CICADA 0x03f1
-#define PHY_OUI_VITESSE        0x01c1
-#define PHY_OUI_REALTEK        0x0732
+#define PHY_OUI_MARVELL                0x5043
+#define PHY_OUI_CICADA         0x03f1
+#define PHY_OUI_VITESSE                0x01c1
+#define PHY_OUI_REALTEK                0x0732
+#define PHY_OUI_REALTEK2       0x0020
 #define PHYID1_OUI_MASK        0x03ff
 #define PHYID1_OUI_SHFT        6
 #define PHYID2_OUI_MASK        0xfc00
 #define PHYID2_OUI_SHFT        10
 #define PHYID2_MODEL_MASK              0x03f0
-#define PHY_MODEL_MARVELL_E3016                0x220
+#define PHY_MODEL_REALTEK_8211         0x0110
+#define PHY_REV_MASK                   0x0001
+#define PHY_REV_REALTEK_8211B          0x0000
+#define PHY_REV_REALTEK_8211C          0x0001
+#define PHY_MODEL_REALTEK_8201         0x0200
+#define PHY_MODEL_MARVELL_E3016                0x0220
 #define PHY_MARVELL_E3016_INITMASK     0x0300
 #define PHY_CICADA_INIT1       0x0f000
 #define PHY_CICADA_INIT2       0x0e00
@@ -509,10 +525,18 @@ union ring_type {
 #define PHY_REALTEK_INIT_REG1  0x1f
 #define PHY_REALTEK_INIT_REG2  0x19
 #define PHY_REALTEK_INIT_REG3  0x13
+#define PHY_REALTEK_INIT_REG4  0x14
+#define PHY_REALTEK_INIT_REG5  0x18
+#define PHY_REALTEK_INIT_REG6  0x11
 #define PHY_REALTEK_INIT1      0x0000
 #define PHY_REALTEK_INIT2      0x8e00
 #define PHY_REALTEK_INIT3      0x0001
 #define PHY_REALTEK_INIT4      0xad17
+#define PHY_REALTEK_INIT5      0xfb54
+#define PHY_REALTEK_INIT6      0xf5c7
+#define PHY_REALTEK_INIT7      0x1000
+#define PHY_REALTEK_INIT8      0x0003
+#define PHY_REALTEK_INIT_MSK1  0x0003
 
 #define PHY_GIGABIT    0x0100
 
@@ -691,6 +715,7 @@ struct fe_priv {
        int wolenabled;
        unsigned int phy_oui;
        unsigned int phy_model;
+       unsigned int phy_rev;
        u16 gigabit;
        int intr_test;
        int recover_error;
@@ -704,6 +729,7 @@ struct fe_priv {
        u32 txrxctl_bits;
        u32 vlanctl_bits;
        u32 driver_data;
+       u32 device_id;
        u32 register_size;
        int rx_csum;
        u32 mac_in_use;
@@ -814,6 +840,16 @@ enum {
 };
 static int dma_64bit = NV_DMA_64BIT_ENABLED;
 
+/*
+ * Crossover Detection
+ * Realtek 8201 phy + some OEM boards do not work properly.
+ */
+enum {
+       NV_CROSSOVER_DETECTION_DISABLED,
+       NV_CROSSOVER_DETECTION_ENABLED
+};
+static int phy_cross = NV_CROSSOVER_DETECTION_DISABLED;
+
 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
 {
        return netdev_priv(dev);
@@ -1078,25 +1114,53 @@ static int phy_init(struct net_device *dev)
                }
        }
        if (np->phy_oui == PHY_OUI_REALTEK) {
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
+               if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
+                   np->phy_rev == PHY_REV_REALTEK_8211B) {
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
                }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
+               if (np->phy_model == PHY_MODEL_REALTEK_8201) {
+                       if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
+                               phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
+                               phy_reserved |= PHY_REALTEK_INIT7;
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                       }
                }
        }
 
@@ -1236,26 +1300,71 @@ static int phy_init(struct net_device *dev)
                }
        }
        if (np->phy_oui == PHY_OUI_REALTEK) {
-               /* reset could have cleared these out, set them back */
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
-               }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
+               if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
+                   np->phy_rev == PHY_REV_REALTEK_8211B) {
+                       /* reset could have cleared these out, set them back */
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
                }
-               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
-                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
-                       return PHY_ERROR;
+               if (np->phy_model == PHY_MODEL_REALTEK_8201) {
+                       if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 ||
+                           np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) {
+                               phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
+                               phy_reserved |= PHY_REALTEK_INIT7;
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                       }
+                       if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                               phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
+                               phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
+                               phy_reserved |= PHY_REALTEK_INIT3;
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                       }
                }
        }
 
@@ -1769,6 +1878,115 @@ static inline u32 nv_get_empty_tx_slots(struct fe_priv *np)
        return (u32)(np->tx_ring_size - ((np->tx_ring_size + (np->put_tx_ctx - np->get_tx_ctx)) % np->tx_ring_size));
 }
 
+static void nv_legacybackoff_reseed(struct net_device *dev)
+{
+       u8 __iomem *base = get_hwbase(dev);
+       u32 reg;
+       u32 low;
+       int tx_status = 0;
+
+       reg = readl(base + NvRegSlotTime) & ~NVREG_SLOTTIME_MASK;
+       get_random_bytes(&low, sizeof(low));
+       reg |= low & NVREG_SLOTTIME_MASK;
+
+       /* Need to stop tx before change takes effect.
+        * Caller has already gained np->lock.
+        */
+       tx_status = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START;
+       if (tx_status)
+               nv_stop_tx(dev);
+       nv_stop_rx(dev);
+       writel(reg, base + NvRegSlotTime);
+       if (tx_status)
+               nv_start_tx(dev);
+       nv_start_rx(dev);
+}
+
+/* Gear Backoff Seeds */
+#define BACKOFF_SEEDSET_ROWS   8
+#define BACKOFF_SEEDSET_LFSRS  15
+
+/* Known Good seed sets */
+static const u32 main_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
+    {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
+    {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974},
+    {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874},
+    {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974},
+    {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984},
+    {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984},
+    {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800,  84},
+    {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184}};
+
+static const u32 gear_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = {
+    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397},
+    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+    {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375,  30, 295},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395},
+    {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}};
+
+static void nv_gear_backoff_reseed(struct net_device *dev)
+{
+       u8 __iomem *base = get_hwbase(dev);
+       u32 miniseed1, miniseed2, miniseed2_reversed, miniseed3, miniseed3_reversed;
+       u32 temp, seedset, combinedSeed;
+       int i;
+
+       /* Setup seed for free running LFSR */
+       /* We are going to read the time stamp counter 3 times
+          and swizzle bits around to increase randomness */
+       get_random_bytes(&miniseed1, sizeof(miniseed1));
+       miniseed1 &= 0x0fff;
+       if (miniseed1 == 0)
+               miniseed1 = 0xabc;
+
+       get_random_bytes(&miniseed2, sizeof(miniseed2));
+       miniseed2 &= 0x0fff;
+       if (miniseed2 == 0)
+               miniseed2 = 0xabc;
+       miniseed2_reversed =
+               ((miniseed2 & 0xF00) >> 8) |
+                (miniseed2 & 0x0F0) |
+                ((miniseed2 & 0x00F) << 8);
+
+       get_random_bytes(&miniseed3, sizeof(miniseed3));
+       miniseed3 &= 0x0fff;
+       if (miniseed3 == 0)
+               miniseed3 = 0xabc;
+       miniseed3_reversed =
+               ((miniseed3 & 0xF00) >> 8) |
+                (miniseed3 & 0x0F0) |
+                ((miniseed3 & 0x00F) << 8);
+
+       combinedSeed = ((miniseed1 ^ miniseed2_reversed) << 12) |
+                      (miniseed2 ^ miniseed3_reversed);
+
+       /* Seeds can not be zero */
+       if ((combinedSeed & NVREG_BKOFFCTRL_SEED_MASK) == 0)
+               combinedSeed |= 0x08;
+       if ((combinedSeed & (NVREG_BKOFFCTRL_SEED_MASK << NVREG_BKOFFCTRL_GEAR)) == 0)
+               combinedSeed |= 0x8000;
+
+       /* No need to disable tx here */
+       temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT);
+       temp |= combinedSeed & NVREG_BKOFFCTRL_SEED_MASK;
+       temp |= combinedSeed >> NVREG_BKOFFCTRL_GEAR;
+       writel(temp,base + NvRegBackOffControl);
+
+       /* Setup seeds for all gear LFSRs. */
+       get_random_bytes(&seedset, sizeof(seedset));
+       seedset = seedset % BACKOFF_SEEDSET_ROWS;
+       for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++)
+       {
+               temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT);
+               temp |= main_seedset[seedset][i-1] & 0x3ff;
+               temp |= ((gear_seedset[seedset][i-1] & 0x3ff) << NVREG_BKOFFCTRL_GEAR);
+               writel(temp, base + NvRegBackOffControl);
+       }
+}
+
 /*
  * nv_start_xmit: dev->hard_start_xmit function
  * Called with netif_tx_lock held.
@@ -2088,6 +2306,8 @@ static void nv_tx_done(struct net_device *dev)
                                                dev->stats.tx_fifo_errors++;
                                        if (flags & NV_TX_CARRIERLOST)
                                                dev->stats.tx_carrier_errors++;
+                                       if ((flags & NV_TX_RETRYERROR) && !(flags & NV_TX_RETRYCOUNT_MASK))
+                                               nv_legacybackoff_reseed(dev);
                                        dev->stats.tx_errors++;
                                } else {
                                        dev->stats.tx_packets++;
@@ -2103,6 +2323,8 @@ static void nv_tx_done(struct net_device *dev)
                                                dev->stats.tx_fifo_errors++;
                                        if (flags & NV_TX2_CARRIERLOST)
                                                dev->stats.tx_carrier_errors++;
+                                       if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK))
+                                               nv_legacybackoff_reseed(dev);
                                        dev->stats.tx_errors++;
                                } else {
                                        dev->stats.tx_packets++;
@@ -2144,6 +2366,15 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit)
                if (flags & NV_TX2_LASTPACKET) {
                        if (!(flags & NV_TX2_ERROR))
                                dev->stats.tx_packets++;
+                       else {
+                               if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) {
+                                       if (np->driver_data & DEV_HAS_GEAR_MODE)
+                                               nv_gear_backoff_reseed(dev);
+                                       else
+                                               nv_legacybackoff_reseed(dev);
+                               }
+                       }
+
                        dev_kfree_skb_any(np->get_tx_ctx->skb);
                        np->get_tx_ctx->skb = NULL;
 
@@ -2905,15 +3136,14 @@ set_speed:
        }
 
        if (np->gigabit == PHY_GIGABIT) {
-               phyreg = readl(base + NvRegRandomSeed);
+               phyreg = readl(base + NvRegSlotTime);
                phyreg &= ~(0x3FF00);
-               if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
-                       phyreg |= NVREG_RNDSEED_FORCE3;
-               else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
-                       phyreg |= NVREG_RNDSEED_FORCE2;
+               if (((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) ||
+                   ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100))
+                       phyreg |= NVREG_SLOTTIME_10_100_FULL;
                else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
-                       phyreg |= NVREG_RNDSEED_FORCE;
-               writel(phyreg, base + NvRegRandomSeed);
+                       phyreg |= NVREG_SLOTTIME_1000_FULL;
+               writel(phyreg, base + NvRegSlotTime);
        }
 
        phyreg = readl(base + NvRegPhyInterface);
@@ -4843,6 +5073,7 @@ static int nv_open(struct net_device *dev)
        u8 __iomem *base = get_hwbase(dev);
        int ret = 1;
        int oom, i;
+       u32 low;
 
        dprintk(KERN_DEBUG "nv_open: begin\n");
 
@@ -4902,8 +5133,20 @@ static int nv_open(struct net_device *dev)
        writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 
        writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
-       get_random_bytes(&i, sizeof(i));
-       writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
+
+       get_random_bytes(&low, sizeof(low));
+       low &= NVREG_SLOTTIME_MASK;
+       if (np->desc_ver == DESC_VER_1) {
+               writel(low|NVREG_SLOTTIME_DEFAULT, base + NvRegSlotTime);
+       } else {
+               if (!(np->driver_data & DEV_HAS_GEAR_MODE)) {
+                       /* setup legacy backoff */
+                       writel(NVREG_SLOTTIME_LEGBF_ENABLED|NVREG_SLOTTIME_10_100_FULL|low, base + NvRegSlotTime);
+               } else {
+                       writel(NVREG_SLOTTIME_10_100_FULL, base + NvRegSlotTime);
+                       nv_gear_backoff_reseed(dev);
+               }
+       }
        writel(NVREG_TX_DEFERRAL_DEFAULT, base + NvRegTxDeferral);
        writel(NVREG_RX_DEFERRAL_DEFAULT, base + NvRegRxDeferral);
        if (poll_interval == -1) {
@@ -5110,6 +5353,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 
        /* copy of driver data */
        np->driver_data = id->driver_data;
+       /* copy of device id */
+       np->device_id = id->device;
 
        /* handle different descriptor versions */
        if (id->driver_data & DEV_HAS_HIGH_DMA) {
@@ -5399,6 +5644,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                        pci_name(pci_dev), id1, id2, phyaddr);
                np->phyaddr = phyaddr;
                np->phy_oui = id1 | id2;
+
+               /* Realtek hardcoded phy id1 to all zero's on certain phys */
+               if (np->phy_oui == PHY_OUI_REALTEK2)
+                       np->phy_oui = PHY_OUI_REALTEK;
+               /* Setup phy revision for Realtek */
+               if (np->phy_oui == PHY_OUI_REALTEK && np->phy_model == PHY_MODEL_REALTEK_8211)
+                       np->phy_rev = mii_rw(dev, phyaddr, MII_RESV1, MII_READ) & PHY_REV_MASK;
+
                break;
        }
        if (i == 33) {
@@ -5477,6 +5730,28 @@ out:
        return err;
 }
 
+static void nv_restore_phy(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u16 phy_reserved, mii_control;
+
+       if (np->phy_oui == PHY_OUI_REALTEK &&
+           np->phy_model == PHY_MODEL_REALTEK_8201 &&
+           phy_cross == NV_CROSSOVER_DETECTION_DISABLED) {
+               mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3);
+               phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ);
+               phy_reserved &= ~PHY_REALTEK_INIT_MSK1;
+               phy_reserved |= PHY_REALTEK_INIT8;
+               mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved);
+               mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1);
+
+               /* restart auto negotiation */
+               mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+               mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
+               mii_rw(dev, np->phyaddr, MII_BMCR, mii_control);
+       }
+}
+
 static void __devexit nv_remove(struct pci_dev *pci_dev)
 {
        struct net_device *dev = pci_get_drvdata(pci_dev);
@@ -5493,6 +5768,9 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
        writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV,
               base + NvRegTransmitPoll);
 
+       /* restore any phy related changes */
+       nv_restore_phy(dev);
+
        /* free all structures */
        free_rings(dev);
        iounmap(get_hwbase(dev));
@@ -5632,83 +5910,83 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP65 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP67 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP73 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP73 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP73 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP73 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP77 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP77 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP77 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP77 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP79 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP79 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP79 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {       /* MCP79 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
        },
        {0,},
 };
@@ -5744,6 +6022,8 @@ module_param(msix, int, 0);
 MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0.");
 module_param(dma_64bit, int, 0);
 MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0.");
+module_param(phy_cross, int, 0);
+MODULE_PARM_DESC(phy_cross, "Phy crossover detection for Realtek 8201 phy is enabled by setting to 1 and disabled by setting to 0.");
 
 MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
 MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
index c8c3df737d73582ebe15484c898ff0f2a9ac5666..99a4b990939f7720780e02da49d822dbdf2b9abd 100644 (file)
@@ -98,7 +98,6 @@
 #include "gianfar_mii.h"
 
 #define TX_TIMEOUT      (1*HZ)
-#define SKB_ALLOC_TIMEOUT 1000000
 #undef BRIEF_GFAR_ERRORS
 #undef VERBOSE_GFAR_ERRORS
 
@@ -115,7 +114,9 @@ static int gfar_enet_open(struct net_device *dev);
 static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void gfar_timeout(struct net_device *dev);
 static int gfar_close(struct net_device *dev);
-struct sk_buff *gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp);
+struct sk_buff *gfar_new_skb(struct net_device *dev);
+static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
+               struct sk_buff *skb);
 static int gfar_set_mac_address(struct net_device *dev);
 static int gfar_change_mtu(struct net_device *dev, int new_mtu);
 static irqreturn_t gfar_error(int irq, void *dev_id);
@@ -783,14 +784,21 @@ int startup_gfar(struct net_device *dev)
 
        rxbdp = priv->rx_bd_base;
        for (i = 0; i < priv->rx_ring_size; i++) {
-               struct sk_buff *skb = NULL;
+               struct sk_buff *skb;
 
-               rxbdp->status = 0;
+               skb = gfar_new_skb(dev);
 
-               skb = gfar_new_skb(dev, rxbdp);
+               if (!skb) {
+                       printk(KERN_ERR "%s: Can't allocate RX buffers\n",
+                                       dev->name);
+
+                       goto err_rxalloc_fail;
+               }
 
                priv->rx_skbuff[i] = skb;
 
+               gfar_new_rxbdp(dev, rxbdp, skb);
+
                rxbdp++;
        }
 
@@ -916,6 +924,7 @@ rx_irq_fail:
 tx_irq_fail:
        free_irq(priv->interruptError, dev);
 err_irq_fail:
+err_rxalloc_fail:      
 rx_skb_fail:
        free_skb_resources(priv);
 tx_skb_fail:
@@ -1328,18 +1337,37 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
+static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
+               struct sk_buff *skb)
+{
+       struct gfar_private *priv = netdev_priv(dev);
+       u32 * status_len = (u32 *)bdp;
+       u16 flags;
+
+       bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
+                       priv->rx_buffer_size, DMA_FROM_DEVICE);
+
+       flags = RXBD_EMPTY | RXBD_INTERRUPT;
+
+       if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
+               flags |= RXBD_WRAP;
+
+       eieio();
+
+       *status_len = (u32)flags << 16;
+}
+
+
+struct sk_buff * gfar_new_skb(struct net_device *dev)
 {
        unsigned int alignamount;
        struct gfar_private *priv = netdev_priv(dev);
        struct sk_buff *skb = NULL;
-       unsigned int timeout = SKB_ALLOC_TIMEOUT;
 
        /* We have to allocate the skb, so keep trying till we succeed */
-       while ((!skb) && timeout--)
-               skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
+       skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
 
-       if (NULL == skb)
+       if (!skb)
                return NULL;
 
        alignamount = RXBUF_ALIGNMENT -
@@ -1350,15 +1378,6 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
         */
        skb_reserve(skb, alignamount);
 
-       bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
-                       priv->rx_buffer_size, DMA_FROM_DEVICE);
-
-       bdp->length = 0;
-
-       /* Mark the buffer empty */
-       eieio();
-       bdp->status |= (RXBD_EMPTY | RXBD_INTERRUPT);
-
        return skb;
 }
 
@@ -1544,10 +1563,31 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
        bdp = priv->cur_rx;
 
        while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
+               struct sk_buff *newskb;
                rmb();
+
+               /* Add another skb for the future */
+               newskb = gfar_new_skb(dev);
+
                skb = priv->rx_skbuff[priv->skb_currx];
 
-               if ((bdp->status & RXBD_LAST) && !(bdp->status & RXBD_ERR)) {
+               /* We drop the frame if we failed to allocate a new buffer */
+               if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
+                                bdp->status & RXBD_ERR)) {
+                       count_errors(bdp->status, dev);
+
+                       if (unlikely(!newskb))
+                               newskb = skb;
+
+                       if (skb) {
+                               dma_unmap_single(&priv->dev->dev,
+                                               bdp->bufPtr,
+                                               priv->rx_buffer_size,
+                                               DMA_FROM_DEVICE);
+
+                               dev_kfree_skb_any(skb);
+                       }
+               } else {
                        /* Increment the number of packets */
                        dev->stats.rx_packets++;
                        howmany++;
@@ -1558,23 +1598,14 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
                        gfar_process_frame(dev, skb, pkt_len);
 
                        dev->stats.rx_bytes += pkt_len;
-               } else {
-                       count_errors(bdp->status, dev);
-
-                       if (skb)
-                               dev_kfree_skb_any(skb);
-
-                       priv->rx_skbuff[priv->skb_currx] = NULL;
                }
 
                dev->last_rx = jiffies;
 
-               /* Clear the status flags for this buffer */
-               bdp->status &= ~RXBD_STATS;
+               priv->rx_skbuff[priv->skb_currx] = newskb;
 
-               /* Add another skb for the future */
-               skb = gfar_new_skb(dev, bdp);
-               priv->rx_skbuff[priv->skb_currx] = skb;
+               /* Setup the new bdp */
+               gfar_new_rxbdp(dev, bdp, newskb);
 
                /* Update to the next pointer */
                if (bdp->status & RXBD_WRAP)
@@ -1584,9 +1615,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
 
                /* update to point at the next skb */
                priv->skb_currx =
-                   (priv->skb_currx +
-                    1) & RX_RING_MOD_MASK(priv->rx_ring_size);
-
+                   (priv->skb_currx + 1) &
+                   RX_RING_MOD_MASK(priv->rx_ring_size);
        }
 
        /* Update the current rxbd pointer to be the next one */
@@ -2001,12 +2031,16 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:fsl-gianfar");
+
 /* Structure for a device driver */
 static struct platform_driver gfar_driver = {
        .probe = gfar_probe,
        .remove = gfar_remove,
        .driver = {
                .name = "fsl-gianfar",
+               .owner = THIS_MODULE,
        },
 };
 
index 378a239634955163fdf6e991725179746ea651a1..5d2108c5ac7c872d32409de44edc22f07bf5620e 100644 (file)
@@ -43,6 +43,8 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
+#include <asm/dcr.h>
+#include <asm/dcr-regs.h>
 
 #include "core.h"
 
@@ -127,10 +129,35 @@ static struct device_node *emac_boot_list[EMAC_BOOT_LIST_SIZE];
 static inline void emac_report_timeout_error(struct emac_instance *dev,
                                             const char *error)
 {
-       if (net_ratelimit())
+       if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
+                                 EMAC_FTR_440EP_PHY_CLK_FIX))
+               DBG(dev, "%s" NL, error);
+       else if (net_ratelimit())
                printk(KERN_ERR "%s: %s\n", dev->ndev->name, error);
 }
 
+/* EMAC PHY clock workaround:
+ * 440EP/440GR has more sane SDR0_MFR register implementation than 440GX,
+ * which allows controlling each EMAC clock
+ */
+static inline void emac_rx_clk_tx(struct emac_instance *dev)
+{
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR,
+                           0, SDR0_MFR_ECS >> dev->cell_index);
+#endif
+}
+
+static inline void emac_rx_clk_default(struct emac_instance *dev)
+{
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR,
+                           SDR0_MFR_ECS >> dev->cell_index, 0);
+#endif
+}
+
 /* PHY polling intervals */
 #define PHY_POLL_LINK_ON       HZ
 #define PHY_POLL_LINK_OFF      (HZ / 5)
@@ -524,7 +551,10 @@ static int emac_configure(struct emac_instance *dev)
                rx_size = dev->rx_fifo_size_gige;
 
                if (dev->ndev->mtu > ETH_DATA_LEN) {
-                       mr1 |= EMAC_MR1_JPSM;
+                       if (emac_has_feature(dev, EMAC_FTR_EMAC4))
+                               mr1 |= EMAC4_MR1_JPSM;
+                       else
+                               mr1 |= EMAC_MR1_JPSM;
                        dev->stop_timeout = STOP_TIMEOUT_1000_JUMBO;
                } else
                        dev->stop_timeout = STOP_TIMEOUT_1000;
@@ -708,7 +738,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
                rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
 
        /* Wait for management interface to become idle */
-       n = 10;
+       n = 20;
        while (!emac_phy_done(dev, in_be32(&p->stacr))) {
                udelay(1);
                if (!--n) {
@@ -733,7 +763,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg)
        out_be32(&p->stacr, r);
 
        /* Wait for read to complete */
-       n = 100;
+       n = 200;
        while (!emac_phy_done(dev, (r = in_be32(&p->stacr)))) {
                udelay(1);
                if (!--n) {
@@ -780,7 +810,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
                rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port);
 
        /* Wait for management interface to be idle */
-       n = 10;
+       n = 20;
        while (!emac_phy_done(dev, in_be32(&p->stacr))) {
                udelay(1);
                if (!--n) {
@@ -806,7 +836,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg,
        out_be32(&p->stacr, r);
 
        /* Wait for write to complete */
-       n = 100;
+       n = 200;
        while (!emac_phy_done(dev, in_be32(&p->stacr))) {
                udelay(1);
                if (!--n) {
@@ -1094,9 +1124,11 @@ static int emac_open(struct net_device *ndev)
                int link_poll_interval;
                if (dev->phy.def->ops->poll_link(&dev->phy)) {
                        dev->phy.def->ops->read_link(&dev->phy);
+                       emac_rx_clk_default(dev);
                        netif_carrier_on(dev->ndev);
                        link_poll_interval = PHY_POLL_LINK_ON;
                } else {
+                       emac_rx_clk_tx(dev);
                        netif_carrier_off(dev->ndev);
                        link_poll_interval = PHY_POLL_LINK_OFF;
                }
@@ -1174,6 +1206,7 @@ static void emac_link_timer(struct work_struct *work)
 
        if (dev->phy.def->ops->poll_link(&dev->phy)) {
                if (!netif_carrier_ok(dev->ndev)) {
+                       emac_rx_clk_default(dev);
                        /* Get new link parameters */
                        dev->phy.def->ops->read_link(&dev->phy);
 
@@ -1186,6 +1219,7 @@ static void emac_link_timer(struct work_struct *work)
                link_poll_interval = PHY_POLL_LINK_ON;
        } else {
                if (netif_carrier_ok(dev->ndev)) {
+                       emac_rx_clk_tx(dev);
                        netif_carrier_off(dev->ndev);
                        netif_tx_disable(dev->ndev);
                        emac_reinitialize(dev);
@@ -2237,7 +2271,7 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb,
        return 0;
 }
 
-static struct notifier_block emac_of_bus_notifier = {
+static struct notifier_block emac_of_bus_notifier __devinitdata = {
        .notifier_call = emac_of_bus_notify
 };
 
@@ -2330,6 +2364,19 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
        dev->phy.mdio_read = emac_mdio_read;
        dev->phy.mdio_write = emac_mdio_write;
 
+       /* Enable internal clock source */
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
+#endif
+       /* PHY clock workaround */
+       emac_rx_clk_tx(dev);
+
+       /* Enable internal clock source on 440GX*/
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
+#endif
        /* Configure EMAC with defaults so we can at least use MDIO
         * This is needed mostly for 440GX
         */
@@ -2362,6 +2409,12 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
                        if (!emac_mii_phy_probe(&dev->phy, i))
                                break;
                }
+
+       /* Enable external clock source */
+#ifdef CONFIG_PPC_DCR_NATIVE
+       if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
+               dcri_clrset(SDR0, SDR0_MFR, SDR0_MFR_ECS, 0);
+#endif
        mutex_unlock(&emac_phy_map_lock);
        if (i == 0x20) {
                printk(KERN_WARNING "%s: can't find PHY!\n", np->full_name);
@@ -2487,8 +2540,15 @@ static int __devinit emac_init_config(struct emac_instance *dev)
        }
 
        /* Check EMAC version */
-       if (of_device_is_compatible(np, "ibm,emac4"))
+       if (of_device_is_compatible(np, "ibm,emac4")) {
                dev->features |= EMAC_FTR_EMAC4;
+               if (of_device_is_compatible(np, "ibm,emac-440gx"))
+                       dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX;
+       } else {
+               if (of_device_is_compatible(np, "ibm,emac-440ep") ||
+                   of_device_is_compatible(np, "ibm,emac-440gr"))
+                       dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
+       }
 
        /* Fixup some feature bits based on the device tree */
        if (of_get_property(np, "has-inverted-stacr-oc", NULL))
@@ -2559,8 +2619,11 @@ static int __devinit emac_probe(struct of_device *ofdev,
        struct device_node **blist = NULL;
        int err, i;
 
-       /* Skip unused/unwired EMACS */
-       if (of_get_property(np, "unused", NULL))
+       /* Skip unused/unwired EMACS.  We leave the check for an unused
+        * property here for now, but new flat device trees should set a
+        * status property to "disabled" instead.
+        */
+       if (of_get_property(np, "unused", NULL) || !of_device_is_available(np))
                return -ENODEV;
 
        /* Find ourselves in the bootlist if we are there */
index 4e74d8287c65b91d25a6a95ff36de8a0d2d16a6b..1683db9870a467fdba8d591bb086c447791598d5 100644 (file)
@@ -301,6 +301,14 @@ struct emac_instance {
  * Set if we have new type STACR with STAOPC
  */
 #define EMAC_FTR_HAS_NEW_STACR         0x00000040
+/*
+ * Set if we need phy clock workaround for 440gx
+ */
+#define EMAC_FTR_440GX_PHY_CLK_FIX     0x00000080
+/*
+ * Set if we need phy clock workaround for 440ep or 440gr
+ */
+#define EMAC_FTR_440EP_PHY_CLK_FIX     0x00000100
 
 
 /* Right now, we don't quite handle the always/possible masks on the
@@ -312,8 +320,8 @@ enum {
 
        EMAC_FTRS_POSSIBLE      =
 #ifdef CONFIG_IBM_NEW_EMAC_EMAC4
-           EMAC_FTR_EMAC4      | EMAC_FTR_HAS_NEW_STACR        |
-           EMAC_FTR_STACR_OC_INVERT    |
+           EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR |
+           EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX |
 #endif
 #ifdef CONFIG_IBM_NEW_EMAC_TAH
            EMAC_FTR_HAS_TAH    |
@@ -324,7 +332,7 @@ enum {
 #ifdef CONFIG_IBM_NEW_EMAC_RGMII
            EMAC_FTR_HAS_RGMII  |
 #endif
-           0,
+       EMAC_FTR_440EP_PHY_CLK_FIX,
 };
 
 static inline int emac_has_feature(struct emac_instance *dev,
index 6869f08c9dcba0188b920524e68c747d1445fb9f..10c267b2b9610b1e446a4fe32e4deba9c5700976 100644 (file)
@@ -61,8 +61,8 @@ int __devinit mal_register_commac(struct mal_instance *mal,
        return 0;
 }
 
-void __devexit mal_unregister_commac(struct mal_instance       *mal,
-                                    struct mal_commac          *commac)
+void mal_unregister_commac(struct mal_instance *mal,
+               struct mal_commac *commac)
 {
        unsigned long flags;
 
@@ -136,6 +136,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
 {
        unsigned long flags;
 
+       /*
+        * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple
+        * of 8, but enabling in MAL_RXCASR needs the divided by 8 value
+        * for the bitmask
+        */
+       if (!(channel % 8))
+               channel >>= 3;
+
        spin_lock_irqsave(&mal->lock, flags);
 
        MAL_DBG(mal, "enable_rx(%d)" NL, channel);
@@ -148,6 +156,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel)
 
 void mal_disable_rx_channel(struct mal_instance *mal, int channel)
 {
+       /*
+        * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple
+        * of 8, but enabling in MAL_RXCASR needs the divided by 8 value
+        * for the bitmask
+        */
+       if (!(channel % 8))
+               channel >>= 3;
+
        set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel));
 
        MAL_DBG(mal, "disable_rx(%d)" NL, channel);
index 5757788227be8d887537b21fbaf97dd7853f55c0..e32da3de2695de79564bfcfa5707d48b507c0ebd 100644 (file)
@@ -179,7 +179,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input)
        mutex_unlock(&dev->lock);
 }
 
-void __devexit rgmii_detach(struct of_device *ofdev, int input)
+void rgmii_detach(struct of_device *ofdev, int input)
 {
        struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
        struct rgmii_regs __iomem *p = dev->base;
index b023d10d7e1c2d14ecac3f61e3af4d6501392ff1..30173a9fb557d930f543d0c237f3fff0a5cb777b 100644 (file)
@@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel)
        return 0;
 }
 
-void __devexit tah_detach(struct of_device *ofdev, int channel)
+void tah_detach(struct of_device *ofdev, int channel)
 {
        struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
 
index 2ea472aeab06ac8c03deb714853024b8cce265f1..17b154124943e5baf89e6640f26643ade28be72c 100644 (file)
@@ -189,7 +189,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed)
        mutex_unlock(&dev->lock);
 }
 
-void __devexit zmii_detach(struct of_device *ofdev, int input)
+void zmii_detach(struct of_device *ofdev, int input)
 {
        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 
index aaee02e9e3f03c4bc0da116942964996fe061fda..ae398f04c7b44d8ef8865ed4f902dba1d12a0172 100644 (file)
@@ -871,6 +871,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
                goto err_pci_reg;
 
        pci_set_master(pdev);
+       pci_save_state(pdev);
 
        err = -ENOMEM;
        netdev = alloc_etherdev(sizeof(struct igb_adapter));
@@ -4079,6 +4080,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
        }
        pci_set_master(pdev);
+       pci_restore_state(pdev);
 
        pci_enable_wake(pdev, PCI_D3hot, 0);
        pci_enable_wake(pdev, PCI_D3cold, 0);
index 9f584521304a8a84ce5e8230f43df2fa72def8b3..083b0dd70fef1f1431e284b0aa7aa864047711b8 100644 (file)
@@ -60,6 +60,7 @@ static struct platform_driver ali_ircc_driver = {
        .resume         = ali_ircc_resume,
        .driver         = {
                .name   = ALI_IRCC_DRIVER_NAME,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -2256,6 +2257,7 @@ static void FIR2SIR(int iobase)
 MODULE_AUTHOR("Benjamin Kong <benjamin_kong@ali.com.tw>");
 MODULE_DESCRIPTION("ALi FIR Controller Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME);
 
 
 module_param_array(io, int, NULL, 0);
index 8db71ab20456b38d14ce1f8e5cd4e1e8e4c87ecf..d5c2d27f3ea4d12c8b29a7aac0f1426303f8dc42 100644 (file)
@@ -908,6 +908,7 @@ static int pxa_irda_remove(struct platform_device *_dev)
 static struct platform_driver pxa_ir_driver = {
        .driver         = {
                .name   = "pxa2xx-ir",
+               .owner  = THIS_MODULE,
        },
        .probe          = pxa_irda_probe,
        .remove         = pxa_irda_remove,
@@ -929,3 +930,4 @@ module_init(pxa_irda_init);
 module_exit(pxa_irda_exit);
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-ir");
index 056639f72becf049657601585f82e83c0c20a6a1..1bc8518f9197d9a00293766bc953990341b5b26f 100644 (file)
@@ -1008,6 +1008,7 @@ static struct platform_driver sa1100ir_driver = {
        .resume         = sa1100_irda_resume,
        .driver         = {
                .name   = "sa11x0-ir",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -1041,3 +1042,4 @@ MODULE_LICENSE("GPL");
 MODULE_PARM_DESC(power_level, "IrDA power level, 1 (low) to 3 (high)");
 MODULE_PARM_DESC(tx_lpm, "Enable transmitter low power (1.6us) mode");
 MODULE_PARM_DESC(max_rate, "Maximum baud rate (4000000, 115200, 57600, 38400, 19200, 9600)");
+MODULE_ALIAS("platform:sa11x0-ir");
index cb371a8c24a72244092b4353757a1e886dd4d91a..7b859220c255b3b81017f156548df2dcca2f32e7 100644 (file)
@@ -3431,6 +3431,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        }
 
        pci_set_master(pdev);
+       pci_save_state(pdev);
 
 #ifdef CONFIG_NETDEVICES_MULTIQUEUE
        netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES);
@@ -3721,6 +3722,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
        }
        pci_set_master(pdev);
+       pci_restore_state(pdev);
 
        pci_enable_wake(pdev, PCI_D3hot, 0);
        pci_enable_wake(pdev, PCI_D3cold, 0);
index 5c154fe1385956d2797a8946000397b4558631a0..07944820f74582b5230c4a362acac0b81eccbec6 100644 (file)
@@ -249,6 +249,7 @@ out:
 MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
 module_param(sonic_debug, int, 0);
 MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
+MODULE_ALIAS("platform:jazzsonic");
 
 #include "sonic.c"
 
@@ -271,6 +272,7 @@ static struct platform_driver jazz_sonic_driver = {
        .remove = __devexit_p(jazz_sonic_device_remove),
        .driver = {
                .name   = jazz_sonic_string,
+               .owner  = THIS_MODULE,
        },
 };
 
index 1d24a73a0e1a1d268c1d319bcd3625a63d5d47da..e18576316bda93050cdd5849da80ef67cd85333a 100644 (file)
@@ -883,7 +883,7 @@ static int korina_init(struct net_device *dev)
 static int korina_restart(struct net_device *dev)
 {
        struct korina_private *lp = netdev_priv(dev);
-       int ret = 0;
+       int ret;
 
        /*
         * Disable interrupts
@@ -987,7 +987,7 @@ static void korina_poll_controller(struct net_device *dev)
 static int korina_open(struct net_device *dev)
 {
        struct korina_private *lp = netdev_priv(dev);
-       int ret = 0;
+       int ret;
 
        /* Initialize */
        ret = korina_init(dev);
@@ -1031,6 +1031,8 @@ static int korina_open(struct net_device *dev)
                    dev->name, lp->und_irq);
                goto err_free_ovr_irq;
        }
+out:
+       return ret;
 
 err_free_ovr_irq:
        free_irq(lp->ovr_irq, dev);
@@ -1041,8 +1043,6 @@ err_free_rx_irq:
 err_release:
        korina_free_ring(dev);
        goto out;
-out:
-       return ret;
 }
 
 static int korina_close(struct net_device *dev)
@@ -1082,7 +1082,7 @@ static int korina_probe(struct platform_device *pdev)
        struct korina_private *lp;
        struct net_device *dev;
        struct resource *r;
-       int retval, err;
+       int rc;
 
        dev = alloc_etherdev(sizeof(struct korina_private));
        if (!dev) {
@@ -1106,7 +1106,7 @@ static int korina_probe(struct platform_device *pdev)
        lp->eth_regs = ioremap_nocache(r->start, r->end - r->start);
        if (!lp->eth_regs) {
                printk(KERN_ERR DRV_NAME "cannot remap registers\n");
-               retval = -ENXIO;
+               rc = -ENXIO;
                goto probe_err_out;
        }
 
@@ -1114,7 +1114,7 @@ static int korina_probe(struct platform_device *pdev)
        lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
        if (!lp->rx_dma_regs) {
                printk(KERN_ERR DRV_NAME "cannot remap Rx DMA registers\n");
-               retval = -ENXIO;
+               rc = -ENXIO;
                goto probe_err_dma_rx;
        }
 
@@ -1122,14 +1122,14 @@ static int korina_probe(struct platform_device *pdev)
        lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start);
        if (!lp->tx_dma_regs) {
                printk(KERN_ERR DRV_NAME "cannot remap Tx DMA registers\n");
-               retval = -ENXIO;
+               rc = -ENXIO;
                goto probe_err_dma_tx;
        }
 
        lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
        if (!lp->td_ring) {
                printk(KERN_ERR DRV_NAME "cannot allocate descriptors\n");
-               retval = -ENOMEM;
+               rc = -ENXIO;
                goto probe_err_td_ring;
        }
 
@@ -1166,14 +1166,14 @@ static int korina_probe(struct platform_device *pdev)
        lp->mii_if.phy_id_mask = 0x1f;
        lp->mii_if.reg_num_mask = 0x1f;
 
-       err = register_netdev(dev);
-       if (err) {
+       rc = register_netdev(dev);
+       if (rc < 0) {
                printk(KERN_ERR DRV_NAME
-                       ": cannot register net device %d\n", err);
-               retval = -EINVAL;
+                       ": cannot register net device %d\n", rc);
                goto probe_err_register;
        }
-       return 0;
+out:
+       return rc;
 
 probe_err_register:
        kfree(lp->td_ring);
@@ -1185,7 +1185,7 @@ probe_err_dma_rx:
        iounmap(lp->eth_regs);
 probe_err_out:
        free_netdev(dev);
-       return retval;
+       goto out;
 }
 
 static int korina_remove(struct platform_device *pdev)
@@ -1193,12 +1193,9 @@ static int korina_remove(struct platform_device *pdev)
        struct korina_device *bif = platform_get_drvdata(pdev);
        struct korina_private *lp = netdev_priv(bif->dev);
 
-       if (lp->eth_regs)
-               iounmap(lp->eth_regs);
-       if (lp->rx_dma_regs)
-               iounmap(lp->rx_dma_regs);
-       if (lp->tx_dma_regs)
-               iounmap(lp->tx_dma_regs);
+       iounmap(lp->eth_regs);
+       iounmap(lp->rx_dma_regs);
+       iounmap(lp->tx_dma_regs);
 
        platform_set_drvdata(pdev, NULL);
        unregister_netdev(bif->dev);
index d513bb8a490210c3dbaac6bfcdcd2d69b77b09de..92dccd43bdcab39fbd0bcd374d3447a33961443c 100644 (file)
@@ -1281,6 +1281,7 @@ static struct platform_driver macb_driver = {
        .remove         = __exit_p(macb_remove),
        .driver         = {
                .name           = "macb",
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -1300,3 +1301,4 @@ module_exit(macb_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Atmel MACB Ethernet driver");
 MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_ALIAS("platform:macb");
index cdaa8fc218091a947996280d27c63caa16f56f84..0b32648a213600fcecae9eda9496a63c996b1768 100644 (file)
@@ -830,6 +830,7 @@ static struct platform_driver meth_driver = {
        .remove = __devexit_p(meth_remove),
        .driver = {
                .name   = "meth",
+               .owner  = THIS_MODULE,
        }
 };
 
@@ -855,3 +856,4 @@ module_exit(meth_exit_module);
 MODULE_AUTHOR("Ilya Volynets <ilya@theIlya.com>");
 MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:meth");
index 601ffd69ebc8f5b260024c1197f2fdb754ed530b..381b36e5f64c2fe11f559d182b5abab91f0de388 100644 (file)
@@ -2030,6 +2030,7 @@ static struct platform_driver mv643xx_eth_driver = {
        .shutdown = mv643xx_eth_shutdown,
        .driver = {
                .name = MV643XX_ETH_NAME,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -2038,6 +2039,7 @@ static struct platform_driver mv643xx_eth_shared_driver = {
        .remove = mv643xx_eth_shared_remove,
        .driver = {
                .name = MV643XX_ETH_SHARED_NAME,
+               .owner  = THIS_MODULE,
        },
 };
 
@@ -2085,7 +2087,8 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani"
                " and Dale Farnsworth");
 MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
-MODULE_ALIAS("platform:mv643xx_eth");
+MODULE_ALIAS("platform:" MV643XX_ETH_NAME);
+MODULE_ALIAS("platform:" MV643XX_ETH_SHARED_NAME);
 
 /*
  * The second part is the low level driver of the gigE ethernet ports.
index 78d34af13a1ca8c59817a3c203b77e715ae6399d..dc442e370850bfb8d6fc73b7db960638ec00661c 100644 (file)
@@ -502,4 +502,4 @@ module_exit(netx_eth_cleanup);
 
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
 MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:" CARDNAME);
index 05748ca6f216831543574dda76d0778883365865..af7356468251ec4fc5aedb23a263a2cc7f70a1e5 100644 (file)
@@ -1132,8 +1132,8 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
        u32 fw_minor = 0;
        u32 fw_build = 0;
        char brd_name[NETXEN_MAX_SHORT_NAME];
-       struct netxen_new_user_info user_info;
-       int i, addr = NETXEN_USER_START;
+       char serial_num[32];
+       int i, addr;
        __le32 *ptr32;
 
        struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
@@ -1150,10 +1150,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
                valid = 0;
        }
        if (valid) {
-               ptr32 = (u32 *) & user_info;
-               for (i = 0;
-                    i < sizeof(struct netxen_new_user_info) / sizeof(u32);
-                    i++) {
+               ptr32 = (u32 *)&serial_num;
+               addr = NETXEN_USER_START +
+                      offsetof(struct netxen_new_user_info, serial_num);
+               for (i = 0; i < 8; i++) {
                        if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
                                printk("%s: ERROR reading %s board userarea.\n",
                                       netxen_nic_driver_name,
@@ -1163,10 +1163,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
                        ptr32++;
                        addr += sizeof(u32);
                }
+
                get_brd_name_by_type(board_info->board_type, brd_name);
 
                printk("NetXen %s Board S/N %s  Chip id 0x%x\n",
-                      brd_name, user_info.serial_num, board_info->chip_id);
+                      brd_name, serial_num, board_info->chip_id);
 
                printk("NetXen %s Board #%d, Chip id 0x%x\n",
                       board_info->board_type == 0x0b ? "XGB" : "GBE",
index 7565c2d7f30e9ce956d3e0a5c6009e1da9fb2038..4009c4ce96b4fd609425e8fe3b95d30f38d705a7 100644 (file)
@@ -33,8 +33,8 @@
 
 #define DRV_MODULE_NAME                "niu"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "0.7"
-#define DRV_MODULE_RELDATE     "February 18, 2008"
+#define DRV_MODULE_VERSION     "0.8"
+#define DRV_MODULE_RELDATE     "April 24, 2008"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -673,11 +673,16 @@ static int serdes_init_10g(struct niu *np)
        }
 
        if ((sig & mask) != val) {
+               if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
+                       np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+                       return 0;
+               }
                dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
                        "[%08x]\n", np->port, (int) (sig & mask), (int) val);
                return -ENODEV;
        }
-
+       if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
+               np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
        return 0;
 }
 
@@ -998,6 +1003,28 @@ static int bcm8704_user_dev3_readback(struct niu *np, int reg)
        return 0;
 }
 
+static int bcm8706_init_user_dev3(struct niu *np)
+{
+       int err;
+
+
+       err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
+                       BCM8704_USER_OPT_DIGITAL_CTRL);
+       if (err < 0)
+               return err;
+       err &= ~USER_ODIG_CTRL_GPIOS;
+       err |= (0x3 << USER_ODIG_CTRL_GPIOS_SHIFT);
+       err |=  USER_ODIG_CTRL_RESV2;
+       err = mdio_write(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
+                        BCM8704_USER_OPT_DIGITAL_CTRL, err);
+       if (err)
+               return err;
+
+       mdelay(1000);
+
+       return 0;
+}
+
 static int bcm8704_init_user_dev3(struct niu *np)
 {
        int err;
@@ -1127,33 +1154,11 @@ static int xcvr_init_10g_mrvl88x2011(struct niu *np)
                          MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
 }
 
-static int xcvr_init_10g_bcm8704(struct niu *np)
+
+static int xcvr_diag_bcm870x(struct niu *np)
 {
-       struct niu_link_config *lp = &np->link_config;
        u16 analog_stat0, tx_alarm_status;
-       int err;
-
-       err = bcm8704_reset(np);
-       if (err)
-               return err;
-
-       err = bcm8704_init_user_dev3(np);
-       if (err)
-               return err;
-
-       err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
-                       MII_BMCR);
-       if (err < 0)
-               return err;
-       err &= ~BMCR_LOOPBACK;
-
-       if (lp->loopback_mode == LOOPBACK_MAC)
-               err |= BMCR_LOOPBACK;
-
-       err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
-                        MII_BMCR, err);
-       if (err)
-               return err;
+       int err = 0;
 
 #if 1
        err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
@@ -1211,6 +1216,89 @@ static int xcvr_init_10g_bcm8704(struct niu *np)
        return 0;
 }
 
+static int xcvr_10g_set_lb_bcm870x(struct niu *np)
+{
+       struct niu_link_config *lp = &np->link_config;
+       int err;
+
+       err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+                       MII_BMCR);
+       if (err < 0)
+               return err;
+
+       err &= ~BMCR_LOOPBACK;
+
+       if (lp->loopback_mode == LOOPBACK_MAC)
+               err |= BMCR_LOOPBACK;
+
+       err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+                        MII_BMCR, err);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+static int xcvr_init_10g_bcm8706(struct niu *np)
+{
+       int err = 0;
+       u64 val;
+
+       if ((np->flags & NIU_FLAGS_HOTPLUG_PHY) &&
+           (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) == 0)
+                       return err;
+
+       val = nr64_mac(XMAC_CONFIG);
+       val &= ~XMAC_CONFIG_LED_POLARITY;
+       val |= XMAC_CONFIG_FORCE_LED_ON;
+       nw64_mac(XMAC_CONFIG, val);
+
+       val = nr64(MIF_CONFIG);
+       val |= MIF_CONFIG_INDIRECT_MODE;
+       nw64(MIF_CONFIG, val);
+
+       err = bcm8704_reset(np);
+       if (err)
+               return err;
+
+       err = xcvr_10g_set_lb_bcm870x(np);
+       if (err)
+               return err;
+
+       err = bcm8706_init_user_dev3(np);
+       if (err)
+               return err;
+
+       err = xcvr_diag_bcm870x(np);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+static int xcvr_init_10g_bcm8704(struct niu *np)
+{
+       int err;
+
+       err = bcm8704_reset(np);
+       if (err)
+               return err;
+
+       err = bcm8704_init_user_dev3(np);
+       if (err)
+               return err;
+
+       err = xcvr_10g_set_lb_bcm870x(np);
+       if (err)
+               return err;
+
+       err =  xcvr_diag_bcm870x(np);
+       if (err)
+               return err;
+
+       return 0;
+}
+
 static int xcvr_init_10g(struct niu *np)
 {
        int phy_id, err;
@@ -1548,6 +1636,59 @@ out:
        return err;
 }
 
+static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
+{
+       int err, link_up;
+       link_up = 0;
+
+       err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
+                       BCM8704_PMD_RCV_SIGDET);
+       if (err < 0)
+               goto out;
+       if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
+               err = 0;
+               goto out;
+       }
+
+       err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+                       BCM8704_PCS_10G_R_STATUS);
+       if (err < 0)
+               goto out;
+
+       if (!(err & PCS_10G_R_STATUS_BLK_LOCK)) {
+               err = 0;
+               goto out;
+       }
+
+       err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
+                       BCM8704_PHYXS_XGXS_LANE_STAT);
+       if (err < 0)
+               goto out;
+       if (err != (PHYXS_XGXS_LANE_STAT_ALINGED |
+                   PHYXS_XGXS_LANE_STAT_MAGIC |
+                   PHYXS_XGXS_LANE_STAT_PATTEST |
+                   PHYXS_XGXS_LANE_STAT_LANE3 |
+                   PHYXS_XGXS_LANE_STAT_LANE2 |
+                   PHYXS_XGXS_LANE_STAT_LANE1 |
+                   PHYXS_XGXS_LANE_STAT_LANE0)) {
+               err = 0;
+               np->link_config.active_speed = SPEED_INVALID;
+               np->link_config.active_duplex = DUPLEX_INVALID;
+               goto out;
+       }
+
+       link_up = 1;
+       np->link_config.active_speed = SPEED_10000;
+       np->link_config.active_duplex = DUPLEX_FULL;
+       err = 0;
+
+out:
+       *link_up_p = link_up;
+       if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
+               err = 0;
+       return err;
+}
+
 static int link_status_10g_bcom(struct niu *np, int *link_up_p)
 {
        int err, link_up;
@@ -1627,6 +1768,82 @@ static int link_status_10g(struct niu *np, int *link_up_p)
        return err;
 }
 
+static int niu_10g_phy_present(struct niu *np)
+{
+       u64 sig, mask, val;
+
+       sig = nr64(ESR_INT_SIGNALS);
+       switch (np->port) {
+       case 0:
+               mask = ESR_INT_SIGNALS_P0_BITS;
+               val = (ESR_INT_SRDY0_P0 |
+                      ESR_INT_DET0_P0 |
+                      ESR_INT_XSRDY_P0 |
+                      ESR_INT_XDP_P0_CH3 |
+                      ESR_INT_XDP_P0_CH2 |
+                      ESR_INT_XDP_P0_CH1 |
+                      ESR_INT_XDP_P0_CH0);
+               break;
+
+       case 1:
+               mask = ESR_INT_SIGNALS_P1_BITS;
+               val = (ESR_INT_SRDY0_P1 |
+                      ESR_INT_DET0_P1 |
+                      ESR_INT_XSRDY_P1 |
+                      ESR_INT_XDP_P1_CH3 |
+                      ESR_INT_XDP_P1_CH2 |
+                      ESR_INT_XDP_P1_CH1 |
+                      ESR_INT_XDP_P1_CH0);
+               break;
+
+       default:
+               return 0;
+       }
+
+       if ((sig & mask) != val)
+               return 0;
+       return 1;
+}
+
+static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
+{
+       unsigned long flags;
+       int err = 0;
+       int phy_present;
+       int phy_present_prev;
+
+       spin_lock_irqsave(&np->lock, flags);
+
+       if (np->link_config.loopback_mode == LOOPBACK_DISABLED) {
+               phy_present_prev = (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) ?
+                       1 : 0;
+               phy_present = niu_10g_phy_present(np);
+               if (phy_present != phy_present_prev) {
+                       /* state change */
+                       if (phy_present) {
+                               np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+                               if (np->phy_ops->xcvr_init)
+                                       err = np->phy_ops->xcvr_init(np);
+                               if (err) {
+                                       /* debounce */
+                                       np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+                               }
+                       } else {
+                               np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+                               *link_up_p = 0;
+                               niuwarn(LINK, "%s: Hotplug PHY Removed\n",
+                                       np->dev->name);
+                       }
+               }
+               if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT)
+                       err = link_status_10g_bcm8706(np, link_up_p);
+       }
+
+       spin_unlock_irqrestore(&np->lock, flags);
+
+       return err;
+}
+
 static int link_status_1g(struct niu *np, int *link_up_p)
 {
        struct niu_link_config *lp = &np->link_config;
@@ -1761,6 +1978,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber = {
        .link_status            = link_status_10g,
 };
 
+static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = {
+       .serdes_init            = serdes_init_10g,
+       .xcvr_init              = xcvr_init_10g_bcm8706,
+       .link_status            = link_status_10g_hotplug,
+};
+
 static const struct niu_phy_ops phy_ops_10g_copper = {
        .serdes_init            = serdes_init_10g,
        .link_status            = link_status_10g, /* XXX */
@@ -1792,6 +2015,11 @@ static const struct niu_phy_template phy_template_10g_fiber = {
        .phy_addr_base  = 8,
 };
 
+static const struct niu_phy_template phy_template_10g_fiber_hotplug = {
+       .ops            = &phy_ops_10g_fiber_hotplug,
+       .phy_addr_base  = 8,
+};
+
 static const struct niu_phy_template phy_template_10g_copper = {
        .ops            = &phy_ops_10g_copper,
        .phy_addr_base  = 10,
@@ -1996,6 +2224,13 @@ static int niu_determine_phy_disposition(struct niu *np)
                            plat_type == PLAT_TYPE_VF_P1)
                                phy_addr_off = 8;
                        phy_addr_off += np->port;
+                       if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
+                               tp = &phy_template_10g_fiber_hotplug;
+                               if (np->port == 0)
+                                       phy_addr_off = 8;
+                               if (np->port == 1)
+                                       phy_addr_off = 12;
+                       }
                        break;
 
                case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
@@ -6773,6 +7008,37 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np,
        return 0;
 }
 
+/* niu board models have a trailing dash version incremented
+ * with HW rev change. Need to ingnore the  dash version while
+ * checking for match
+ *
+ * for example, for the 10G card the current vpd.board_model
+ * is 501-5283-04, of which -04 is the  dash version and have
+ * to be ignored
+ */
+static int niu_board_model_match(struct niu *np, const char *model)
+{
+       return !strncmp(np->vpd.board_model, model, strlen(model));
+}
+
+static int niu_pci_vpd_get_nports(struct niu *np)
+{
+       int ports = 0;
+
+       if ((niu_board_model_match(np, NIU_QGC_LP_BM_STR)) ||
+           (niu_board_model_match(np, NIU_QGC_PEM_BM_STR)) ||
+           (niu_board_model_match(np, NIU_ALONSO_BM_STR))) {
+               ports = 4;
+       } else if ((niu_board_model_match(np, NIU_2XGF_LP_BM_STR)) ||
+                  (niu_board_model_match(np, NIU_2XGF_PEM_BM_STR)) ||
+                  (niu_board_model_match(np, NIU_FOXXY_BM_STR)) ||
+                  (niu_board_model_match(np, NIU_2XGF_MRVL_BM_STR))) {
+               ports = 2;
+       }
+
+       return ports;
+}
+
 static void __devinit niu_pci_vpd_validate(struct niu *np)
 {
        struct net_device *dev = np->dev;
@@ -6799,6 +7065,9 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
                }
                if (np->flags & NIU_FLAGS_10G)
                         np->mac_xcvr = MAC_XCVR_XPCS;
+       } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
+               np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
+                             NIU_FLAGS_HOTPLUG_PHY);
        } else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
                dev_err(np->device, PFX "Illegal phy string [%s].\n",
                        np->vpd.phy_type);
@@ -6987,11 +7256,17 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
                if (parent->plat_type == PLAT_TYPE_NIU) {
                        parent->num_ports = 2;
                } else {
-                       parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
-                               ESPC_NUM_PORTS_MACS_VAL;
-
-                       if (!parent->num_ports)
-                               parent->num_ports = 4;
+                       parent->num_ports = niu_pci_vpd_get_nports(np);
+                       if (!parent->num_ports) {
+                               /* Fall back to SPROM as last resort.
+                                * This will fail on most cards.
+                                */
+                               parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
+                                       ESPC_NUM_PORTS_MACS_VAL;
+
+                               if (!parent->num_ports)
+                                       return -ENODEV;
+                       }
                }
        }
 
@@ -7015,7 +7290,8 @@ static int __devinit phy_record(struct niu_parent *parent,
                return 0;
        if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) {
                if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) &&
-                   ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011))
+                   ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011) &&
+                   ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8706))
                        return 0;
        } else {
                if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R)
@@ -7262,7 +7538,6 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
        u32 val;
        int err;
 
-
        if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
            !strcmp(np->vpd.model, "SUNW,CP3260")) {
                num_10g = 0;
@@ -7273,6 +7548,12 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
                       phy_encode(PORT_TYPE_1G, 1) |
                       phy_encode(PORT_TYPE_1G, 2) |
                       phy_encode(PORT_TYPE_1G, 3));
+       } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) {
+               num_10g = 2;
+               num_1g = 0;
+               parent->num_ports = 2;
+               val = (phy_encode(PORT_TYPE_10G, 0) |
+                      phy_encode(PORT_TYPE_10G, 1));
        } else {
                err = fill_phy_probe_info(np, parent, info);
                if (err)
@@ -7733,15 +8014,16 @@ static int __devinit niu_get_invariants(struct niu *np)
 
        have_props = !err;
 
-       err = niu_get_and_validate_port(np);
-       if (err)
-               return err;
-
        err = niu_init_mac_ipp_pcs_base(np);
        if (err)
                return err;
 
-       if (!have_props) {
+       if (have_props) {
+               err = niu_get_and_validate_port(np);
+               if (err)
+                       return err;
+
+       } else  {
                if (np->parent->plat_type == PLAT_TYPE_NIU)
                        return -EINVAL;
 
@@ -7753,10 +8035,17 @@ static int __devinit niu_get_invariants(struct niu *np)
                        niu_pci_vpd_fetch(np, offset);
                nw64(ESPC_PIO_EN, 0);
 
-               if (np->flags & NIU_FLAGS_VPD_VALID)
+               if (np->flags & NIU_FLAGS_VPD_VALID) {
                        niu_pci_vpd_validate(np);
+                       err = niu_get_and_validate_port(np);
+                       if (err)
+                               return err;
+               }
 
                if (!(np->flags & NIU_FLAGS_VPD_VALID)) {
+                       err = niu_get_and_validate_port(np);
+                       if (err)
+                               return err;
                        err = niu_pci_probe_sprom(np);
                        if (err)
                                return err;
index 336aed08b27507964394f3cca929c1c2b4112dd4..97ffbe137bcbaa20fbea8ae4eeedf54c9b9ac7a8 100644 (file)
@@ -2537,6 +2537,7 @@ struct fcram_hash_ipv6 {
 
 #define NIU_PHY_ID_MASK                        0xfffff0f0
 #define NIU_PHY_ID_BCM8704             0x00206030
+#define NIU_PHY_ID_BCM8706             0x00206035
 #define NIU_PHY_ID_BCM5464R            0x002060b0
 #define NIU_PHY_ID_MRVL88X2011         0x01410020
 
@@ -2937,6 +2938,15 @@ struct rx_ring_info {
 
 #define NIU_MAX_MTU            9216
 
+/* VPD strings */
+#define        NIU_QGC_LP_BM_STR       "501-7606"
+#define        NIU_2XGF_LP_BM_STR      "501-7283"
+#define        NIU_QGC_PEM_BM_STR      "501-7765"
+#define        NIU_2XGF_PEM_BM_STR     "501-7626"
+#define        NIU_ALONSO_BM_STR       "373-0202"
+#define        NIU_FOXXY_BM_STR        "501-7961"
+#define        NIU_2XGF_MRVL_BM_STR    "SK-6E82"
+
 #define NIU_VPD_MIN_MAJOR      3
 #define NIU_VPD_MIN_MINOR      4
 
@@ -3199,6 +3209,8 @@ struct niu {
        struct niu_parent               *parent;
 
        u32                             flags;
+#define NIU_FLAGS_HOTPLUG_PHY_PRESENT  0x02000000 /* Removebale PHY detected*/
+#define NIU_FLAGS_HOTPLUG_PHY          0x01000000 /* Removebale PHY */
 #define NIU_FLAGS_VPD_VALID            0x00800000 /* VPD has valid version */
 #define NIU_FLAGS_MSIX                 0x00400000 /* MSI-X in use */
 #define NIU_FLAGS_MCAST                        0x00200000 /* multicast filter enabled */
index 963630c65ca940d9dfc59ed57370c54dbfed7847..94e0b7ed76f16ff8c2c2a7f43aaf341c4cace12d 100644 (file)
@@ -89,6 +89,9 @@ int mdiobus_register(struct mii_bus *bus)
 
                        phydev->bus = bus;
 
+                       /* Run all of the fixups for this PHY */
+                       phy_scan_fixups(phydev);
+
                        err = device_register(&phydev->dev);
 
                        if (err) {
index 12fccb1c76dc0c147e3291aaad803c8d5dbc9caf..3c18bb594957a3e2e0320274ff88897189d8b594 100644 (file)
@@ -406,8 +406,10 @@ int phy_mii_ioctl(struct phy_device *phydev,
                
                if (mii_data->reg_num == MII_BMCR 
                                && val & BMCR_RESET
-                               && phydev->drv->config_init)
+                               && phydev->drv->config_init) {
+                       phy_scan_fixups(phydev);
                        phydev->drv->config_init(phydev);
+               }
                break;
 
        default:
index 8b1121b02f9806d9323cfea84fb157bc83c5ae08..ddf8d51832a679dcd7b2767bd8c9793d5b2a8a23 100644 (file)
@@ -53,6 +53,96 @@ static void phy_device_release(struct device *dev)
        phy_device_free(to_phy_device(dev));
 }
 
+static LIST_HEAD(phy_fixup_list);
+static DEFINE_MUTEX(phy_fixup_lock);
+
+/*
+ * Creates a new phy_fixup and adds it to the list
+ * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID)
+ * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY)
+ *     It can also be PHY_ANY_UID
+ * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before
+ *     comparison
+ * @run: The actual code to be run when a matching PHY is found
+ */
+int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *))
+{
+       struct phy_fixup *fixup;
+
+       fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL);
+       if (!fixup)
+               return -ENOMEM;
+
+       strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE);
+       fixup->phy_uid = phy_uid;
+       fixup->phy_uid_mask = phy_uid_mask;
+       fixup->run = run;
+
+       mutex_lock(&phy_fixup_lock);
+       list_add_tail(&fixup->list, &phy_fixup_list);
+       mutex_unlock(&phy_fixup_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(phy_register_fixup);
+
+/* Registers a fixup to be run on any PHY with the UID in phy_uid */
+int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *))
+{
+       return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run);
+}
+EXPORT_SYMBOL(phy_register_fixup_for_uid);
+
+/* Registers a fixup to be run on the PHY with id string bus_id */
+int phy_register_fixup_for_id(const char *bus_id,
+               int (*run)(struct phy_device *))
+{
+       return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run);
+}
+EXPORT_SYMBOL(phy_register_fixup_for_id);
+
+/*
+ * Returns 1 if fixup matches phydev in bus_id and phy_uid.
+ * Fixups can be set to match any in one or more fields.
+ */
+static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
+{
+       if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0)
+               if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
+                       return 0;
+
+       if ((fixup->phy_uid & fixup->phy_uid_mask) !=
+                       (phydev->phy_id & fixup->phy_uid_mask))
+               if (fixup->phy_uid != PHY_ANY_UID)
+                       return 0;
+
+       return 1;
+}
+
+/* Runs any matching fixups for this phydev */
+int phy_scan_fixups(struct phy_device *phydev)
+{
+       struct phy_fixup *fixup;
+
+       mutex_lock(&phy_fixup_lock);
+       list_for_each_entry(fixup, &phy_fixup_list, list) {
+               if (phy_needs_fixup(phydev, fixup)) {
+                       int err;
+
+                       err = fixup->run(phydev);
+
+                       if (err < 0)
+                               return err;
+               }
+       }
+       mutex_unlock(&phy_fixup_lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(phy_scan_fixups);
+
 struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
 {
        struct phy_device *dev;
@@ -179,13 +269,13 @@ void phy_prepare_link(struct phy_device *phydev,
  *   choose to call only the subset of functions which provide
  *   the desired functionality.
  */
-struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
                void (*handler)(struct net_device *), u32 flags,
                phy_interface_t interface)
 {
        struct phy_device *phydev;
 
-       phydev = phy_attach(dev, phy_id, flags, interface);
+       phydev = phy_attach(dev, bus_id, flags, interface);
 
        if (IS_ERR(phydev))
                return phydev;
@@ -226,7 +316,7 @@ static int phy_compare_id(struct device *dev, void *data)
 /**
  * phy_attach - attach a network device to a particular PHY device
  * @dev: network device to attach
- * @phy_id: PHY device to attach
+ * @bus_id: PHY device to attach
  * @flags: PHY device's dev_flags
  * @interface: PHY device's interface
  *
@@ -238,7 +328,7 @@ static int phy_compare_id(struct device *dev, void *data)
  *     change.  The phy_device is returned to the attaching driver.
  */
 struct phy_device *phy_attach(struct net_device *dev,
-               const char *phy_id, u32 flags, phy_interface_t interface)
+               const char *bus_id, u32 flags, phy_interface_t interface)
 {
        struct bus_type *bus = &mdio_bus_type;
        struct phy_device *phydev;
@@ -246,12 +336,12 @@ struct phy_device *phy_attach(struct net_device *dev,
 
        /* Search the list of PHY devices on the mdio bus for the
         * PHY with the requested name */
-       d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
+       d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id);
 
        if (d) {
                phydev = to_phy_device(d);
        } else {
-               printk(KERN_ERR "%s not found\n", phy_id);
+               printk(KERN_ERR "%s not found\n", bus_id);
                return ERR_PTR(-ENODEV);
        }
 
@@ -271,7 +361,7 @@ struct phy_device *phy_attach(struct net_device *dev,
 
        if (phydev->attached_dev) {
                printk(KERN_ERR "%s: %s already attached\n",
-                               dev->name, phy_id);
+                               dev->name, bus_id);
                return ERR_PTR(-EBUSY);
        }
 
@@ -287,6 +377,11 @@ struct phy_device *phy_attach(struct net_device *dev,
        if (phydev->drv->config_init) {
                int err;
 
+               err = phy_scan_fixups(phydev);
+
+               if (err < 0)
+                       return ERR_PTR(err);
+
                err = phydev->drv->config_init(phydev);
 
                if (err < 0)
@@ -395,6 +490,7 @@ EXPORT_SYMBOL(genphy_config_advert);
  */
 int genphy_setup_forced(struct phy_device *phydev)
 {
+       int err;
        int ctl = 0;
 
        phydev->pause = phydev->asym_pause = 0;
@@ -407,17 +503,26 @@ int genphy_setup_forced(struct phy_device *phydev)
        if (DUPLEX_FULL == phydev->duplex)
                ctl |= BMCR_FULLDPLX;
        
-       ctl = phy_write(phydev, MII_BMCR, ctl);
+       err = phy_write(phydev, MII_BMCR, ctl);
 
-       if (ctl < 0)
-               return ctl;
+       if (err < 0)
+               return err;
+
+       /*
+        * Run the fixups on this PHY, just in case the
+        * board code needs to change something after a reset
+        */
+       err = phy_scan_fixups(phydev);
+
+       if (err < 0)
+               return err;
 
        /* We just reset the device, so we'd better configure any
         * settings the PHY requires to operate */
        if (phydev->drv->config_init)
-               ctl = phydev->drv->config_init(phydev);
+               err = phydev->drv->config_init(phydev);
 
-       return ctl;
+       return err;
 }
 
 
index dcbe01b0ca0de05d3c21d75f5661858d88157232..157fd932e95140ce54936e3d0a79bdb30cd25048 100644 (file)
@@ -86,7 +86,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.20"
+#define DRV_VERSION "2.0.26.22"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -117,20 +117,6 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
 
 #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
                                      ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
-#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status))
-#define PANIC  1
-#define LOW    2
-static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring)
-{
-       struct mac_info *mac_control;
-
-       mac_control = &sp->mac_control;
-       if (rxb_size <= rxd_count[sp->rxd_mode])
-               return PANIC;
-       else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
-               return  LOW;
-       return 0;
-}
 
 static inline int is_s2io_card_up(const struct s2io_nic * sp)
 {
@@ -2458,7 +2444,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
        for (i = 0; i < config->tx_fifo_num; i++) {
                unsigned long flags;
                spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags);
-               for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
+               for (j = 0; j < config->tx_cfg[i].fifo_len; j++) {
                        txdp = (struct TxD *) \
                        mac_control->fifos[i].list_info[j].list_virt_addr;
                        skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
@@ -2544,7 +2530,6 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
        struct config_param *config;
        u64 tmp;
        struct buffAdd *ba;
-       unsigned long flags;
        struct RxD_t *first_rxdp = NULL;
        u64 Buffer0_ptr = 0, Buffer1_ptr = 0;
        struct RxD1 *rxdp1;
@@ -2592,15 +2577,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                        DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
                                  dev->name, rxdp);
                }
-               if(!napi) {
-                       spin_lock_irqsave(&nic->put_lock, flags);
-                       mac_control->rings[ring_no].put_pos =
-                       (block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
-                       spin_unlock_irqrestore(&nic->put_lock, flags);
-               } else {
-                       mac_control->rings[ring_no].put_pos =
-                       (block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
-               }
+
                if ((rxdp->Control_1 & RXD_OWN_XENA) &&
                        ((nic->rxd_mode == RXD_MODE_3B) &&
                                (rxdp->Control_2 & s2BIT(0)))) {
@@ -2978,7 +2955,7 @@ static void rx_intr_handler(struct ring_info *ring_data)
 {
        struct s2io_nic *nic = ring_data->nic;
        struct net_device *dev = (struct net_device *) nic->dev;
-       int get_block, put_block, put_offset;
+       int get_block, put_block;
        struct rx_curr_get_info get_info, put_info;
        struct RxD_t *rxdp;
        struct sk_buff *skb;
@@ -2987,19 +2964,11 @@ static void rx_intr_handler(struct ring_info *ring_data)
        struct RxD1* rxdp1;
        struct RxD3* rxdp3;
 
-       spin_lock(&nic->rx_lock);
-
        get_info = ring_data->rx_curr_get_info;
        get_block = get_info.block_index;
        memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info));
        put_block = put_info.block_index;
        rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr;
-       if (!napi) {
-               spin_lock(&nic->put_lock);
-               put_offset = ring_data->put_pos;
-               spin_unlock(&nic->put_lock);
-       } else
-               put_offset = ring_data->put_pos;
 
        while (RXD_IS_UP2DT(rxdp)) {
                /*
@@ -3016,7 +2985,6 @@ static void rx_intr_handler(struct ring_info *ring_data)
                        DBG_PRINT(ERR_DBG, "%s: The skb is ",
                                  dev->name);
                        DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
-                       spin_unlock(&nic->rx_lock);
                        return;
                }
                if (nic->rxd_mode == RXD_MODE_1) {
@@ -3072,8 +3040,6 @@ static void rx_intr_handler(struct ring_info *ring_data)
                        }
                }
        }
-
-       spin_unlock(&nic->rx_lock);
 }
 
 /**
@@ -4105,7 +4071,6 @@ static int s2io_close(struct net_device *dev)
                        do_s2io_delete_unicast_mc(sp, tmp64);
        }
 
-       /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
 
        return 0;
@@ -4370,29 +4335,9 @@ s2io_alarm_handle(unsigned long data)
 
 static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n)
 {
-       int rxb_size, level;
-
-       if (!sp->lro) {
-               rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
-               level = rx_buffer_level(sp, rxb_size, rng_n);
-
-               if ((level == PANIC) && (!TASKLET_IN_USE)) {
-                       int ret;
-                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
-                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
-                       if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
-                               DBG_PRINT(INFO_DBG, "Out of memory in %s",
-                                         __FUNCTION__);
-                               clear_bit(0, (&sp->tasklet_status));
-                               return -1;
-                       }
-                       clear_bit(0, (&sp->tasklet_status));
-               } else if (level == LOW)
-                       tasklet_schedule(&sp->task);
-
-       } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
-                       DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
-                       DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
+       if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
+               DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
+               DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
        }
        return 0;
 }
@@ -6769,49 +6714,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
        return ret;
 }
 
-/**
- *  s2io_tasklet - Bottom half of the ISR.
- *  @dev_adr : address of the device structure in dma_addr_t format.
- *  Description:
- *  This is the tasklet or the bottom half of the ISR. This is
- *  an extension of the ISR which is scheduled by the scheduler to be run
- *  when the load on the CPU is low. All low priority tasks of the ISR can
- *  be pushed into the tasklet. For now the tasklet is used only to
- *  replenish the Rx buffers in the Rx buffer descriptors.
- *  Return value:
- *  void.
- */
-
-static void s2io_tasklet(unsigned long dev_addr)
-{
-       struct net_device *dev = (struct net_device *) dev_addr;
-       struct s2io_nic *sp = dev->priv;
-       int i, ret;
-       struct mac_info *mac_control;
-       struct config_param *config;
-
-       mac_control = &sp->mac_control;
-       config = &sp->config;
-
-       if (!TASKLET_IN_USE) {
-               for (i = 0; i < config->rx_ring_num; i++) {
-                       ret = fill_rx_buffers(sp, i);
-                       if (ret == -ENOMEM) {
-                               DBG_PRINT(INFO_DBG, "%s: Out of ",
-                                         dev->name);
-                               DBG_PRINT(INFO_DBG, "memory in tasklet\n");
-                               break;
-                       } else if (ret == -EFILL) {
-                               DBG_PRINT(INFO_DBG,
-                                         "%s: Rx Ring %d is full\n",
-                                         dev->name, i);
-                               break;
-                       }
-               }
-               clear_bit(0, (&sp->tasklet_status));
-       }
-}
-
 /**
  * s2io_set_link - Set the LInk status
  * @data: long pointer to device private structue
@@ -7161,7 +7063,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
 {
        int cnt = 0;
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
-       unsigned long flags;
        register u64 val64 = 0;
        struct config_param *config;
        config = &sp->config;
@@ -7186,9 +7087,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
 
        s2io_rem_isr(sp);
 
-       /* Kill tasklet. */
-       tasklet_kill(&sp->task);
-
        /* Check if the device is Quiescent and then Reset the NIC */
        while(do_io) {
                /* As per the HW requirement we need to replenish the
@@ -7223,9 +7121,7 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
        free_tx_buffers(sp);
 
        /* Free all Rx buffers */
-       spin_lock_irqsave(&sp->rx_lock, flags);
        free_rx_buffers(sp);
-       spin_unlock_irqrestore(&sp->rx_lock, flags);
 
        clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state));
 }
@@ -7314,9 +7210,6 @@ static int s2io_card_up(struct s2io_nic * sp)
 
        S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
 
-       /* Enable tasklet for the device */
-       tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
-
        /*  Enable select interrupts */
        en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
        if (sp->config.intr_type != INTA)
@@ -8119,20 +8012,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        s2io_reset(sp);
 
        /*
-        * Initialize the tasklet status and link state flags
+        * Initialize link state flags
         * and the card state parameter
         */
-       sp->tasklet_status = 0;
        sp->state = 0;
 
        /* Initialize spinlocks */
        for (i = 0; i < sp->config.tx_fifo_num; i++)
                spin_lock_init(&mac_control->fifos[i].tx_lock);
 
-       if (!napi)
-               spin_lock_init(&sp->put_lock);
-       spin_lock_init(&sp->rx_lock);
-
        /*
         * SXE-002: Configure link and activity LED to init state
         * on driver load.
index e68fdf7e42600558ff7114772b58c8ed65c3ece7..ce53a02105f25ab99aee4e017c74b4c04a2e2600 100644 (file)
@@ -703,9 +703,6 @@ struct ring_info {
         */
        struct rx_curr_get_info rx_curr_get_info;
 
-       /* Index to the absolute position of the put pointer of Rx ring */
-       int put_pos;
-
        /* Buffer Address store. */
        struct buffAdd **ba;
        struct s2io_nic *nic;
@@ -868,8 +865,6 @@ struct s2io_nic {
        int device_enabled_once;
 
        char name[60];
-       struct tasklet_struct task;
-       volatile unsigned long tasklet_status;
 
        /* Timer that handles I/O errors/exceptions */
        struct timer_list alarm_timer;
@@ -879,8 +874,6 @@ struct s2io_nic {
 
        atomic_t rx_bufs_left[MAX_RX_RINGS];
 
-       spinlock_t put_lock;
-
 #define PROMISC     1
 #define ALL_MULTI   2
 
@@ -964,7 +957,6 @@ struct s2io_nic {
        u8              lro;
        u16             lro_max_aggr_per_sess;
        volatile unsigned long state;
-       spinlock_t      rx_lock;
        u64             general_int_mask;
 #define VPD_STRING_LEN 80
        u8  product_name[VPD_STRING_LEN];
@@ -1094,7 +1086,6 @@ static void s2io_handle_errors(void * dev_id);
 static int s2io_starter(void);
 static void s2io_closer(void);
 static void s2io_tx_watchdog(struct net_device *dev);
-static void s2io_tasklet(unsigned long dev_addr);
 static void s2io_set_multicast(struct net_device *dev);
 static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp);
 static void s2io_link(struct s2io_nic * sp, int link);
index 78994ede0cb0666945dc3d35e1061b1cc3cc8aee..6261201403cdd143ca592a880ca5052c167522d9 100644 (file)
@@ -825,7 +825,8 @@ static struct platform_driver sgiseeq_driver = {
        .probe  = sgiseeq_probe,
        .remove = __devexit_p(sgiseeq_remove),
        .driver = {
-               .name   = "sgiseeq"
+               .name   = "sgiseeq",
+               .owner  = THIS_MODULE,
        }
 };
 
@@ -850,3 +851,4 @@ module_exit(sgiseeq_module_exit);
 MODULE_DESCRIPTION("SGI Seeq 8003 driver");
 MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sgiseeq");
index 76cc1d3adf715fc635a58db2c2b9df40789f7a56..4e28002051899c21f0a6050b5b32f14b6f2c6dec 100644 (file)
@@ -92,6 +92,7 @@ module_param(tx_fifo_kb, int, 0400);
 MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)");
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:smc911x");
 
 /*
  * The internal workings of the driver.  If you are changing anything
@@ -243,7 +244,7 @@ static void smc911x_reset(struct net_device *dev)
                do {
                        udelay(10);
                        reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_;
-               } while ( timeout-- && !reg);
+               } while (--timeout && !reg);
                if (timeout == 0) {
                        PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name);
                        return;
@@ -267,7 +268,7 @@ static void smc911x_reset(struct net_device *dev)
                                resets++;
                                break;
                        }
-               } while ( timeout-- && (reg & HW_CFG_SRST_));
+               } while (--timeout && (reg & HW_CFG_SRST_));
        }
        if (timeout == 0) {
                PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name);
@@ -413,7 +414,7 @@ static inline void smc911x_drop_pkt(struct net_device *dev)
                do {
                        udelay(10);
                        reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_;
-               } while ( timeout-- && reg);
+               } while (--timeout && reg);
                if (timeout == 0) {
                        PRINTK("%s: timeout waiting for RX fast forward\n", dev->name);
                }
@@ -2262,6 +2263,7 @@ static struct platform_driver smc911x_driver = {
        .resume  = smc911x_drv_resume,
        .driver  = {
                .name    = CARDNAME,
+               .owner  = THIS_MODULE,
        },
 };
 
index 600b92af33349c1d5a2ed782f0aba89f0fa4a229..a188e33484e631326f366edd68b33f635fce94e6 100644 (file)
@@ -132,6 +132,7 @@ module_param(watchdog, int, 0400);
 MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:smc91x");
 
 /*
  * The internal workings of the driver.  If you are changing anything
@@ -2308,6 +2309,7 @@ static struct platform_driver smc_driver = {
        .resume         = smc_drv_resume,
        .driver         = {
                .name   = CARDNAME,
+               .owner  = THIS_MODULE,
        },
 };
 
index 2cf6794acb4f9368a8f99ca94952c3766395fc97..854ccf2b4105efd1958a46eb942bb96928d511d2 100644 (file)
@@ -44,6 +44,7 @@ static const char sni_82596_string[] = "snirm_82596";
 MODULE_AUTHOR("Thomas Bogendoerfer");
 MODULE_DESCRIPTION("i82596 driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:snirm_82596");
 module_param(i596_debug, int, 0);
 MODULE_PARM_DESC(i596_debug, "82596 debug mask");
 
@@ -166,6 +167,7 @@ static struct platform_driver sni_82596_driver = {
        .remove = __devexit_p(sni_82596_driver_remove),
        .driver = {
                .name   = sni_82596_string,
+               .owner  = THIS_MODULE,
        },
 };
 
index 17585e5eed5379c2299f85f92a3956768850161e..e83b166aa6b9a53aeeb00a70224d10e46660f638 100644 (file)
@@ -625,6 +625,12 @@ static void __init bdx_firmware_endianess(void)
                s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]);
 }
 
+static int bdx_range_check(struct bdx_priv *priv, u32 offset)
+{
+       return (offset > (u32) (BDX_REGS_SIZE / priv->nic->port_num)) ?
+               -EINVAL : 0;
+}
+
 static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
 {
        struct bdx_priv *priv = ndev->priv;
@@ -643,9 +649,15 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
        }
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        switch (data[0]) {
 
        case BDX_OP_READ:
+               error = bdx_range_check(priv, data[1]);
+               if (error < 0)
+                       return error;
                data[2] = READ_REG(priv, data[1]);
                DBG("read_reg(0x%x)=0x%x (dec %d)\n", data[1], data[2],
                    data[2]);
@@ -655,6 +667,9 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                break;
 
        case BDX_OP_WRITE:
+               error = bdx_range_check(priv, data[1]);
+               if (error < 0)
+                       return error;
                WRITE_REG(priv, data[1], data[2]);
                DBG("write_reg(0x%x, 0x%x)\n", data[1], data[2]);
                break;
index bc4c62b8e81a4d7be3441bdc578daf3689646ab2..e3f74c9f78bd848f1e61aa6647f7109e7282fd7c 100644 (file)
@@ -4017,6 +4017,8 @@ static int tg3_halt(struct tg3 *, int, int);
  * Invoked with tp->lock held.
  */
 static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
+       __releases(tp->lock)
+       __acquires(tp->lock)
 {
        int err;
 
index 6f33f84d37b0631652d04825b58a554cc7477dc7..6017d5267d08f4c80939834385cc7d3c591ca8be 100644 (file)
@@ -162,6 +162,7 @@ static struct platform_driver tsi_eth_driver = {
        .remove = tsi108_ether_remove,
        .driver = {
                .name = "tsi-ethernet",
+               .owner = THIS_MODULE,
        },
 };
 
@@ -1729,3 +1730,4 @@ module_exit(tsi108_ether_exit);
 MODULE_AUTHOR("Tundra Semiconductor Corporation");
 MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tsi-ethernet");
index 333961bb7873973df7c75e5870aaee1f458ec47f..c0dd25ba7a18dcd9cc7969e85f1e02ce954af797 100644 (file)
@@ -2183,7 +2183,6 @@ typhoon_resume(struct pci_dev *pdev)
        }
 
        netif_device_attach(dev);
-       netif_start_queue(dev);
        return 0;
 
 reset:
index 2f11254bcc077fa22f506a1481221150429d3bee..281ce3d395324787c8b986f0dae5648e793aa853 100644 (file)
@@ -3932,7 +3932,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
        fixed_link = of_get_property(np, "fixed-link", NULL);
        if (fixed_link) {
-               ug_info->mdio_bus = 0;
+               snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "0");
                ug_info->phy_address = fixed_link[0];
                phy = NULL;
        } else {
index ed1afaf683a4bb96481325165929542bf04e6db8..6b8d882d197b4c450e25c302e238d462718226c8 100644 (file)
@@ -605,7 +605,6 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index,
 static void velocity_init_cam_filter(struct velocity_info *vptr)
 {
        struct mac_regs __iomem * regs = vptr->mac_regs;
-       unsigned short vid;
 
        /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
        WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
@@ -617,29 +616,33 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
        mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
        mac_set_cam_mask(regs, vptr->mCAMmask);
 
-       /* Enable first VCAM */
+       /* Enable VCAMs */
        if (vptr->vlgrp) {
-               for (vid = 0; vid < VLAN_VID_MASK; vid++) {
-                       if (vlan_group_get_device(vptr->vlgrp, vid)) {
-                               /* If Tagging option is enabled and
-                                  VLAN ID is not zero, then
-                                  turn on MCFG_RTGOPT also */
-                               if (vid != 0)
-                                       WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
+               unsigned int vid, i = 0;
+
+               if (!vlan_group_get_device(vptr->vlgrp, 0))
+                       WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
 
-                               mac_set_vlan_cam(regs, 0, (u8 *) &vid);
+               for (vid = 1; (vid < VLAN_VID_MASK); vid++) {
+                       if (vlan_group_get_device(vptr->vlgrp, vid)) {
+                               mac_set_vlan_cam(regs, i, (u8 *) &vid);
+                               vptr->vCAMmask[i / 8] |= 0x1 << (i % 8);
+                               if (++i >= VCAM_SIZE)
+                                       break;
                        }
                }
-               vptr->vCAMmask[0] |= 1;
                mac_set_vlan_cam_mask(regs, vptr->vCAMmask);
-       } else {
-               u16 temp = 0;
-               mac_set_vlan_cam(regs, 0, (u8 *) &temp);
-               temp = 1;
-               mac_set_vlan_cam_mask(regs, (u8 *) &temp);
        }
 }
 
+static void velocity_vlan_rx_register(struct net_device *dev,
+                                     struct vlan_group *grp)
+{
+       struct velocity_info *vptr = netdev_priv(dev);
+
+       vptr->vlgrp = grp;
+}
+
 static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
        struct velocity_info *vptr = netdev_priv(dev);
@@ -959,11 +962,13 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
 
        dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid;
        dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid;
+       dev->vlan_rx_register = velocity_vlan_rx_register;
 
 #ifdef  VELOCITY_ZERO_COPY_SUPPORT
        dev->features |= NETIF_F_SG;
 #endif
-       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER;
+       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
+               NETIF_F_HW_VLAN_RX;
 
        if (vptr->flags & VELOCITY_FLAGS_TX_CSUM)
                dev->features |= NETIF_F_IP_CSUM;
@@ -1597,8 +1602,13 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
        skb_put(skb, pkt_len - 4);
        skb->protocol = eth_type_trans(skb, vptr->dev);
 
+       if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) {
+               vlan_hwaccel_rx(skb, vptr->vlgrp,
+                               swab16(le16_to_cpu(rd->rdesc1.PQTAG)));
+       } else
+               netif_rx(skb);
+
        stats->rx_bytes += pkt_len;
-       netif_rx(skb);
 
        return 0;
 }
index c4c8eab8574f79bb36fc3352648d8df09ab579fb..c2cc42f723d5fdd517ca209183b0b147645cff4b 100644 (file)
@@ -402,7 +402,7 @@ static int __init c101_init(void)
 #ifdef MODULE
                printk(KERN_INFO "c101: no card initialized\n");
 #endif
-               return -ENOSYS; /* no parameters specified, abort */
+               return -EINVAL; /* no parameters specified, abort */
        }
 
        printk(KERN_INFO "%s\n", version);
@@ -420,11 +420,11 @@ static int __init c101_init(void)
                        c101_run(irq, ram);
 
                if (*hw == '\x0')
-                       return first_card ? 0 : -ENOSYS;
+                       return first_card ? 0 : -EINVAL;
        }while(*hw++ == ':');
 
        printk(KERN_ERR "c101: invalid hardware parameters\n");
-       return first_card ? 0 : -ENOSYS;
+       return first_card ? 0 : -EINVAL;
 }
 
 
index c4ab0326f91103b03dcd01dd7b1a153101ef4ea9..520bb0b1a9a2f6f1c6a74d00d9200631fda23bf5 100644 (file)
@@ -1090,10 +1090,6 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
        pvc_device *pvc = NULL;
        struct net_device *dev;
        int result, used;
-       char * prefix = "pvc%d";
-
-       if (type == ARPHRD_ETHER)
-               prefix = "pvceth%d";
 
        if ((pvc = add_pvc(frad, dlci)) == NULL) {
                printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
index 779cbcd65f62d50ae56b897deff6adca44496cad..02df20f085fe9e89637affb8cb880d2a1f153628 100644 (file)
@@ -379,6 +379,18 @@ struct phy_driver {
 };
 #define to_phy_driver(d) container_of(d, struct phy_driver, driver)
 
+#define PHY_ANY_ID "MATCH ANY PHY"
+#define PHY_ANY_UID 0xffffffff
+
+/* A Structure for boards to register fixups with the PHY Lib */
+struct phy_fixup {
+       struct list_head list;
+       char bus_id[BUS_ID_SIZE];
+       u32 phy_uid;
+       u32 phy_uid_mask;
+       int (*run)(struct phy_device *phydev);
+};
+
 int phy_read(struct phy_device *phydev, u16 regnum);
 int phy_write(struct phy_device *phydev, u16 regnum, u16 val);
 int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id);
@@ -386,8 +398,8 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr);
 int phy_clear_interrupt(struct phy_device *phydev);
 int phy_config_interrupt(struct phy_device *phydev, u32 interrupts);
 struct phy_device * phy_attach(struct net_device *dev,
-               const char *phy_id, u32 flags, phy_interface_t interface);
-struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
+               const char *bus_id, u32 flags, phy_interface_t interface);
+struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
                void (*handler)(struct net_device *), u32 flags,
                phy_interface_t interface);
 void phy_disconnect(struct phy_device *phydev);
@@ -427,5 +439,13 @@ void phy_print_status(struct phy_device *phydev);
 struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
 void phy_device_free(struct phy_device *phydev);
 
+int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *));
+int phy_register_fixup_for_id(const char *bus_id,
+               int (*run)(struct phy_device *));
+int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
+               int (*run)(struct phy_device *));
+int phy_scan_fixups(struct phy_device *phydev);
+
 extern struct bus_type mdio_bus_type;
 #endif /* __PHY_H */
index 0c82c80b277f935f25e43c2a83ea348b1481153a..2ca6bae88721920215a649bc437393733452aae9 100644 (file)
@@ -97,10 +97,10 @@ struct xfrm_algo {
 };
 
 struct xfrm_algo_aead {
-       char    alg_name[64];
-       int     alg_key_len;    /* in bits */
-       int     alg_icv_len;    /* in bits */
-       char    alg_key[0];
+       char            alg_name[64];
+       unsigned int    alg_key_len;    /* in bits */
+       unsigned int    alg_icv_len;    /* in bits */
+       char            alg_key[0];
 };
 
 struct xfrm_stats {
index ead50c7c0d40f54e8b05d7b1c9e04cdef5b92fb2..201cbfc6b9ece724b3cda9427f27d976534567c7 100644 (file)
@@ -573,7 +573,8 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
                        int fsize = ro->count * sizeof(struct can_filter);
                        if (len > fsize)
                                len = fsize;
-                       err = copy_to_user(optval, ro->filter, len);
+                       if (copy_to_user(optval, ro->filter, len))
+                               err = -EFAULT;
                } else
                        len = 0;
                release_sock(sk);
index a29b43d0b450a5e1a265375bd4f77797f0b23d79..0133b5ebd545287be9a2ee19d8fbf75db8e9ca59 100644 (file)
@@ -323,6 +323,11 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
                bytes_remaining -= eeprom.len;
        }
 
+       eeprom.len = userbuf - (useraddr + sizeof(eeprom));
+       eeprom.offset -= eeprom.len;
+       if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
+               ret = -EFAULT;
+
        kfree(data);
        return ret;
 }
index 6e1df62bd7c9167dc6e123b20c5af79ce30537c3..0bcdc92502794867b7254bc338044555b6493245 100644 (file)
@@ -140,7 +140,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf,
                goto out_free;
 
        cnt = kfifo_get(dccpw.fifo, tbuf, len);
-       error = copy_to_user(buf, tbuf, cnt);
+       error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0;
 
 out_free:
        vfree(tbuf);
index 1c509592574a79d6ee53a6104e8cfe6466058a5c..5ff0ce6e9d39d25538f5c98dff986231fbaebcc9 100644 (file)
@@ -190,19 +190,18 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf,
 
                width = tcpprobe_sprint(tbuf, sizeof(tbuf));
 
-               if (width < len)
+               if (cnt + width < len)
                        tcp_probe.tail = (tcp_probe.tail + 1) % bufsize;
 
                spin_unlock_bh(&tcp_probe.lock);
 
                /* if record greater than space available
                   return partial buffer (so far) */
-               if (width >= len)
+               if (cnt + width >= len)
                        break;
 
-               error = copy_to_user(buf + cnt, tbuf, width);
-               if (error)
-                       break;
+               if (copy_to_user(buf + cnt, tbuf, width))
+                       return -EFAULT;
                cnt += width;
        }
 
index 42814a2ec9d73f0249b53386e997104cde4dee64..b2c9becc02e8cad4e6453578587cabc6a7701c52 100644 (file)
@@ -167,7 +167,7 @@ config IPV6_SIT
          Tunneling means encapsulating data of one protocol type within
          another protocol and sending it over a channel that understands the
          encapsulating protocol. This driver implements encapsulation of IPv6
-         into IPv4 packets. This is useful if you want to connect two IPv6
+         into IPv4 packets. This is useful if you want to connect to IPv6
          networks over an IPv4-only path.
 
          Saying M here will produce a module called sit.ko. If unsure, say Y.
index 6193b124cbc764bd367df15addead75c07ae0322..396f0ea11090a98d6a07898d0e79d58fb7652313 100644 (file)
@@ -971,6 +971,19 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
 
        switch (optname) {
                case IPV6_CHECKSUM:
+                       if (inet_sk(sk)->num == IPPROTO_ICMPV6 &&
+                           level == IPPROTO_IPV6) {
+                               /*
+                                * RFC3542 tells that IPV6_CHECKSUM socket
+                                * option in the IPPROTO_IPV6 level is not
+                                * allowed on ICMPv6 sockets.
+                                * If you want to set it, use IPPROTO_RAW
+                                * level IPV6_CHECKSUM socket option
+                                * (Linux extension).
+                                */
+                               return -EINVAL;
+                       }
+
                        /* You may get strange result with a positive odd offset;
                           RFC2292bis agrees with me. */
                        if (val > 0 && (val&1))
@@ -1046,6 +1059,11 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
 
        switch (optname) {
        case IPV6_CHECKSUM:
+               /*
+                * We allow getsockopt() for IPPROTO_IPV6-level
+                * IPV6_CHECKSUM socket option on ICMPv6 sockets
+                * since RFC3542 is silent about it.
+                */
                if (rp->checksum == 0)
                        val = -1;
                else
index 81a8e5297ad113be9d1c09de897df283532c9632..2403a31fe0f64ea6de774982e2ba3c6b7ea36a35 100644 (file)
@@ -2356,7 +2356,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
        struct xfrm_selector sel;
        struct km_event c;
        struct sadb_x_sec_ctx *sec_ctx;
-       struct xfrm_sec_ctx *pol_ctx;
+       struct xfrm_sec_ctx *pol_ctx = NULL;
 
        if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
                                     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2396,8 +2396,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
                kfree(uctx);
                if (err)
                        return err;
-       } else
-               pol_ctx = NULL;
+       }
 
        xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN,
                                   pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
index 05853159536a03b984708c400808dcf6e26fcb77..230f9ca2ad6b361dd4e78e6a2f1247334e9b9d22 100644 (file)
@@ -1756,8 +1756,8 @@ static int getsockopt(struct socket *sock,
        else if (len < sizeof(value)) {
                res = -EINVAL;
        }
-       else if ((res = copy_to_user(ov, &value, sizeof(value)))) {
-               /* couldn't return value */
+       else if (copy_to_user(ov, &value, sizeof(value))) {
+               res = -EFAULT;
        }
        else {
                res = put_user(sizeof(value), ol);