[PATCH 8/13] tg3: Limit 5784 / 5764 to MAC LED mode

2007-11-09 Thread Matt Carlson
Most 5784 / 5764 LED modes do not work as expected because of a hardware
bug.  This patch forces the LED mode to be in MAC LED mode.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b5c4799..bb3b734 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10610,6 +10610,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 
*tp)
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0)
+   tp->led_ctrl = LED_CTRL_MODE_MAC;
+
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
if ((tp->pdev->subsystem_vendor ==


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/13] tg3: APE flag fix

2007-11-09 Thread Matt Carlson
This patch corrects a bug where the ENABLE_APE flag was tested against
the wrong flag variable.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 82b1cf0..833cb9b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10881,7 +10881,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
}
 
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
-(tp->tg3_flags & TG3_FLG3_ENABLE_APE))
+(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return;
 
for (offset = TG3_NVM_DIR_START;


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/13] tg3: Add A1 revs

2007-11-09 Thread Matt Carlson
This patch adds the A1 revision of 5784, 5764, and 5761, and applies all
previous bugfixes.  In places where the list of devices gets too long,
the patch uses a new TG3_FLG3_5761_5784_AX_FIXES flag instead.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 72db78b..8e76092 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1106,8 +1106,7 @@ static int tg3_phy_reset(struct tg3 *tp)
if (err)
return err;
 
-   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
+   if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
u32 val;
 
val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
@@ -1352,8 +1351,7 @@ static void tg3_power_down_phy(struct tg3 *tp)
 (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
return;
 
-   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
+   if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
val |= CPMU_LSPD_1000MB_MACCLK_12_5;
@@ -3154,7 +3152,8 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
err = tg3_setup_copper_phy(tp, force_reset);
}
 
-   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
u32 val, scale;
 
val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
@@ -6390,7 +6389,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
tg3_write_sig_legacy(tp, RESET_KIND_INIT);
 
-   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
val = tr32(TG3_CPMU_CTRL);
val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
tw32(TG3_CPMU_CTRL, val);
@@ -9379,8 +9379,7 @@ static int tg3_test_loopback(struct tg3 *tp)
if (err)
return TG3_LOOPBACK_FAILED;
 
-   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
+   if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
int i;
u32 status;
 
@@ -9407,8 +9406,7 @@ static int tg3_test_loopback(struct tg3 *tp)
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
 
-   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
-   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
+   if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
tw32(TG3_CPMU_CTRL, cpmuctrl);
 
/* Release the mutex */
@@ -10629,7 +10627,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 
*tp)
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
-   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0)
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5784_A1)
tp->led_ctrl = LED_CTRL_MODE_MAC;
 
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
@@ -11401,9 +11400,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
 
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
-   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
 
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5761_A1)
+   tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES;
+   }
+
/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
 * GPIO1 driven high will bring 5700's external PHY out of reset.
 * It is also used as eeprom write protect on LOMs.
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index d325ab5..da18fb2 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -109,7 +109,9 @@
 #define  CHIPREV_ID_5714_A2 0x9002
 #define  CHIPREV_ID_5906_A1 0xc001
 #define  CHIPREV_ID_5784_A0 0x5784000
+#define  CHIPREV_ID_5784_A1 0x5784001
 #define  CHIPREV_ID_5761_A0 0x5761000
+#define  CHIPREV_ID_5761_A1  

[PATCH 12/13] tg3: MII => TP

2007-11-09 Thread Matt Carlson
This patch changes the PHY type reported through ethtool for copper
devices from MII to TP.  The latter is more accurate.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 8e76092..8d518cc 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -8329,7 +8329,7 @@ static int tg3_get_settings(struct net_device *dev, 
struct ethtool_cmd *cmd)
  SUPPORTED_100baseT_Full |
  SUPPORTED_10baseT_Half |
  SUPPORTED_10baseT_Full |
- SUPPORTED_MII);
+ SUPPORTED_TP);
cmd->port = PORT_TP;
} else {
cmd->supported |= SUPPORTED_FIBRE;


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 13/13] tg3: Update version to 3.86

2007-11-09 Thread Matt Carlson
This patch updates the version number to 3.86

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 8d518cc..4942f7d 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME"tg3"
 #define PFX DRV_MODULE_NAME": "
-#define DRV_MODULE_VERSION "3.85"
-#define DRV_MODULE_RELDATE "October 18, 2007"
+#define DRV_MODULE_VERSION "3.86"
+#define DRV_MODULE_RELDATE "November 9, 2007"
 
 #define TG3_DEF_MAC_MODE   0
 #define TG3_DEF_RX_MODE0


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/13] tg3: Increase the PCI MRRS

2007-11-09 Thread Matt Carlson
Previous devices hardcoded the PCI Maximum Read Request Size to 4K.  To
better comply with the PCI spec, the hardware now defaults the MRRS to
512 bytes.  This will yield poor driver performance if left untouched.
This patch increases the MRRS to 4K on driver initialization.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ecd64a2..72db78b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5098,12 +5098,15 @@ static void tg3_restore_pci_state(struct tg3 *tp)
 
pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
 
-   if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+   if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+   pcie_set_readrq(tp->pdev, 4096);
+   else {
pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
  tp->pci_cacheline_sz);
pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
  tp->pci_lat_timer);
}
+
/* Make sure PCI-X relaxed ordering bit is clear. */
if (tp->pcix_cap) {
u16 pcix_cmd;
@@ -11215,6 +11218,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
if (pcie_cap != 0) {
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+
+   pcie_set_readrq(tp->pdev, 4096);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
u16 lnkctl;
 


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/13] tg3: Disable GPHY autopowerdown

2007-11-09 Thread Matt Carlson
New CPMU devices contend with the GPHY for power management.  The GPHY
autopowerdown feature is enabled by default in the PHY and thus needs to
be disabled after every PHY reset.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 25e57d8..b5c4799 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1117,6 +1117,12 @@ static int tg3_phy_reset(struct tg3 *tp)
udelay(40);
tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
}
+
+   /* Disable GPHY autopowerdown. */
+   tg3_writephy(tp, MII_TG3_MISC_SHDW,
+MII_TG3_MISC_SHDW_WREN |
+MII_TG3_MISC_SHDW_APD_SEL |
+MII_TG3_MISC_SHDW_APD_WKTM_84MS);
}
 
 out:
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index f715b35..5b799ff 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1715,6 +1715,12 @@
 #define MII_TG3_ISTAT  0x1a /* IRQ status register */
 #define MII_TG3_IMASK  0x1b /* IRQ mask register */
 
+#define MII_TG3_MISC_SHDW  0x1c
+#define MII_TG3_MISC_SHDW_WREN 0x8000
+#define MII_TG3_MISC_SHDW_APD_SEL  0x2800
+
+#define MII_TG3_MISC_SHDW_APD_WKTM_84MS0x0001
+
 /* ISTAT/IMASK event bits */
 #define MII_TG3_INT_LINKCHG0x0002
 #define MII_TG3_INT_SPEEDCHG   0x0004


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/13] tg3: 5784 / 5764 DMA engine lockup fix

2007-11-09 Thread Matt Carlson
5784 and 5764 devices lock up when the link speed is 10Mbps, the CPMU
link speed mode is enabled, and the MAC clock is running at 1.5Mhz.  The
fix is to run the MAC clock at faster speeds.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 833cb9b..b865c5d 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -6369,6 +6369,21 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
val = tr32(TG3_CPMU_CTRL);
val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
tw32(TG3_CPMU_CTRL, val);
+
+   val = tr32(TG3_CPMU_LSPD_10MB_CLK);
+   val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
+   val |= CPMU_LSPD_10MB_MACCLK_6_25;
+   tw32(TG3_CPMU_LSPD_10MB_CLK, val);
+
+   val = tr32(TG3_CPMU_LNK_AWARE_PWRMD);
+   val &= ~CPMU_LNK_AWARE_MACCLK_MASK;
+   val |= CPMU_LNK_AWARE_MACCLK_6_25;
+   tw32(TG3_CPMU_LNK_AWARE_PWRMD, val);
+
+   val = tr32(TG3_CPMU_HST_ACC);
+   val &= ~CPMU_HST_ACC_MACCLK_MASK;
+   val |= CPMU_HST_ACC_MACCLK_6_25;
+   tw32(TG3_CPMU_HST_ACC, val);
}
 
/* This works around an issue with Athlon chipsets on
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 4659697..c6aad49 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -857,13 +857,24 @@
 #define  CPMU_CTRL_LINK_IDLE_MODE   0x0200
 #define  CPMU_CTRL_LINK_AWARE_MODE  0x0400
 #define  CPMU_CTRL_LINK_SPEED_MODE  0x4000
-/* 0x3604 --> 0x360c unused */
+#define TG3_CPMU_LSPD_10MB_CLK 0x3604
+#define  CPMU_LSPD_10MB_MACCLK_MASK 0x001f
+#define  CPMU_LSPD_10MB_MACCLK_6_25 0x0013
+/* 0x3608 --> 0x360c unused */
 
 #define TG3_CPMU_LSPD_1000MB_CLK   0x360c
 #define  CPMU_LSPD_1000MB_MACCLK_62_5   0x
 #define  CPMU_LSPD_1000MB_MACCLK_12_5   0x0011
 #define  CPMU_LSPD_1000MB_MACCLK_MASK   0x001f
-/* 0x3610 --> 0x365c unused */
+#define TG3_CPMU_LNK_AWARE_PWRMD   0x3610
+#define  CPMU_LNK_AWARE_MACCLK_MASK 0x001f
+#define  CPMU_LNK_AWARE_MACCLK_6_25 0x0013
+/* 0x3614 --> 0x361c unused */
+
+#define TG3_CPMU_HST_ACC   0x361c
+#define  CPMU_HST_ACC_MACCLK_MASK   0x001f
+#define  CPMU_HST_ACC_MACCLK_6_25   0x0013
+/* 0x3620 --> 0x365c unused */
 
 #define TG3_CPMU_MUTEX_REQ 0x365c
 #define  CPMU_MUTEX_REQ_DRIVER  0x1000


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/13] tg3: Fix 5761 PXEboot crash

2007-11-09 Thread Matt Carlson
When 5761 devices boot the machine using PXEboot, PXE leaves the device
active when it terminates.  The tg3 driver has code to detect this
condition and resets the device during initialization.  On 5761 devices,
device resets involve sending a driver state update message to the APE
on the 5761.  However, during this initialization stage, communications
to the APE registers have not yet been set up.  The driver then
dereferences a NULL pointer and crashes the machine.  The fix is to move
the APE register access setup earlier in the initialization code to
cover this condition.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index cad5199..ddeaa0c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -12464,6 +12464,28 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_iounmap;
}
 
+   if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
+   if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
+   printk(KERN_ERR PFX "Cannot find proper PCI device "
+  "base address for APE, aborting.\n");
+   err = -ENODEV;
+   goto err_out_iounmap;
+   }
+
+   tg3reg_base = pci_resource_start(pdev, 2);
+   tg3reg_len = pci_resource_len(pdev, 2);
+
+   tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
+   if (tp->aperegs == 0UL) {
+   printk(KERN_ERR PFX "Cannot map APE registers, "
+  "aborting.\n");
+   err = -ENOMEM;
+   goto err_out_iounmap;
+   }
+
+   tg3_ape_lock_init(tp);
+   }
+
/*
 * Reset chip in case UNDI or EFI driver did not shutdown
 * DMA self test will enable WDMAC and we'll see (spurious)
@@ -12478,7 +12500,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
err = tg3_test_dma(tp);
if (err) {
printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
-   goto err_out_iounmap;
+   goto err_out_apeunmap;
}
 
/* Tigon3 can do ipv4 only... and some chips have buggy
@@ -12501,28 +12523,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
tg3_init_coal(tp);
 
-   if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
-   if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
-   printk(KERN_ERR PFX "Cannot find proper PCI device "
-  "base address for APE, aborting.\n");
-   err = -ENODEV;
-   goto err_out_iounmap;
-   }
-
-   tg3reg_base = pci_resource_start(pdev, 2);
-   tg3reg_len = pci_resource_len(pdev, 2);
-
-   tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
-   if (tp->aperegs == 0UL) {
-   printk(KERN_ERR PFX "Cannot map APE registers, "
-  "aborting.\n");
-   err = -ENOMEM;
-   goto err_out_iounmap;
-   }
-
-   tg3_ape_lock_init(tp);
-   }
-
pci_set_drvdata(pdev, dev);
 
err = register_netdev(dev);


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/13] tg3: CPMU adjustments for loopback tests

2007-11-09 Thread Matt Carlson
This patch adds the LINK_SPEED mode to the list of CPMU modes that can
cause the loopback tests to fail.  These bugs are planned to be fixed in
future revisions of the chip, so the patch qualifies the fixes as such.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ef849b1..25e57d8 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -9354,7 +9354,8 @@ static int tg3_test_loopback(struct tg3 *tp)
if (err)
return TG3_LOOPBACK_FAILED;
 
-   if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
int i;
u32 status;
 
@@ -9371,17 +9372,18 @@ static int tg3_test_loopback(struct tg3 *tp)
if (status != CPMU_MUTEX_GNT_DRIVER)
return TG3_LOOPBACK_FAILED;
 
-   cpmuctrl = tr32(TG3_CPMU_CTRL);
-
/* Turn off power management based on link speed. */
+   cpmuctrl = tr32(TG3_CPMU_CTRL);
tw32(TG3_CPMU_CTRL,
-cpmuctrl & ~CPMU_CTRL_LINK_SPEED_MODE);
+cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
+ CPMU_CTRL_LINK_AWARE_MODE));
}
 
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
 
-   if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
tw32(TG3_CPMU_CTRL, cpmuctrl);
 
/* Release the mutex */


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/13] tg3: 5784 / 5764 GPHY power down fix

2007-11-09 Thread Matt Carlson
5784 and 5764 devices fail to link / pass traffic after one load /
unload cycle.  This happens because of a hardware bug in the new CPMU.
During normal operation, the MAC depends on the PHY clock being
available.  When the PHY is powered down, the clock the MAC depends on
is disabled.  The fix is to switch the MAC clock to an alternate source
before powering down the PHY, and to restore the MAC clock to the PHY
source upon device resume.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ddeaa0c..82b1cf0 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1106,6 +1106,19 @@ static int tg3_phy_reset(struct tg3 *tp)
if (err)
return err;
 
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
+   u32 val;
+
+   val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+   if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
+   CPMU_LSPD_1000MB_MACCLK_12_5) {
+   val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+   udelay(40);
+   tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+   }
+   }
+
 out:
if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
@@ -1297,6 +1310,8 @@ static void tg3_nvram_unlock(struct tg3 *);
 
 static void tg3_power_down_phy(struct tg3 *tp)
 {
+   u32 val;
+
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
@@ -1311,8 +1326,6 @@ static void tg3_power_down_phy(struct tg3 *tp)
}
 
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
-   u32 val;
-
tg3_bmcr_reset(tp);
val = tr32(GRC_MISC_CFG);
tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
@@ -1332,6 +1345,15 @@ static void tg3_power_down_phy(struct tg3 *tp)
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
 (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
return;
+
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+   tp->pci_chip_rev_id == CHIPREV_ID_5761_A0) {
+   val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+   val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+   val |= CPMU_LSPD_1000MB_MACCLK_12_5;
+   tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+   }
+
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
 }
 
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 1d5b2a3..4659697 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -109,6 +109,7 @@
 #define  CHIPREV_ID_5714_A2 0x9002
 #define  CHIPREV_ID_5906_A1 0xc001
 #define  CHIPREV_ID_5784_A0 0x5784000
+#define  CHIPREV_ID_5761_A0 0x5761000
 #define  GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700 0x07
 #define   ASIC_REV_5701 0x00
@@ -856,7 +857,13 @@
 #define  CPMU_CTRL_LINK_IDLE_MODE   0x0200
 #define  CPMU_CTRL_LINK_AWARE_MODE  0x0400
 #define  CPMU_CTRL_LINK_SPEED_MODE  0x4000
-/* 0x3604 --> 0x365c unused */
+/* 0x3604 --> 0x360c unused */
+
+#define TG3_CPMU_LSPD_1000MB_CLK   0x360c
+#define  CPMU_LSPD_1000MB_MACCLK_62_5   0x
+#define  CPMU_LSPD_1000MB_MACCLK_12_5   0x0011
+#define  CPMU_LSPD_1000MB_MACCLK_MASK   0x001f
+/* 0x3610 --> 0x365c unused */
 
 #define TG3_CPMU_MUTEX_REQ 0x365c
 #define  CPMU_MUTEX_REQ_DRIVER  0x1000


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/13] tg3: Fix nvram selftest failures

2007-11-09 Thread Matt Carlson
Newer devices contain bootcode in the chip's private ROM area.  This
bootcode is called selfboot.  Selfboot can be patched in the device's
NVRAM and the patches can have several formats.  In one particular
format, the checksum calculation needs to be slightly modified.  This
patch adjusts the NVRAM test code for that case, and add support for the
missing formats.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b865c5d..ef849b1 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -8701,7 +8701,9 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
 }
 
 #define NVRAM_TEST_SIZE 0x100
-#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_0_SIZE  0x14
+#define NVRAM_SELFBOOT_FORMAT1_2_SIZE  0x18
+#define NVRAM_SELFBOOT_FORMAT1_3_SIZE  0x1c
 #define NVRAM_SELFBOOT_HW_SIZE 0x20
 #define NVRAM_SELFBOOT_DATA_SIZE 0x1c
 
@@ -8716,9 +8718,22 @@ static int tg3_test_nvram(struct tg3 *tp)
if (magic == TG3_EEPROM_MAGIC)
size = NVRAM_TEST_SIZE;
else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
-   if ((magic & 0xe0) == 0x20)
-   size = NVRAM_SELFBOOT_FORMAT1_SIZE;
-   else
+   if ((magic & TG3_EEPROM_SB_FORMAT_MASK) ==
+   TG3_EEPROM_SB_FORMAT_1) {
+   switch (magic & TG3_EEPROM_SB_REVISION_MASK) {
+   case TG3_EEPROM_SB_REVISION_0:
+   size = NVRAM_SELFBOOT_FORMAT1_0_SIZE;
+   break;
+   case TG3_EEPROM_SB_REVISION_2:
+   size = NVRAM_SELFBOOT_FORMAT1_2_SIZE;
+   break;
+   case TG3_EEPROM_SB_REVISION_3:
+   size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
+   break;
+   default:
+   return 0;
+   }
+   } else
return 0;
} else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
size = NVRAM_SELFBOOT_HW_SIZE;
@@ -8745,8 +8760,17 @@ static int tg3_test_nvram(struct tg3 *tp)
TG3_EEPROM_MAGIC_FW) {
u8 *buf8 = (u8 *) buf, csum8 = 0;
 
-   for (i = 0; i < size; i++)
-   csum8 += buf8[i];
+   if ((cpu_to_be32(buf[0]) & TG3_EEPROM_SB_REVISION_MASK) ==
+   TG3_EEPROM_SB_REVISION_2) {
+   /* For rev 2, the csum doesn't include the MBA. */
+   for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++)
+   csum8 += buf8[i];
+   for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++)
+   csum8 += buf8[i];
+   } else {
+   for (i = 0; i < size; i++)
+   csum8 += buf8[i];
+   }
 
if (csum8 == 0) {
err = 0;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index c6aad49..f715b35 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1555,6 +1555,12 @@
 #define TG3_EEPROM_MAGIC   0x669955aa
 #define TG3_EEPROM_MAGIC_FW0xa500
 #define TG3_EEPROM_MAGIC_FW_MSK0xff00
+#define TG3_EEPROM_SB_FORMAT_MASK  0x00e0
+#define TG3_EEPROM_SB_FORMAT_1 0x0020
+#define TG3_EEPROM_SB_REVISION_MASK0x001f
+#define TG3_EEPROM_SB_REVISION_0   0x
+#define TG3_EEPROM_SB_REVISION_2   0x0002
+#define TG3_EEPROM_SB_REVISION_3   0x0003
 #define TG3_EEPROM_MAGIC_HW0xabcd
 #define TG3_EEPROM_MAGIC_HW_MSK0x
 
@@ -1765,6 +1771,8 @@
 /* APE convenience enumerations. */
 #define TG3_APE_LOCK_MEM4
 
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+
 
 /* There are two ways to manage the TX descriptors on the tigon3.
  * Either the descriptors are in host DMA'able memory, or they


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 9/13] tg3: Prescaler fix

2007-11-09 Thread Matt Carlson
Internal hardware timers become inaccurate after link events.  Clock
frequency switches performed by the CPMU fail to adjust timer
prescalers.  The fix is to detect core clock frequency changes during
link events and adjust the timer prescalers accordingly.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index bb3b734..ecd64a2 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3154,6 +3154,22 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
err = tg3_setup_copper_phy(tp, force_reset);
}
 
+   if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+   u32 val, scale;
+
+   val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
+   if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5)
+   scale = 65;
+   else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25)
+   scale = 6;
+   else
+   scale = 12;
+
+   val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK;
+   val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT);
+   tw32(GRC_MISC_CFG, val);
+   }
+
if (tp->link_config.active_speed == SPEED_1000 &&
tp->link_config.active_duplex == DUPLEX_HALF)
tw32(MAC_TX_LENGTHS,
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 5b799ff..d325ab5 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -874,7 +874,14 @@
 #define TG3_CPMU_HST_ACC   0x361c
 #define  CPMU_HST_ACC_MACCLK_MASK   0x001f
 #define  CPMU_HST_ACC_MACCLK_6_25   0x0013
-/* 0x3620 --> 0x365c unused */
+/* 0x3620 --> 0x3630 unused */
+
+#define TG3_CPMU_CLCK_STAT 0x3630
+#define  CPMU_CLCK_STAT_MAC_CLCK_MASK   0x001f
+#define  CPMU_CLCK_STAT_MAC_CLCK_62_5   0x
+#define  CPMU_CLCK_STAT_MAC_CLCK_12_5   0x0011
+#define  CPMU_CLCK_STAT_MAC_CLCK_6_25   0x0013
+/* 0x3634 --> 0x365c unused */
 
 #define TG3_CPMU_MUTEX_REQ 0x365c
 #define  CPMU_MUTEX_REQ_DRIVER  0x1000




-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/13] tg3: 5761, 5784, and 5764 support fixes

2007-11-09 Thread Matt Carlson
The following patches round out support for 5784, 5764, and 5761
devices, fixing bugs in the process.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 10/13] tg3: Increase the PCI MRRS

2007-11-15 Thread Matt Carlson
On Mon, 2007-11-12 at 21:21 -0800, David Miller wrote:
> From: "Matt Carlson" <[EMAIL PROTECTED]>
> Date: Fri, 09 Nov 2007 16:39:01 -0800
> 
> > Previous devices hardcoded the PCI Maximum Read Request Size to 4K.  To
> > better comply with the PCI spec, the hardware now defaults the MRRS to
> > 512 bytes.  This will yield poor driver performance if left untouched.
> > This patch increases the MRRS to 4K on driver initialization.
> > 
> > Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
> > Signed-off-by: Michael Chan <[EMAIL PROTECTED]>
> 
> I've applied this patch, but...
> 
> I sense that the PCI spec wants devices to use an MRRS value of 512 in
> order to get better fairness on a PCI-E segment amongst multiple
> devices.
> 
> From that perspective, jacking up the MRRS to 4096 unilaterally seems
> like a very bad idea.  If this was necessary for good performance, I'm
> sure the PCI spec folks would have choosen a higher value.
> 
> Or is this some tg3 specific performance issue?

Keeping the MRRS at 512 introduces DMA latencies that effectively
prevent us from achieving linerate.  With a packet size of ~1.5K and the
MRRS at 512 bytes, the DMA will be broken into at least 3 DMA reads.
Each DMA read takes ~1usec to initiate.  It is this overhead that starts
to cut into total throughput.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [WIP][PATCHES] Network xmit batching - tg3 support

2007-07-02 Thread Matt Carlson
On Wed, 2007-06-27 at 20:05 -0400, jamal wrote:
> peoplez,
> 
> I have added support for tg3 on batching. I see equivalent performance
> improvement for pktgen as i did with e1000 when using gige. 
> I have only tested on two machines (one being a laptop which does
> 10/100Mbps). Unfortunately in both cases these are considered to be in
> the class of  "buggy" tg3s (which take a longer code path).
> 
> To the tg3 folks - can you double check if am off on something?
> I have split a few things that you may like as well.
> I havent upgraded the tree - it is still circa 2.6.22-rc4 based; at some
> point i will sync with Daves net-26
> 
> Anyone who has tg3 based hardware: I would appreciate any testing and
> results ...
> 
> The git tree is at:
> git://git.kernel.org/pub/scm/linux/kernel/git/hadi/batch-lin26.git
> but i have attached the patch in case you just wanna stare.
> 
> cheers,
> jamal

Hi Jamal.  I'll be testing your patch soon, but I wanted to point out a
bug in the patch.  The patch defines TG3_SKB_CB() as follows :

#define TG3_SKB_CB(__skb) ((struct tg3_tx_cbdata *)&((__skb)->cb[0]))

This definition will collide with the VLAN macros if TG3_VLAN_TAG_USED
is set.  vlan_tx_tag_get() is defined as :

#define vlan_tx_tag_get(__skb)  (VLAN_TX_SKB_CB(__skb)->vlan_tag)

VLAN_TX_SKB_CB is defined as :

#define VLAN_TX_SKB_CB(__skb) \
((struct vlan_skb_tx_cookie *)&((__skb)->cb[0]))

Also, I think the count, max_per_txd, and nr_frags fields of the
tg3_tx_cbdata struct are not needed.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [WIP][PATCHES] Network xmit batching - tg3 support

2007-07-03 Thread Matt Carlson
On Tue, 2007-07-03 at 09:09 -0400, jamal wrote:
> On Mon, 2007-02-07 at 14:20 -0700, Matt Carlson wrote:
> 
> 
> > 
> > Hi Jamal.  I'll be testing your patch soon,
> 
> much thanks. Please let me know if you need help while doing this.
> What tools are you planning to test with? I have tested this patch
> with pktgen on a dual opteron/tg3-buggy. 
> There is an outstanding issue in regards to clocksource - however the
> batch does well regardless of the clock source.

I had planned on using netperf, but pktgen sounds like a more controlled
environment.  Thanks for the tip.

> >  but I wanted to point out a
> > bug in the patch.  The patch defines TG3_SKB_CB() as follows :
> > 
> > #define TG3_SKB_CB(__skb) ((struct tg3_tx_cbdata *)&((__skb)->cb[0]))
> > 
> > This definition will collide with the VLAN macros if TG3_VLAN_TAG_USED
> > is set.  vlan_tx_tag_get() is defined as :
> > 
> > #define vlan_tx_tag_get(__skb)  (VLAN_TX_SKB_CB(__skb)->vlan_tag)
> > 
> > VLAN_TX_SKB_CB is defined as :
> > 
> > #define VLAN_TX_SKB_CB(__skb) \
> > ((struct vlan_skb_tx_cookie *)&((__skb)->cb[0]))
> > 
> 
> yikes. Thanks for catching that - I thought i had this pretty much
> covered after scanning the source. So that bug exists on the e1000 as
> well.
> [It sounds very dangerous to me the way skb->cb is being used by the
> vlan code (i.e requires human intervention/knowledge to catch it as an
> issue). I had no freaking idea the vlan code was using it. Maybe a huge
> comment somewhere on how these cbs are being used by drivers would help
> or even a registration on startup to just make sure there is no conflict
> at a layer (i have been meaning to do the later for years now). In any
> case this is is a digression]. 
> 
> In the meantime, changing it to use byte 8 and above should do it? i.e.
> #define TG3_SKB_CB(__skb) ((struct tg3_tx_cbdata *)&((__skb)->cb[8]))
> 
> There are 48 bytes there on the skb-cb, so there should be plenty.

Do you see any reason why we couldn't just add the VLAN code to the prep
stage and simply overwrite that portion of the skb-cb?  Our driver would
just store its value in the base_flags member of tg3_tx_cbdata.

> > Also, I think the count, max_per_txd, and nr_frags fields of the
> > tg3_tx_cbdata struct are not needed.
> 
> Yes, you are right. That was a result of the LinuxWay(tm) (aka cutnpaste
> from the e1000 which needs them), Can you send me a patch for that and
> TG3_SKB_CB? 

Once we iron out the skb-cb issue, sure.

> 
> cheers,
> jamal
> 
> 

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] tg3: Fix VLAN tag corruption

2007-07-05 Thread Matt Carlson
This patch fixes a VLAN tag corruption bug introduced in the tx batching
modifications.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index be03cbd..cef9cbe 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3896,8 +3896,15 @@ struct tg3_tx_cbdata {
 static int tg3_prep_bug_frame(struct sk_buff *skb, struct net_device *dev)
 {
struct tg3_tx_cbdata *cb = TG3_SKB_CB(skb);
+   struct tg3 *tp = netdev_priv(dev);
+   u32 vlantag = 0;
+
+#if TG3_VLAN_TAG_USED
+   if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
+   vlantag = (TXD_FLAG_VLAN | (vlan_tx_tag_get(skb) << 16));
+#endif
 
-   cb->base_flags = 0;
+   cb->base_flags = vlantag;
cb->mss = skb_shinfo(skb)->gso_size;
if (cb->mss != 0) {
if (skb_header_cloned(skb) &&
@@ -3919,8 +3926,15 @@ static int tg3_prep_bug_frame(struct sk_buff *skb, 
struct net_device *dev)
 static int tg3_prep_frame(struct sk_buff *skb, struct net_device *dev)
 {
struct tg3_tx_cbdata *cb = TG3_SKB_CB(skb);
+   struct tg3 *tp = netdev_priv(dev);
+   u32 vlantag = 0;
+
+#if TG3_VLAN_TAG_USED
+   if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
+   vlantag = (TXD_FLAG_VLAN | (vlan_tx_tag_get(skb) << 16));
+#endif
 
-   cb->base_flags = 0;
+   cb->base_flags = vlantag;
cb->mss = skb_shinfo(skb)->gso_size;
if (cb->mss != 0) {
int tcp_opt_len, ip_tcp_len;
@@ -3985,13 +3999,6 @@ static int tg3_enqueue(struct sk_buff *skb, struct 
net_device *dev)
u32 len, entry;
struct tg3_tx_cbdata *cb = TG3_SKB_CB(skb);
 
-
-#if TG3_VLAN_TAG_USED
-   if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
-   cb->base_flags |= (TXD_FLAG_VLAN |
-  (vlan_tx_tag_get(skb) << 16));
-#endif
-
entry = tp->tx_prod;
len = skb_headlen(skb);
/* Queue skb data, a.k.a. the main skb fragment. */
@@ -4187,11 +4194,6 @@ static int tg3_enqueue_buggy(struct sk_buff *skb, struct 
net_device *dev)
}
}
}
-#if TG3_VLAN_TAG_USED
-   if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
-   cb->base_flags |= (TXD_FLAG_VLAN |
-  (vlan_tx_tag_get(skb) << 16));
-#endif
len = skb_headlen(skb);
entry = tp->tx_prod;
 


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] tg3: Tx availability fix

2007-07-05 Thread Matt Carlson
This patch changes how and to what value the xmit_win variable is
assigned.

The patch starts by correcting the initialization of xmit_win to be 1/4
the value of tx_pending rather than the tx ring size.  The tx_pending
value is initialized to be the tx ring size, but it may be changed
through ethtool.

The patch then reverts the code back to the old logic when deciding
whether or not to wake up the transmit queue.  The new tx batching
implementation had changed this code so that the tg3_tx_avail() function
was only called once and the value returned stored in a local variable.
While the new code looks slightly cleaner, there is the possibility that
more descriptors will become available in-between the time of the call
and the time the value gets used.  Reverting back to the old logic will
ensure that the driver always acts on current information.

The last change makes sure that new xmit_win values, as assigned by the
transmit queue wake code, will not be drastically larger than the value
set during initialization.

As a bonus, this patch removes the unused struct tg3_tx_cbdata members.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index cef9cbe..afa617a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -581,7 +581,7 @@ static inline void tg3_netif_stop(struct tg3 *tp)
 static inline void tg3_netif_start(struct tg3 *tp)
 {
netif_wake_queue(tp->dev);
-   tp->dev->xmit_win = TG3_TX_RING_SIZE >> 2;
+   tp->dev->xmit_win = tp->tx_pending >> 2;
/* NOTE: unconditional netif_wake_queue is only appropriate
 * so long as all callers are assured to have free tx slots
 * (such as after tg3_init_hw)
@@ -3120,15 +3120,14 @@ static void tg3_tx(struct tg3 *tp)
 */
smp_mb();
 
-   dcount = tg3_tx_avail(tp);
if (unlikely(netif_queue_stopped(tp->dev) &&
-(dcount > TG3_TX_WAKEUP_THRESH(tp {
+(tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp {
netif_tx_lock(tp->dev);
tp->dev->xmit_win = 1;
if (netif_queue_stopped(tp->dev) &&
-   (dcount > TG3_TX_WAKEUP_THRESH(tp))) {
+   (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))) {
netif_wake_queue(tp->dev);
-   tp->dev->xmit_win = dcount;
+   tp->dev->xmit_win = tg3_tx_avail(tp) >> 2;
}
netif_tx_unlock(tp->dev);
}
@@ -3885,9 +3884,6 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
 
 struct tg3_tx_cbdata {
u32 base_flags;
-   int count;
-   unsigned int max_per_txd;
-   unsigned int nr_frags;
unsigned int mss;
 };
 #define TG3_SKB_CB(__skb)   ((struct tg3_tx_cbdata *)&((__skb)->cb[0]))
@@ -3974,16 +3970,16 @@ static int tg3_prep_frame(struct sk_buff *skb, struct 
net_device *dev)
 void tg3_kick_DMA(struct tg3 *tp)
 {
u32 entry = tp->tx_prod;
-   u32 count = tg3_tx_avail(tp);
+
/* Packets are ready, update Tx producer idx local and on card. */
tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
-   if (unlikely(count <= (MAX_SKB_FRAGS + 1))) {
+   if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(tp->dev);
tp->dev->xmit_win = 1;
-   if (count > TG3_TX_WAKEUP_THRESH(tp)) {
+   if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) {
netif_wake_queue(tp->dev);
-   tp->dev->xmit_win = count;
+   tp->dev->xmit_win = tg3_tx_avail(tp) >> 2;
}
}
 
@@ -11965,7 +11961,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
dev->change_mtu = tg3_change_mtu;
dev->irq = pdev->irq;
dev->features |= NETIF_F_BTX;
-   dev->xmit_win = TG3_TX_RING_SIZE >> 2;
+   dev->xmit_win = tp->tx_pending >> 2;
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = tg3_poll_controller;


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] tg3: Tx availability fix

2007-07-05 Thread Matt Carlson
Ugh.  Please disregard the previous version and use this one instead.
The original patch had a compiler warning.



This patch changes how and to what value the xmit_win variable is
assigned.

The patch starts by correcting the initialization of xmit_win to be 1/4
the value of tx_pending rather than the tx ring size.  The tx_pending
value is initialized to be the tx ring size, but it may be changed
through ethtool.

The patch then reverts the code back to the old logic when deciding
whether or not to wake up the transmit queue.  The new tx batching
implementation had changed this code so that the tg3_tx_avail() function
was only called once and the value returned stored in a local variable.
While the new code looks slightly cleaner, there is the possibility that
more descriptors will become available in-between the time of the call
and the time the value gets used.  Reverting back to the old logic will
ensure that the driver always acts on current information.

The last change makes sure that new xmit_win values, as assigned by the
transmit queue wake code, will not be drastically larger than the value
set during initialization.

As a bonus, this patch removes the unused struct tg3_tx_cbdata members.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index cef9cbe..d5d9b82 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -581,7 +581,7 @@ static inline void tg3_netif_stop(struct tg3 *tp)
 static inline void tg3_netif_start(struct tg3 *tp)
 {
netif_wake_queue(tp->dev);
-   tp->dev->xmit_win = TG3_TX_RING_SIZE >> 2;
+   tp->dev->xmit_win = tp->tx_pending >> 2;
/* NOTE: unconditional netif_wake_queue is only appropriate
 * so long as all callers are assured to have free tx slots
 * (such as after tg3_init_hw)
@@ -3067,7 +3067,6 @@ static inline u32 tg3_tx_avail(struct tg3 *tp)
  */
 static void tg3_tx(struct tg3 *tp)
 {
-   int dcount;
u32 hw_idx = tp->hw_status->idx[0].tx_consumer;
u32 sw_idx = tp->tx_cons;
 
@@ -3120,15 +3119,14 @@ static void tg3_tx(struct tg3 *tp)
 */
smp_mb();
 
-   dcount = tg3_tx_avail(tp);
if (unlikely(netif_queue_stopped(tp->dev) &&
-(dcount > TG3_TX_WAKEUP_THRESH(tp {
+(tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp {
netif_tx_lock(tp->dev);
tp->dev->xmit_win = 1;
if (netif_queue_stopped(tp->dev) &&
-   (dcount > TG3_TX_WAKEUP_THRESH(tp))) {
+   (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))) {
netif_wake_queue(tp->dev);
-   tp->dev->xmit_win = dcount;
+   tp->dev->xmit_win = tg3_tx_avail(tp) >> 2;
}
netif_tx_unlock(tp->dev);
}
@@ -3885,9 +3883,6 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
 
 struct tg3_tx_cbdata {
u32 base_flags;
-   int count;
-   unsigned int max_per_txd;
-   unsigned int nr_frags;
unsigned int mss;
 };
 #define TG3_SKB_CB(__skb)   ((struct tg3_tx_cbdata *)&((__skb)->cb[0]))
@@ -3974,16 +3969,16 @@ static int tg3_prep_frame(struct sk_buff *skb, struct 
net_device *dev)
 void tg3_kick_DMA(struct tg3 *tp)
 {
u32 entry = tp->tx_prod;
-   u32 count = tg3_tx_avail(tp);
+
/* Packets are ready, update Tx producer idx local and on card. */
tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
-   if (unlikely(count <= (MAX_SKB_FRAGS + 1))) {
+   if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(tp->dev);
tp->dev->xmit_win = 1;
-   if (count > TG3_TX_WAKEUP_THRESH(tp)) {
+   if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) {
netif_wake_queue(tp->dev);
-   tp->dev->xmit_win = count;
+   tp->dev->xmit_win = tg3_tx_avail(tp) >> 2;
}
}
 
@@ -11965,7 +11960,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
dev->change_mtu = tg3_change_mtu;
dev->irq = pdev->irq;
dev->features |= NETIF_F_BTX;
-   dev->xmit_win = TG3_TX_RING_SIZE >> 2;
+   dev->xmit_win = tp->tx_pending >> 2;
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = tg3_poll_controller;


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/8] tg3: Flow Control Modifications

2007-12-20 Thread Matt Carlson
This patchset modifies the driver to accept changes in flow control
settings via ethtool.

-- 

Matt Carlson 5300 California Ave
Senior Software EngineerIrvine, CA 92617
Broadcom  (949) 926-6341


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/8] tg3: Separate requested and actual flow control parameters

2007-12-20 Thread Matt Carlson
This patch removes the TX and RX flow control flags from tg3_flags and
adds two new flow control variables, flowctrl and active_flowctrl.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 4942f7d..d503214 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1602,17 +1602,19 @@ static void tg3_link_report(struct tg3 *tp)
   (tp->link_config.active_duplex == DUPLEX_FULL ?
"full" : "half"));
 
-   printk(KERN_INFO PFX "%s: Flow control is %s for TX and "
-  "%s for RX.\n",
+   printk(KERN_INFO PFX
+  "%s: Flow control is %s for TX and %s for RX.\n",
   tp->dev->name,
-  (tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "on" : "off",
-  (tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "on" : "off");
+  (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ?
+  "on" : "off",
+  (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ?
+  "on" : "off");
}
 }
 
 static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 
remote_adv)
 {
-   u32 new_tg3_flags = 0;
+   u8 new_tg3_flags = 0;
u32 old_rx_mode = tp->rx_mode;
u32 old_tx_mode = tp->tx_mode;
 
@@ -1639,31 +1641,27 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 
local_adv, u32 remote_adv
if (local_adv & ADVERTISE_PAUSE_CAP) {
if (local_adv & ADVERTISE_PAUSE_ASYM) {
if (remote_adv & LPA_PAUSE_CAP)
-   new_tg3_flags |=
-   (TG3_FLAG_RX_PAUSE |
-   TG3_FLAG_TX_PAUSE);
+   new_tg3_flags = TG3_FLOW_CTRL_RX |
+   TG3_FLOW_CTRL_TX;
else if (remote_adv & LPA_PAUSE_ASYM)
-   new_tg3_flags |=
-   (TG3_FLAG_RX_PAUSE);
+   new_tg3_flags = TG3_FLOW_CTRL_RX;
} else {
if (remote_adv & LPA_PAUSE_CAP)
-   new_tg3_flags |=
-   (TG3_FLAG_RX_PAUSE |
-   TG3_FLAG_TX_PAUSE);
+   new_tg3_flags = TG3_FLOW_CTRL_RX |
+   TG3_FLOW_CTRL_TX;
}
} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
if ((remote_adv & LPA_PAUSE_CAP) &&
-   (remote_adv & LPA_PAUSE_ASYM))
-   new_tg3_flags |= TG3_FLAG_TX_PAUSE;
+   (remote_adv & LPA_PAUSE_ASYM))
+   new_tg3_flags = TG3_FLOW_CTRL_TX;
}
-
-   tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
-   tp->tg3_flags |= new_tg3_flags;
} else {
-   new_tg3_flags = tp->tg3_flags;
+   new_tg3_flags = tp->link_config.flowctrl;
}
 
-   if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
+   tp->link_config.active_flowctrl = new_tg3_flags;
+
+   if (new_tg3_flags & TG3_FLOW_CTRL_RX)
tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
else
tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
@@ -1672,7 +1670,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 
local_adv, u32 remote_adv
tw32_f(MAC_RX_MODE, tp->rx_mode);
}
 
-   if (new_tg3_flags & TG3_FLAG_TX_PAUSE)
+   if (new_tg3_flags & TG3_FLOW_CTRL_TX)
tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
else
tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
@@ -2812,9 +2810,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int 
force_reset)
int current_link_up;
int i;
 
-   orig_pause_cfg =
-   (tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
- TG3_FLAG_TX_PAUSE));
+   orig_pause_cfg = tp->link_config.active_flowctrl;
orig_active_speed = tp->link_config.active_speed;
orig_active_duplex = tp->link_config.active_duplex;
 
@@ -2903,9 +2899,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int 
force_reset)
neti

[PATCH 2/8] tg3: Add 1000T & 1000X flowctrl resolvers

2007-12-20 Thread Matt Carlson
This patch adds two new utility functions to resolve flow control.  One
function resolves flow control based on 1000-BaseT register definitions.
The other resolves flow control based on 1000-Base X register
definitions.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index d503214..0cb0a6a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1612,6 +1612,50 @@ static void tg3_link_report(struct tg3 *tp)
}
 }
 
+static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv)
+{
+   u8 cap = 0;
+
+   if (lcladv & ADVERTISE_PAUSE_CAP) {
+   if (lcladv & ADVERTISE_PAUSE_ASYM) {
+   if (rmtadv & LPA_PAUSE_CAP)
+   cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+   else if (rmtadv & LPA_PAUSE_ASYM)
+   cap = TG3_FLOW_CTRL_RX;
+   } else {
+   if (rmtadv & LPA_PAUSE_CAP)
+   cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+   }
+   } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
+   if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
+   cap = TG3_FLOW_CTRL_TX;
+   }
+
+   return cap;
+}
+
+static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
+{
+   u8 cap = 0;
+
+   if (lcladv & ADVERTISE_1000XPAUSE) {
+   if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+   if (rmtadv & LPA_1000XPAUSE)
+   cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+   else if (rmtadv & LPA_1000XPAUSE_ASYM)
+   cap = TG3_FLOW_CTRL_RX;
+   } else {
+   if (rmtadv & LPA_1000XPAUSE)
+   cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+   }
+   } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+   if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
+   cap = TG3_FLOW_CTRL_TX;
+   }
+
+   return cap;
+}
+
 static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 
remote_adv)
 {
u8 new_tg3_flags = 0;
@@ -1619,42 +1663,12 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 
local_adv, u32 remote_adv
u32 old_tx_mode = tp->tx_mode;
 
if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
-
-   /* Convert 1000BaseX flow control bits to 1000BaseT
-* bits before resolving flow control.
-*/
-   if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
-   local_adv &= ~(ADVERTISE_PAUSE_CAP |
-  ADVERTISE_PAUSE_ASYM);
-   remote_adv &= ~(LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
-
-   if (local_adv & ADVERTISE_1000XPAUSE)
-   local_adv |= ADVERTISE_PAUSE_CAP;
-   if (local_adv & ADVERTISE_1000XPSE_ASYM)
-   local_adv |= ADVERTISE_PAUSE_ASYM;
-   if (remote_adv & LPA_1000XPAUSE)
-   remote_adv |= LPA_PAUSE_CAP;
-   if (remote_adv & LPA_1000XPAUSE_ASYM)
-   remote_adv |= LPA_PAUSE_ASYM;
-   }
-
-   if (local_adv & ADVERTISE_PAUSE_CAP) {
-   if (local_adv & ADVERTISE_PAUSE_ASYM) {
-   if (remote_adv & LPA_PAUSE_CAP)
-   new_tg3_flags = TG3_FLOW_CTRL_RX |
-   TG3_FLOW_CTRL_TX;
-   else if (remote_adv & LPA_PAUSE_ASYM)
-   new_tg3_flags = TG3_FLOW_CTRL_RX;
-   } else {
-   if (remote_adv & LPA_PAUSE_CAP)
-   new_tg3_flags = TG3_FLOW_CTRL_RX |
-   TG3_FLOW_CTRL_TX;
-   }
-   } else if (local_adv & ADVERTISE_PAUSE_ASYM) {
-   if ((remote_adv & LPA_PAUSE_CAP) &&
-   (remote_adv & LPA_PAUSE_ASYM))
-   new_tg3_flags = TG3_FLOW_CTRL_TX;
-   }
+   if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+   new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv,
+  remote_adv);
+   else
+   new_tg3_flags = tg3_resolve_flowctrl_1000T(local_adv,
+  remote_adv);
   

[PATCH 4/8] tg3: Replace some magic 5704S constants

2007-12-20 Thread Matt Carlson
This patch replaces magic values with preprocessor definitions for
the sg_dig_ctrl and sg_dig_status registers.  This is preparatory work
for the next patch.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 9e51457..9985166 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -2683,7 +2683,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 
mac_status)
sg_dig_ctrl = tr32(SG_DIG_CTRL);
 
if (tp->link_config.autoneg != AUTONEG_ENABLE) {
-   if (sg_dig_ctrl & (1 << 31)) {
+   if (sg_dig_ctrl & SG_DIG_USING_HW_AUTONEG) {
if (workaround) {
u32 val = serdes_cfg;
 
@@ -2693,7 +2693,8 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 
mac_status)
val |= 0x401;
tw32_f(MAC_SERDES_CFG, val);
}
-   tw32_f(SG_DIG_CTRL, 0x01388400);
+
+   tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
}
if (mac_status & MAC_STATUS_PCS_SYNCED) {
tg3_setup_flow_control(tp, 0, 0);
@@ -2703,13 +2704,13 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, 
u32 mac_status)
}
 
/* Want auto-negotiation.  */
-   expected_sg_dig_ctrl = 0x81388400;
+   expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP;
 
/* Pause capability */
-   expected_sg_dig_ctrl |= (1 << 11);
+   expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP;
 
/* Asymettric pause */
-   expected_sg_dig_ctrl |= (1 << 12);
+   expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE;
 
if (sg_dig_ctrl != expected_sg_dig_ctrl) {
if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) &&
@@ -2724,7 +2725,7 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 
mac_status)
 restart_autoneg:
if (workaround)
tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000);
-   tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
+   tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | SG_DIG_SOFT_RESET);
udelay(5);
tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
 
@@ -2735,22 +2736,22 @@ restart_autoneg:
sg_dig_status = tr32(SG_DIG_STATUS);
mac_status = tr32(MAC_STATUS);
 
-   if ((sg_dig_status & (1 << 1)) &&
+   if ((sg_dig_status & SG_DIG_AUTONEG_COMPLETE) &&
(mac_status & MAC_STATUS_PCS_SYNCED)) {
u32 local_adv, remote_adv;
 
local_adv = ADVERTISE_PAUSE_CAP;
remote_adv = 0;
-   if (sg_dig_status & (1 << 19))
+   if (sg_dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
remote_adv |= LPA_PAUSE_CAP;
-   if (sg_dig_status & (1 << 20))
+   if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
remote_adv |= LPA_PAUSE_ASYM;
 
tg3_setup_flow_control(tp, local_adv, remote_adv);
current_link_up = 1;
tp->serdes_counter = 0;
tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
-   } else if (!(sg_dig_status & (1 << 1))) {
+   } else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) {
if (tp->serdes_counter)
tp->serdes_counter--;
else {
@@ -2765,7 +2766,7 @@ restart_autoneg:
tw32_f(MAC_SERDES_CFG, val);
}
 
-   tw32_f(SG_DIG_CTRL, 0x01388400);
+   tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
udelay(40);
 
/* Link parallel detection - link is up */
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index ac47c17..3938eb3 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -545,6 +545,8 @@
 #define  SG_DIG_FIBER_MODE  0x8000
 #define  SG_DIG_REMOTE_FAULT_MASK   0x6000
 #define  SG_DIG_PAUSE_MASK  0x1800
+#define  SG_DIG_PAUSE_CAP   0x0800
+#define  SG_DIG_ASYM_PAUSE  0x1000
 #define  SG_DIG_GBIC_ENABLE 0x0400
 #define  SG_DIG_CHECK_END_ENABLE0x0200
 #define  SG_DIG_SGMII_AUTONEG_TIMER 0x0100
@@ -556,6 +558,11 @@
 #define  SG_DIG_AUTONEG_LOW_ENABLE  0x0004
 #define  SG_DIG_REMOTE_LOOPBACK 0x0002
 #defi

[PATCH 3/8] tg3: Add 1000T & 1000X flowctl adv helpers

2007-12-20 Thread Matt Carlson
This patch adds two functions designed to convert abstract TX & RX
flow control parameters to 1000-BaseT and 1000-BaseX autonegotiation
advertisements.  Code that uses standard definitions which statically
advertises TX & RX flow control has been replaced with code that
configures the advertisements based on administrator dictated
preferences.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 0cb0a6a..9e51457 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1612,6 +1612,38 @@ static void tg3_link_report(struct tg3 *tp)
}
 }
 
+static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
+{
+   u16 miireg;
+
+   if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
+   miireg = ADVERTISE_PAUSE_CAP;
+   else if (flow_ctrl & TG3_FLOW_CTRL_TX)
+   miireg = ADVERTISE_PAUSE_ASYM;
+   else if (flow_ctrl & TG3_FLOW_CTRL_RX)
+   miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+   else
+   miireg = 0;
+
+   return miireg;
+}
+
+static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
+{
+   u16 miireg;
+
+   if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
+   miireg = ADVERTISE_1000XPAUSE;
+   else if (flow_ctrl & TG3_FLOW_CTRL_TX)
+   miireg = ADVERTISE_1000XPSE_ASYM;
+   else if (flow_ctrl & TG3_FLOW_CTRL_RX)
+   miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+   else
+   miireg = 0;
+
+   return miireg;
+}
+
 static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv)
 {
u8 cap = 0;
@@ -1764,7 +1796,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
~(ADVERTISED_1000baseT_Half |
  ADVERTISED_1000baseT_Full);
 
-   new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+   new_adv = ADVERTISE_CSMA;
if (tp->link_config.advertising & ADVERTISED_10baseT_Half)
new_adv |= ADVERTISE_10HALF;
if (tp->link_config.advertising & ADVERTISED_10baseT_Full)
@@ -1773,6 +1805,9 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
new_adv |= ADVERTISE_100HALF;
if (tp->link_config.advertising & ADVERTISED_100baseT_Full)
new_adv |= ADVERTISE_100FULL;
+
+   new_adv |= tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+
tg3_writephy(tp, MII_ADVERTISE, new_adv);
 
if (tp->link_config.advertising &
@@ -1792,9 +1827,11 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
tg3_writephy(tp, MII_TG3_CTRL, 0);
}
} else {
+   new_adv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+   new_adv |= ADVERTISE_CSMA;
+
/* Asking for a specific link mode. */
if (tp->link_config.speed == SPEED_1000) {
-   new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
tg3_writephy(tp, MII_ADVERTISE, new_adv);
 
if (tp->link_config.duplex == DUPLEX_FULL)
@@ -1805,11 +1842,7 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
new_adv |= (MII_TG3_CTRL_AS_MASTER |
MII_TG3_CTRL_ENABLE_AS_MASTER);
-   tg3_writephy(tp, MII_TG3_CTRL, new_adv);
} else {
-   tg3_writephy(tp, MII_TG3_CTRL, 0);
-
-   new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
if (tp->link_config.speed == SPEED_100) {
if (tp->link_config.duplex == DUPLEX_FULL)
new_adv |= ADVERTISE_100FULL;
@@ -1822,7 +1855,11 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
new_adv |= ADVERTISE_10HALF;
}
tg3_writephy(tp, MII_ADVERTISE, new_adv);
+
+   new_adv = 0;
}
+
+   tg3_writephy(tp, MII_TG3_CTRL, new_adv);
}
 
if (tp->link_config.autoneg == AUTONEG_DISABLE &&
@@ -2118,17 +2155,15 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int 
force_reset)
 
if (tg3_readphy(tp, MII_ADVERTISE, &local_adv))
local_adv = 0;
-   local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
 
if (tg3_readphy(tp, MII_LPA, &remote_adv))
remote_adv = 0;
 
-   remote_adv &= (LPA_PAUSE_CAP | LPA_PA

[PATCH 7/8] tg3: Fix supporting flowctrl code

2007-12-20 Thread Matt Carlson
This patch does three things.  It modifies tg3_setup_flow_control() to
use the administrator requested flow control settings if
autonegotiation is turned off.  It slightly modifies the
tg3_setup_fiber_mii_phy() function to account for this new use case.
And finally, it does the same for tg3_setup_copper_phy().

The copper modifications are more than a small multi-line change.  The
new code makes an attempt to avoid a link renegotiation if the link is
active at half duplex and the only difference between the current
advertised settings and requested advertised settings is the
flow control advertisements.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 373642c..dd9229c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1694,7 +1694,8 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 
local_adv, u32 remote_adv
u32 old_rx_mode = tp->rx_mode;
u32 old_tx_mode = tp->tx_mode;
 
-   if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
+   if (tp->link_config.autoneg == AUTONEG_ENABLE &&
+   (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) {
if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv,
   remote_adv);
@@ -1975,10 +1976,44 @@ static int tg3_copper_is_advertising_all(struct tg3 
*tp, u32 mask)
return 1;
 }
 
+static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
+{
+   u32 curadv, reqadv;
+
+   if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
+   return 1;
+
+   curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+   reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+
+   if (tp->link_config.active_duplex == DUPLEX_FULL) {
+   if (curadv != reqadv)
+   return 0;
+
+   if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)
+   tg3_readphy(tp, MII_LPA, rmtadv);
+   } else {
+   /* Reprogram the advertisement register, even if it
+* does not affect the current link.  If the link
+* gets renegotiated in the future, we can save an
+* additional renegotiation cycle by advertising
+* it correctly in the first place.
+*/
+   if (curadv != reqadv) {
+   *lcladv &= ~(ADVERTISE_PAUSE_CAP |
+ADVERTISE_PAUSE_ASYM);
+   tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv);
+   }
+   }
+
+   return 1;
+}
+
 static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
int current_link_up;
u32 bmsr, dummy;
+   u32 lcl_adv, rmt_adv;
u16 current_speed;
u8 current_duplex;
int i, err;
@@ -2121,54 +2156,35 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int 
force_reset)
udelay(10);
}
 
-   if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-   if (bmcr & BMCR_ANENABLE) {
-   current_link_up = 1;
+   lcl_adv = 0;
+   rmt_adv = 0;
 
-   /* Force autoneg restart if we are exiting
-* low power mode.
-*/
-   if (!tg3_copper_is_advertising_all(tp,
-   tp->link_config.advertising))
-   current_link_up = 0;
-   } else {
-   current_link_up = 0;
+   tp->link_config.active_speed = current_speed;
+   tp->link_config.active_duplex = current_duplex;
+
+   if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+   if ((bmcr & BMCR_ANENABLE) &&
+   tg3_copper_is_advertising_all(tp,
+   tp->link_config.advertising)) {
+   if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv,
+ &rmt_adv))
+   current_link_up = 1;
}
} else {
if (!(bmcr & BMCR_ANENABLE) &&
tp->link_config.speed == current_speed &&
-   tp->link_config.duplex == current_duplex) {
+   tp->link_config.duplex == current_duplex &&
+   tp->link_config.flowctrl ==
+   tp->link_config.

[PATCH 5/8] tg3: Correct 5704S flowctrl advertisements

2007-12-20 Thread Matt Carlson
This patch modifies the 5704S hardware autoneg code to use the
administrator specified flow control parameters.  Since the 5704S uses
device specific flow control enumerations, the 1000-BaseX utility
functions are used and code was added to convert the definitions to and
from the proprietary enumerations.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 9985166..e30a99f 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1695,7 +1695,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 
local_adv, u32 remote_adv
u32 old_tx_mode = tp->tx_mode;
 
if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
-   if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+   if (tp->tg3_flags2 & (TG3_FLG2_MII_SERDES|TG3_FLG2_HW_AUTONEG))
new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv,
   remote_adv);
else
@@ -2658,6 +2658,7 @@ static void tg3_init_bcm8002(struct tg3 *tp)
 
 static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
 {
+   u16 flowctrl;
u32 sg_dig_ctrl, sg_dig_status;
u32 serdes_cfg, expected_sg_dig_ctrl;
int workaround, port_a;
@@ -2706,11 +2707,11 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, 
u32 mac_status)
/* Want auto-negotiation.  */
expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP;
 
-   /* Pause capability */
-   expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP;
-
-   /* Asymettric pause */
-   expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE;
+   flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
+   if (flowctrl & ADVERTISE_1000XPAUSE)
+   expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP;
+   if (flowctrl & ADVERTISE_1000XPSE_ASYM)
+   expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE;
 
if (sg_dig_ctrl != expected_sg_dig_ctrl) {
if ((tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) &&
@@ -2738,14 +2739,17 @@ restart_autoneg:
 
if ((sg_dig_status & SG_DIG_AUTONEG_COMPLETE) &&
(mac_status & MAC_STATUS_PCS_SYNCED)) {
-   u32 local_adv, remote_adv;
+   u32 local_adv = 0, remote_adv = 0;
+
+   if (sg_dig_ctrl & SG_DIG_PAUSE_CAP)
+   local_adv |= ADVERTISE_1000XPAUSE;
+   if (sg_dig_ctrl & SG_DIG_ASYM_PAUSE)
+   local_adv |= ADVERTISE_1000XPSE_ASYM;
 
-   local_adv = ADVERTISE_PAUSE_CAP;
-   remote_adv = 0;
if (sg_dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
-   remote_adv |= LPA_PAUSE_CAP;
+   remote_adv |= LPA_1000XPAUSE;
if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
-   remote_adv |= LPA_PAUSE_ASYM;
+   remote_adv |= LPA_1000XPAUSE_ASYM;
 
tg3_setup_flow_control(tp, local_adv, remote_adv);
current_link_up = 1;


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/8] tg3: Correct sw autoneg flow control advertisements

2007-12-20 Thread Matt Carlson
This patch modifies the software autoneg code to use the administrator
specified flow control parameters.  Since the autonegotiation code uses
alternative flow control enumerations, the 1000-BaseX utility functions
are used and code was added to convert the definitions to and from the
alternate enumerations.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index e30a99f..373642c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1695,7 +1695,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 
local_adv, u32 remote_adv
u32 old_tx_mode = tp->tx_mode;
 
if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
-   if (tp->tg3_flags2 & (TG3_FLG2_MII_SERDES|TG3_FLG2_HW_AUTONEG))
+   if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv,
   remote_adv);
else
@@ -2317,6 +2317,7 @@ struct tg3_fiber_aneginfo {
 static int tg3_fiber_aneg_smachine(struct tg3 *tp,
   struct tg3_fiber_aneginfo *ap)
 {
+   u16 flowctrl;
unsigned long delta;
u32 rx_cfg_reg;
int ret;
@@ -2416,7 +2417,12 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
 
case ANEG_STATE_ABILITY_DETECT_INIT:
ap->flags &= ~(MR_TOGGLE_TX);
-   ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
+   ap->txconfig = ANEG_CFG_FD;
+   flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
+   if (flowctrl & ADVERTISE_1000XPAUSE)
+   ap->txconfig |= ANEG_CFG_PS1;
+   if (flowctrl & ADVERTISE_1000XPSE_ASYM)
+   ap->txconfig |= ANEG_CFG_PS2;
tw32(MAC_TX_AUTO_NEG, ap->txconfig);
tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
tw32_f(MAC_MODE, tp->mac_mode);
@@ -2562,7 +2568,7 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
return ret;
 }
 
-static int fiber_autoneg(struct tg3 *tp, u32 *flags)
+static int fiber_autoneg(struct tg3 *tp, u32 *txflags, u32 *rxflags)
 {
int res = 0;
struct tg3_fiber_aneginfo aninfo;
@@ -2596,7 +2602,8 @@ static int fiber_autoneg(struct tg3 *tp, u32 *flags)
tw32_f(MAC_MODE, tp->mac_mode);
udelay(40);
 
-   *flags = aninfo.flags;
+   *txflags = aninfo.txconfig;
+   *rxflags = aninfo.flags;
 
if (status == ANEG_DONE &&
(aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
@@ -2806,18 +2813,21 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 
mac_status)
goto out;
 
if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-   u32 flags;
+   u32 txflags, rxflags;
int i;
 
-   if (fiber_autoneg(tp, &flags)) {
-   u32 local_adv, remote_adv;
+   if (fiber_autoneg(tp, &txflags, &rxflags)) {
+   u32 local_adv = 0, remote_adv = 0;
 
-   local_adv = ADVERTISE_PAUSE_CAP;
-   remote_adv = 0;
-   if (flags & MR_LP_ADV_SYM_PAUSE)
-   remote_adv |= LPA_PAUSE_CAP;
-   if (flags & MR_LP_ADV_ASYM_PAUSE)
-   remote_adv |= LPA_PAUSE_ASYM;
+   if (txflags & ANEG_CFG_PS1)
+   local_adv |= ADVERTISE_1000XPAUSE;
+   if (txflags & ANEG_CFG_PS2)
+   local_adv |= ADVERTISE_1000XPSE_ASYM;
+
+   if (rxflags & MR_LP_ADV_SYM_PAUSE)
+   remote_adv |= LPA_1000XPAUSE;
+   if (rxflags & MR_LP_ADV_ASYM_PAUSE)
+   remote_adv |= LPA_1000XPAUSE_ASYM;
 
tg3_setup_flow_control(tp, local_adv, remote_adv);
 
@@ -2841,6 +2851,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 
mac_status)
!(mac_status & MAC_STATUS_RCVD_CFG))
current_link_up = 1;
} else {
+   tg3_setup_flow_control(tp, 0, 0);
+
/* Forcing 1000FD link up. */
current_link_up = 1;
 


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/8] tg3: Update version to 3.87

2007-12-20 Thread Matt Carlson
This patch updates the version number to 3.87.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index dd9229c..6264454 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME"tg3"
 #define PFX DRV_MODULE_NAME": "
-#define DRV_MODULE_VERSION "3.86"
-#define DRV_MODULE_RELDATE "November 9, 2007"
+#define DRV_MODULE_VERSION "3.87"
+#define DRV_MODULE_RELDATE "December 20, 2007"
 
 #define TG3_DEF_MAC_MODE   0
 #define TG3_DEF_RX_MODE0


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/5] tg3: Add 5761 support

2007-10-10 Thread Matt Carlson
This patch adds rest of the miscellaneous code required to support the
5761.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 5b6c1b2..3af93b5 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -200,6 +200,8 @@ static struct pci_device_id tg3_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)},
+   {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
+   {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -5087,7 +5089,8 @@ static int tg3_chip_reset(struct tg3 *tp)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
tw32(GRC_FASTBOOT_PC, 0);
 
/*
@@ -6363,7 +6366,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
if (err)
return err;
 
-   if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784) {
+   if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
+   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
/* This value is determined during the probe time DMA
 * engine test, tg3_test_dma.
 */
@@ -6769,7 +6773,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
/* Enable host coalescing bug fix */
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ||
-   (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784))
+   (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) ||
+   (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761))
val |= (1 << 29);
 
tw32_f(WDMAC_MODE, val);
@@ -6797,7 +6802,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
-   tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+
+   if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+   tw32(SNDDATAC_MODE,
+SNDDATAC_MODE_ENABLE | SNDDATAC_MODE_CDELAY);
+   else
+   tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
+
tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
@@ -6824,7 +6835,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
udelay(100);
 
tp->rx_mode = RX_MODE_ENABLE;
-   if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+   if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
 
tw32_f(MAC_RX_MODE, tp->rx_mode);
@@ -8368,10 +8380,12 @@ static int tg3_set_tso(struct net_device *dev, u32 
value)
}
if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) {
-   if (value)
+   if (value) {
dev->features |= NETIF_F_TSO6;
-   else
-   dev->features &= ~NETIF_F_TSO6;
+   if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+   dev->features |= NETIF_F_TSO_ECN;
+   } else
+   dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
}
return ethtool_op_set_tso(dev, value);
 }
@@ -8550,7 +8564,8 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 
data)
 
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
-   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
+   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
ethtool_op_set_tx_ipv6_csum(dev

[PATCH 0/5] tg3: Add 5761 support

2007-10-10 Thread Matt Carlson
The following patchset adds support for the 5761 device and enables WOL
by default if out-of-box WOL is enabled in the NVRAM.  The 5761 patches
were tested against preproduction hardware.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/5] tg3: Update version to 3.83

2007-10-10 Thread Matt Carlson
Update to version 3.83.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 8967bc3..fa8f6c0 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME"tg3"
 #define PFX DRV_MODULE_NAME": "
-#define DRV_MODULE_VERSION "3.82"
-#define DRV_MODULE_RELDATE "October 5, 2007"
+#define DRV_MODULE_VERSION "3.83"
+#define DRV_MODULE_RELDATE "October 10, 2007"
 
 #define TG3_DEF_MAC_MODE   0
 #define TG3_DEF_RX_MODE0


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] tg3: WOL defaults

2007-10-10 Thread Matt Carlson
This patch enables WOL by default if out-of-box WOL is enabled in the
NVRAM.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 3af93b5..8967bc3 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10412,8 +10412,12 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 
*tp)
tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
tp->tg3_flags2 |= TG3_FLG2_IS_NIC;
}
-   if (tr32(VCPU_CFGSHDW) & VCPU_CFGSHDW_ASPM_DBNC)
+   val = tr32(VCPU_CFGSHDW);
+   if (val & VCPU_CFGSHDW_ASPM_DBNC)
tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
+   if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
+   (val & VCPU_CFGSHDW_WOL_MAGPKT))
+   tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
return;
}
 
@@ -10536,6 +10540,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 
*tp)
!(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
 
+   if (tp->tg3_flags & TG3_FLAG_WOL_CAP &&
+   nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE)
+   tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
+
if (cfg2 & (1 << 17))
tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
 
@@ -11454,11 +11462,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
tp->rx_std_max_post = 8;
 
-   /* By default, disable wake-on-lan.  User can change this
-* using ETHTOOL_SWOL.
-*/
-   tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
-
if (tp->tg3_flags & TG3_FLAG_ASPM_WORKAROUND)
tp->pwrmgmt_thresh = tr32(PCIE_PWR_MGMT_THRESH) &
 PCIE_PWR_MGMT_L1_THRESH_MSK;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index d1f5fa3..6dbdad2 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1151,6 +1151,8 @@
 #define  VCPU_STATUS_DRV_RESET  0x0800
 
 #define VCPU_CFGSHDW   0x5104
+#define  VCPU_CFGSHDW_WOL_ENABLE0x0001
+#define  VCPU_CFGSHDW_WOL_MAGPKT0x0004
 #define  VCPU_CFGSHDW_ASPM_DBNC 0x1000
 
 /* Mailboxes */


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] tg3: Add 5761 APE support

2007-10-10 Thread Matt Carlson
This patch adds support for the new APE block, present in 5761 chips.
APE stands for Application Processing Engine.  The primary function of
the APE is to process manageability traffic, such as ASF.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 3200c9c..5b6c1b2 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -314,6 +314,16 @@ static u32 tg3_read32(struct tg3 *tp, u32 off)
return (readl(tp->regs + off));
 }
 
+static void tg3_ape_write32(struct tg3 *tp, u32 off, u32 val)
+{
+   writel(val, tp->aperegs + off);
+}
+
+static u32 tg3_ape_read32(struct tg3 *tp, u32 off)
+{
+   return (readl(tp->aperegs + off));
+}
+
 static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
 {
unsigned long flags;
@@ -500,6 +510,73 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
 
+static void tg3_ape_lock_init(struct tg3 *tp)
+{
+   int i;
+
+   /* Make sure the driver hasn't any stale locks. */
+   for (i = 0; i < 8; i++)
+   tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + 4 * i,
+   APE_LOCK_GRANT_DRIVER);
+}
+
+static int tg3_ape_lock(struct tg3 *tp, int locknum)
+{
+   int i, off;
+   int ret = 0;
+   u32 status;
+
+   if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
+   return 0;
+
+   switch (locknum) {
+   case TG3_APE_LOCK_MEM:
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   off = 4 * locknum;
+
+   tg3_ape_write32(tp, TG3_APE_LOCK_REQ + off, APE_LOCK_REQ_DRIVER);
+
+   /* Wait for up to 1 millisecond to acquire lock. */
+   for (i = 0; i < 100; i++) {
+   status = tg3_ape_read32(tp, TG3_APE_LOCK_GRANT + off);
+   if (status == APE_LOCK_GRANT_DRIVER)
+   break;
+   udelay(10);
+   }
+
+   if (status != APE_LOCK_GRANT_DRIVER) {
+   /* Revoke the lock request. */
+   tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off,
+   APE_LOCK_GRANT_DRIVER);
+
+   ret = -EBUSY;
+   }
+
+   return ret;
+}
+
+static void tg3_ape_unlock(struct tg3 *tp, int locknum)
+{
+   int off;
+
+   if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
+   return;
+
+   switch (locknum) {
+   case TG3_APE_LOCK_MEM:
+   break;
+   default:
+   return;
+   }
+
+   off = 4 * locknum;
+   tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, APE_LOCK_GRANT_DRIVER);
+}
+
 static void tg3_disable_ints(struct tg3 *tp)
 {
tw32(TG3PCI_MISC_HOST_CTRL,
@@ -1448,7 +1525,8 @@ static int tg3_set_power_state(struct tg3 *tp, 
pci_power_t state)
}
 
if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
-   !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+   !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
+   !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
tg3_power_down_phy(tp);
 
tg3_frob_aux_power(tp);
@@ -4726,6 +4804,80 @@ static void tg3_disable_nvram_access(struct tg3 *tp)
}
 }
 
+static void tg3_ape_send_event(struct tg3 *tp, u32 event)
+{
+   int i;
+   u32 apedata;
+
+   apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
+   if (apedata != APE_SEG_SIG_MAGIC)
+   return;
+
+   apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
+   if (apedata != APE_FW_STATUS_READY)
+   return;
+
+   /* Wait for up to 1 millisecond for APE to service previous event. */
+   for (i = 0; i < 10; i++) {
+   if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
+   return;
+
+   apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
+
+   if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+   tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
+   event | APE_EVENT_STATUS_EVENT_PENDING);
+
+   tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
+
+   if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+   break;
+
+   udelay(100);
+   }
+
+   if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+   tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
+}
+
+static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
+{
+   u32 event;
+   u32 apedata;
+
+   if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
+   return;
+
+   switch (kind) {
+   case RESET_KIND_INIT:
+   tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG,
+ 

[PATCH 1/5] tg3: Add new 5761 NVRAM decode routines

2007-10-10 Thread Matt Carlson
This patch adds a new 5761-specific NVRAM strapping decode routine.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 1e0c9e0..3200c9c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -9581,6 +9581,81 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 
*tp)
}
 }
 
+static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
+{
+   u32 nvcfg1, protect = 0;
+
+   nvcfg1 = tr32(NVRAM_CFG1);
+
+   /* NVRAM protection for TPM */
+   if (nvcfg1 & (1 << 27)) {
+   tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+   protect = 1;
+   }
+
+   nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
+   switch (nvcfg1) {
+   case FLASH_5761VENDOR_ATMEL_ADB021D:
+   case FLASH_5761VENDOR_ATMEL_ADB041D:
+   case FLASH_5761VENDOR_ATMEL_ADB081D:
+   case FLASH_5761VENDOR_ATMEL_ADB161D:
+   case FLASH_5761VENDOR_ATMEL_MDB021D:
+   case FLASH_5761VENDOR_ATMEL_MDB041D:
+   case FLASH_5761VENDOR_ATMEL_MDB081D:
+   case FLASH_5761VENDOR_ATMEL_MDB161D:
+   tp->nvram_jedecnum = JEDEC_ATMEL;
+   tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+   tp->tg3_flags2 |= TG3_FLG2_FLASH;
+   tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+   tp->nvram_pagesize = 256;
+   break;
+   case FLASH_5761VENDOR_ST_A_M45PE20:
+   case FLASH_5761VENDOR_ST_A_M45PE40:
+   case FLASH_5761VENDOR_ST_A_M45PE80:
+   case FLASH_5761VENDOR_ST_A_M45PE16:
+   case FLASH_5761VENDOR_ST_M_M45PE20:
+   case FLASH_5761VENDOR_ST_M_M45PE40:
+   case FLASH_5761VENDOR_ST_M_M45PE80:
+   case FLASH_5761VENDOR_ST_M_M45PE16:
+   tp->nvram_jedecnum = JEDEC_ST;
+   tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+   tp->tg3_flags2 |= TG3_FLG2_FLASH;
+   tp->nvram_pagesize = 256;
+   break;
+   }
+
+   if (protect) {
+   tp->nvram_size = tr32(NVRAM_ADDR_LOCKOUT);
+   } else {
+   switch (nvcfg1) {
+   case FLASH_5761VENDOR_ATMEL_ADB161D:
+   case FLASH_5761VENDOR_ATMEL_MDB161D:
+   case FLASH_5761VENDOR_ST_A_M45PE16:
+   case FLASH_5761VENDOR_ST_M_M45PE16:
+   tp->nvram_size = 0x10;
+   break;
+   case FLASH_5761VENDOR_ATMEL_ADB081D:
+   case FLASH_5761VENDOR_ATMEL_MDB081D:
+   case FLASH_5761VENDOR_ST_A_M45PE80:
+   case FLASH_5761VENDOR_ST_M_M45PE80:
+   tp->nvram_size = 0x8;
+   break;
+   case FLASH_5761VENDOR_ATMEL_ADB041D:
+   case FLASH_5761VENDOR_ATMEL_MDB041D:
+   case FLASH_5761VENDOR_ST_A_M45PE40:
+   case FLASH_5761VENDOR_ST_M_M45PE40:
+   tp->nvram_size = 0x4;
+   break;
+   case FLASH_5761VENDOR_ATMEL_ADB021D:
+   case FLASH_5761VENDOR_ATMEL_MDB021D:
+   case FLASH_5761VENDOR_ST_A_M45PE20:
+   case FLASH_5761VENDOR_ST_M_M45PE20:
+   tp->nvram_size = 0x2;
+   break;
+   }
+   }
+}
+
 static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
 {
tp->nvram_jedecnum = JEDEC_ATMEL;
@@ -9623,6 +9698,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
tg3_get_5787_nvram_info(tp);
+   else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+   tg3_get_5761_nvram_info(tp);
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
tg3_get_5906_nvram_info(tp);
else
@@ -9700,6 +9777,7 @@ static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr)
if ((tp->tg3_flags & TG3_FLAG_NVRAM) &&
(tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED) &&
(tp->tg3_flags2 & TG3_FLG2_FLASH) &&
+  !(tp->tg3_flags3 & TG3_FLG3_NO_NVRAM_ADDR_TRANS) &&
(tp->nvram_jedecnum == JEDEC_ATMEL))
 
addr = ((addr / tp->nvram_pagesize) <<

[PATCH] tg3: Fix APE induced regression

2007-10-11 Thread Matt Carlson
This patch fixes a bug caused by the recent APE support added for 5761
devices.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index d2b30fb..e978a79 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -6966,9 +6966,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
break;
};
 
-   /* Write our heartbeat update interval to APE. */
-   tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS,
-   APE_HOST_HEARTBEAT_INT_DISABLE);
+   if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
+   /* Write our heartbeat update interval to APE. */
+   tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS,
+   APE_HOST_HEARTBEAT_INT_DISABLE);
 
tg3_write_sig_post_reset(tp, RESET_KIND_INIT);
 


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/7] pci: Export the pci_restore_msi_state() function

2007-10-19 Thread Matt Carlson
This patch exports the pci_restore_msi_state() function.  This function
is needed to restore the MSI state during PCI error recovery.

Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]>
Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 87e0161..f57762d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -224,7 +224,6 @@ static struct msi_desc* alloc_msi_entry(void)
return entry;
 }
 
-#ifdef CONFIG_PM
 static void __pci_restore_msi_state(struct pci_dev *dev)
 {
int pos;
@@ -282,7 +281,7 @@ void pci_restore_msi_state(struct pci_dev *dev)
__pci_restore_msi_state(dev);
__pci_restore_msix_state(dev);
 }
-#endif /* CONFIG_PM */
+EXPORT_SYMBOL_GPL(pci_restore_msi_state);
 
 /**
  * msi_capability_init - configure device's MSI capability structure
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 6fda33d..23c6c17 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -45,12 +45,6 @@ static inline void pci_no_msi(void) { }
 static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
 #endif
 
-#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
-void pci_restore_msi_state(struct pci_dev *dev);
-#else
-static inline void pci_restore_msi_state(struct pci_dev *dev) {}
-#endif
-
 #ifdef CONFIG_PCIEAER
 void pci_no_aer(void);
 #else
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 768b933..5575227 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -662,6 +662,7 @@ static inline int pci_enable_msix(struct pci_dev* dev,
struct msix_entry *entries, int nvec) {return -1;}
 static inline void pci_disable_msix(struct pci_dev *dev) {}
 static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+static inline void pci_restore_msi_state(struct pci_dev *dev) {}
 #else
 extern int pci_enable_msi(struct pci_dev *dev);
 extern void pci_disable_msi(struct pci_dev *dev);
@@ -669,6 +670,7 @@ extern int pci_enable_msix(struct pci_dev* dev,
struct msix_entry *entries, int nvec);
 extern void pci_disable_msix(struct pci_dev *dev);
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+void pci_restore_msi_state(struct pci_dev *dev);
 #endif
 
 #ifdef CONFIG_HT_IRQ


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/7] tg3: Add management FW version to ethtool report

2007-10-19 Thread Matt Carlson
This patch appends the management firmware version to the bootcode
firmware string reported through ethtool.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 66682b8..68472ce 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10821,9 +10821,24 @@ out_not_found:
strcpy(tp->board_part_number, "none");
 }
 
+static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+{
+   u32 val;
+
+   if (tg3_nvram_read_swab(tp, offset, &val) ||
+   (val & 0xfc00) != 0x0c00 ||
+   tg3_nvram_read_swab(tp, offset + 4, &val) ||
+   val != 0)
+   return 0;
+
+   return 1;
+}
+
 static void __devinit tg3_read_fw_ver(struct tg3 *tp)
 {
u32 val, offset, start;
+   u32 ver_offset;
+   int i, bcnt;
 
if (tg3_nvram_read_swab(tp, 0, &val))
return;
@@ -10836,29 +10851,71 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
return;
 
offset = tg3_nvram_logical_addr(tp, offset);
-   if (tg3_nvram_read_swab(tp, offset, &val))
+
+   if (!tg3_fw_img_is_valid(tp, offset) ||
+   tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
return;
 
-   if ((val & 0xfc00) == 0x0c00) {
-   u32 ver_offset, addr;
-   int i;
+   offset = offset + ver_offset - start;
+   for (i = 0; i < 16; i += 4) {
+   if (tg3_nvram_read(tp, offset + i, &val))
+   return;
+
+   val = le32_to_cpu(val);
+   memcpy(tp->fw_ver + i, &val, 4);
+   }
 
-   if (tg3_nvram_read_swab(tp, offset + 4, &val) ||
-   tg3_nvram_read_swab(tp, offset + 8, &ver_offset))
+   if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+(tp->tg3_flags & TG3_FLG3_ENABLE_APE))
+   return;
+
+   for (offset = TG3_NVM_DIR_START;
+offset < TG3_NVM_DIR_END;
+offset += TG3_NVM_DIRENT_SIZE) {
+   if (tg3_nvram_read_swab(tp, offset, &val))
return;
 
-   if (val != 0)
+   if ((val >> TG3_NVM_DIRTYPE_SHIFT) == TG3_NVM_DIRTYPE_ASFINI)
+   break;
+   }
+
+   if (offset == TG3_NVM_DIR_END)
+   return;
+
+   if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+   start = 0x0800;
+   else if (tg3_nvram_read_swab(tp, offset - 4, &start))
+   return;
+
+   if (tg3_nvram_read_swab(tp, offset + 4, &offset) ||
+   !tg3_fw_img_is_valid(tp, offset) ||
+   tg3_nvram_read_swab(tp, offset + 8, &val))
+   return;
+
+   offset += val - start;
+
+   bcnt = strlen(tp->fw_ver);
+
+   tp->fw_ver[bcnt++] = ',';
+   tp->fw_ver[bcnt++] = ' ';
+
+   for (i = 0; i < 4; i++) {
+   if (tg3_nvram_read(tp, offset, &val))
return;
 
-   addr = offset + ver_offset - start;
-   for (i = 0; i < 16; i += 4) {
-   if (tg3_nvram_read(tp, addr + i, &val))
-   return;
+   val = le32_to_cpu(val);
+   offset += sizeof(val);
 
-   val = cpu_to_le32(val);
-   memcpy(tp->fw_ver + i, &val, 4);
+   if (bcnt > TG3_VER_SIZE - sizeof(val)) {
+   memcpy(&tp->fw_ver[bcnt], &val, TG3_VER_SIZE - bcnt);
+   break;
}
+
+   memcpy(&tp->fw_ver[bcnt], &val, sizeof(val));
+   bcnt += sizeof(val);
}
+
+   tp->fw_ver[TG3_VER_SIZE - 1] = 0;
 }
 
 static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 6dbdad2..495a1df 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1540,6 +1540,12 @@
 #define TG3_EEPROM_MAGIC_HW0xabcd
 #define TG3_EEPROM_MAGIC_HW_MSK0x
 
+#define TG3_NVM_DIR_START  0x18
+#define TG3_NVM_DIR_END0x78
+#define TG3_NVM_DIRENT_SIZE0xc
+#define TG3_NVM_DIRTYPE_SHIFT  24
+#define TG3_NVM_DIRTYPE_ASFINI 1
+
 /* 32K Window into NIC internal memory */
 #define NIC_SRAM_WIN_BASE  0x8000
 
@@ -2418,7 +2424,8 @@ struct tg3 {
u32 pci_cmd;
 
charboard_part_number[24];
-   charfw_ver[16];
+#define TG3_VER_SIZE 32
+   charfw_ver[TG3_VER_SIZE];
u32 nic_sram_data_cfg;
u32 pci_

[PATCH 0/7] tg3: PCI error recovery and more

2007-10-19 Thread Matt Carlson
This patchset adds PCI error recovery, 5723 support and a few other odds
and ends.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/7] tg3: PCI command adjustment

2007-10-19 Thread Matt Carlson
This patch changes the way the driver works with the PCI command
register.  It adjusts the access size from dwords to words.  This patch
is done both as a PCI configuration space cleanup and as preparatory
work for PCI error recovery.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 68472ce..9920751 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5029,10 +5029,7 @@ static int tg3_poll_fw(struct tg3 *tp)
 /* Save PCI command register before chip reset */
 static void tg3_save_pci_state(struct tg3 *tp)
 {
-   u32 val;
-
-   pci_read_config_dword(tp->pdev, TG3PCI_COMMAND, &val);
-   tp->pci_cmd = val;
+   pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
 }
 
 /* Restore PCI state after chip reset */
@@ -5055,7 +5052,7 @@ static void tg3_restore_pci_state(struct tg3 *tp)
   PCISTATE_ALLOW_APE_SHMEM_WR;
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
 
-   pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
+   pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
 
if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 495a1df..1d5b2a3 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2421,7 +2421,7 @@ struct tg3 {
 #define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */
 
u32 led_ctrl;
-   u32 pci_cmd;
+   u16 pci_cmd;
 
charboard_part_number[24];
 #define TG3_VER_SIZE 32


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/7] tg3: MII => TP

2007-10-19 Thread Matt Carlson
This patch changes the PHY type reported through ethtool for copper
devices from MII to TP.  The latter is more accurate.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 253d761..66682b8 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -8274,7 +8274,7 @@ static int tg3_get_settings(struct net_device *dev, 
struct ethtool_cmd *cmd)
  SUPPORTED_100baseT_Full |
  SUPPORTED_10baseT_Half |
  SUPPORTED_10baseT_Full |
- SUPPORTED_MII);
+ SUPPORTED_TP);
cmd->port = PORT_TP;
} else {
cmd->supported |= SUPPORTED_FIBRE;


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/7] tg3: Add PCI error recovery

2007-10-19 Thread Matt Carlson
This patch adds PCI error recovery support.

Signed-off-by: Linas Vepstas <[EMAIL PROTECTED]>
Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 9920751..d866387 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5026,12 +5026,6 @@ static int tg3_poll_fw(struct tg3 *tp)
return 0;
 }
 
-/* Save PCI command register before chip reset */
-static void tg3_save_pci_state(struct tg3 *tp)
-{
-   pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
-}
-
 /* Restore PCI state after chip reset */
 static void tg3_restore_pci_state(struct tg3 *tp)
 {
@@ -5107,12 +5101,6 @@ static int tg3_chip_reset(struct tg3 *tp)
 */
tp->nvram_lock_cnt = 0;
 
-   /* GRC_MISC_CFG core clock reset will clear the memory
-* enable bit in PCI register 4 and the MSI enable bit
-* on some chips, so we save relevant registers here.
-*/
-   tg3_save_pci_state(tp);
-
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
@@ -12527,6 +12515,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tg3_ape_lock_init(tp);
}
 
+   pci_read_config_word(tp->pdev, PCI_COMMAND, &tp->pci_cmd);
+
pci_set_drvdata(pdev, dev);
 
err = register_netdev(dev);
@@ -12706,11 +12696,148 @@ out:
return err;
 }
 
+/**
+ * tg3_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+   int rc;
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct tg3 *tp = netdev_priv(netdev);
+   struct device *dev = &netdev->dev;
+
+   rtnl_lock();
+
+   dev_info(dev, "PCI I/O error detected on %s\n", netdev->name);
+
+   if (!netif_running(netdev)) {
+   rc = PCI_ERS_RESULT_NEED_RESET;
+   goto done;
+   }
+
+   /* Want to make sure that the reset task doesn't run */
+   cancel_work_sync(&tp->reset_task);
+   tg3_netif_stop(tp);
+   del_timer_sync(&tp->timer);
+   netif_device_detach(netdev);
+   pci_disable_device(pdev);
+
+   if (state == pci_channel_io_perm_failure) {
+   /* avoid hang in dev_close() with rtnl_lock held */
+   napi_enable(&tp->napi);
+   rc = PCI_ERS_RESULT_DISCONNECT;
+   goto done;
+   }
+
+   rc = PCI_ERS_RESULT_NEED_RESET;
+
+done:
+   rtnl_unlock();
+
+   return rc;
+}
+
+/**
+ * tg3_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ * At this point, the card has exprienced a hard reset,
+ * followed by fixups by BIOS, and has its config space
+ * set up identically to what it was at cold boot.
+ */
+static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev)
+{
+   struct net_device *netdev = pci_get_drvdata(pdev);
+   struct tg3 *tp = netdev_priv(netdev);
+   int rc;
+
+   rtnl_lock();
+
+   pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
+
+   if (!netif_running(netdev)) {
+   rc = PCI_ERS_RESULT_RECOVERED;
+   goto done;
+   }
+
+   if (pci_enable_device(pdev)) {
+   printk(KERN_ERR "tg3: %s: "
+  "Cannot re-enable PCI device after reset.\n",
+  netdev->name);
+   rc = PCI_ERS_RESULT_DISCONNECT;
+   goto done;
+   }
+
+   pci_set_master(pdev);
+   pci_restore_msi_state(tp->pdev);
+   netif_device_attach(netdev);
+
+   tg3_full_lock(tp, 0);
+   tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
+   rc = tg3_restart_hw(tp, 1);
+   tg3_full_unlock(tp);
+   if (rc) {
+   printk(KERN_ERR "tg3: %s: "
+  "Cannot restart hardware after reset.\n", netdev->name);
+   rc = PCI_ERS_RESULT_DISCONNECT;
+   goto done;
+   }
+
+   rc = PCI_ERS_RESULT_RECOVERED;
+
+done:
+   rtnl_unlock();
+
+   return rc;
+}
+
+/**
+ * tg3_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells
+ * us that its OK to resume normal operation.
+ */
+static void tg3_io_resume(struct pci_dev *pdev)
+{
+   struct net_device *netdev = p

[PATCH 7/7] tg3: Update version to 3.85

2007-10-19 Thread Matt Carlson
This patch updates the version number to 3.85.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index d866387..e5cf97a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
 
 #define DRV_MODULE_NAME"tg3"
 #define PFX DRV_MODULE_NAME": "
-#define DRV_MODULE_VERSION "3.84"
-#define DRV_MODULE_RELDATE "October 12, 2007"
+#define DRV_MODULE_VERSION "3.85"
+#define DRV_MODULE_RELDATE "October 18, 2007"
 
 #define TG3_DEF_MAC_MODE   0
 #define TG3_DEF_RX_MODE0


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/7] tg3: Add 5723 support

2007-10-19 Thread Matt Carlson
This patch adds support for upcoming 5723 devices.

Signed-off-by: Matt Carlson <[EMAIL PROTECTED]>
Signed-off-by: Michael Chan <[EMAIL PROTECTED]>

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 014dc2c..253d761 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -200,6 +200,7 @@ static struct pci_device_id tg3_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)},
+   {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index df948b4..4e10a07 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1943,6 +1943,7 @@
 #define PCI_DEVICE_ID_TIGON3_5720  0x1658
 #define PCI_DEVICE_ID_TIGON3_5721  0x1659
 #define PCI_DEVICE_ID_TIGON3_5722  0x165a
+#define PCI_DEVICE_ID_TIGON3_5723  0x165b
 #define PCI_DEVICE_ID_TIGON3_5705M 0x165d
 #define PCI_DEVICE_ID_TIGON3_5705M_2   0x165e
 #define PCI_DEVICE_ID_TIGON3_5714  0x1668


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: TG3 network data corruption regression 2.6.24/2.6.23.4

2008-02-19 Thread Matt Carlson
On Tue, Feb 19, 2008 at 05:14:26PM -0500, Tony Battersby wrote:
> Michael Chan wrote:
> > On Tue, 2008-02-19 at 11:16 -0500, Tony Battersby wrote:
> >   
> >> iSCSI
> >> performance drops to 6 - 15 MB/s when the 3Com NIC is doing heavy rx
> >> with light tx,
> >> 
> >
> > That's strange.  The patch should only affect TX performance slightly
> > since we are just turning off SG for TX.  Please take an ethereal trace
> > to see what's happening and compare with a good trace.
> >
> >   
> 
> Update: when I revert Herbert's patch in addition to applying your
> patch, the iSCSI performance goes back up to 115 MB/s again in both
> directions.  So it looks like turning off SG for TX didn't itself cause
> the performance drop, but rather that the performance drop is just
> another manifestation of whatever bug is causing the data corruption.
> 
> I do not regularly use wireshark or look at network packet dumps, so I
> am not really sure what to look for.  Given the above information, do
> you still believe that there is value in examining the packet dump?
> 
> Tony

Hi Tony.  Can you give us the output of :

sudo lspci -vvv - -s 03:01.0'

(assuming that is still the correct address of the 3Com NIC.)

Also, after some digging, I found that the 5701 can run into trouble if
a 64-bit DMA read terminates early and then completes as a 32-bit transfer.
The problem is reportedly very rare, but the failure mode looks like a
match.  Can you apply the following patch and see if it helps your
performance / corruption problems?


diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index db606b6..7ad08ce 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -11409,6 +11409,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
tp->tg3_flags |= TG3_FLAG_PCI_32BIT;
+   else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)
+   tp->grc_mode |= GRC_MODE_FORCE_PCI32BIT;
 
/* Chip-specific fixup from Broadcom driver */
if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) &&


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html