* [PATCH 00/10] sky2: version 1.9 patches
@ 2006-10-11 21:22 Stephen Hemminger
2006-10-11 21:22 ` [PATCH 01/10] sky2: MSI test is only a warning Stephen Hemminger
` (9 more replies)
0 siblings, 10 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
Several little patches to sky2 driver. Mostly having to do with
PHY handling and flow control.
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 01/10] sky2: MSI test is only a warning
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 02/10] sky2: turn of workaround timer Stephen Hemminger
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: msi-message.patch --]
[-- Type: text/plain, Size: 946 bytes --]
Some motherboards don't implement MSI correctly. The driver handles this
but the warning is too verbose and overly cautious.
Signed-off-by: Stephe Hemminger <shemminger@osdl.org>
--- sky2.orig/drivers/net/sky2.c 2006-10-11 11:43:08.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 11:43:33.000000000 -0700
@@ -3326,9 +3326,8 @@
if (!hw->msi_detected) {
/* MSI test failed, go back to INTx mode */
- printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, "
- "switching to INTx mode. Please report this failure to "
- "the PCI maintainer and include system chipset information.\n",
+ printk(KERN_INFO PFX "%s: No interrupt generated using MSI, "
+ "switching to INTx mode.\n",
pci_name(pdev));
err = -EOPNOTSUPP;
@@ -3336,6 +3335,7 @@
}
sky2_write32(hw, B0_IMSK, 0);
+ sky2_read32(hw, B0_IMSK);
free_irq(pdev->irq, hw);
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 02/10] sky2: turn of workaround timer
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
2006-10-11 21:22 ` [PATCH 01/10] sky2: MSI test is only a warning Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 03/10] sky2: phy irq on shutdown Stephen Hemminger
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-no-timer.patch --]
[-- Type: text/plain, Size: 963 bytes --]
The workaround timer is not needed in most systems with proper IRQ
routing and by perodically waking up it adds to laptop power consumption.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
---
drivers/net/sky2.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- sky2.orig/drivers/net/sky2.c 2006-10-11 11:43:33.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 11:43:40.000000000 -0700
@@ -96,9 +96,9 @@
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
-static int idle_timeout = 100;
+static int idle_timeout = 0;
module_param(idle_timeout, int, 0);
-MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms)");
+MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 03/10] sky2: phy irq on shutdown
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
2006-10-11 21:22 ` [PATCH 01/10] sky2: MSI test is only a warning Stephen Hemminger
2006-10-11 21:22 ` [PATCH 02/10] sky2: turn of workaround timer Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 04/10] sky2: fiber pause bits Stephen Hemminger
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-phy-read-shut.patch --]
[-- Type: text/plain, Size: 1502 bytes --]
When PHY is turned off on shutdown, it causes the IRQ to get stuck on.
Make sure and disable the IRQ first, and if IRQ occurs when device
is not running, don't access PHY because that will hang.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
--- sky2.orig/drivers/net/sky2.c 2006-10-11 11:43:40.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 11:43:43.000000000 -0700
@@ -1499,6 +1499,11 @@
/* Stop more packets from being queued */
netif_stop_queue(dev);
+ /* Disable port IRQ */
+ imask = sky2_read32(hw, B0_IMSK);
+ imask &= ~portirq_msk[port];
+ sky2_write32(hw, B0_IMSK, imask);
+
sky2_gmac_reset(hw, port);
/* Stop transmitter */
@@ -1549,11 +1554,6 @@
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
- /* Disable port IRQ */
- imask = sky2_read32(hw, B0_IMSK);
- imask &= ~portirq_msk[port];
- sky2_write32(hw, B0_IMSK, imask);
-
sky2_phy_power(hw, port, 0);
/* turn off LED's */
@@ -1750,13 +1750,13 @@
struct sky2_port *sky2 = netdev_priv(dev);
u16 istatus, phystat;
+ if (!netif_running(dev))
+ return;
+
spin_lock(&sky2->phy_lock);
istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT);
phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
- if (!netif_running(dev))
- goto out;
-
if (netif_msg_intr(sky2))
printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n",
sky2->netdev->name, istatus, phystat);
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 04/10] sky2: fiber pause bits
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
` (2 preceding siblings ...)
2006-10-11 21:22 ` [PATCH 03/10] sky2: phy irq on shutdown Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 05/10] sky2: advertising register 16 bits Stephen Hemminger
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-fiber-pause-bits.patch --]
[-- Type: text/plain, Size: 1578 bytes --]
The advertisement bits for flow control are located in
different location on fiber (1000baseX)
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
--- sky2.orig/drivers/net/sky2.c 2006-10-11 11:43:43.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 11:43:47.000000000 -0700
@@ -384,20 +384,31 @@
adv |= PHY_M_AN_10_FD;
if (sky2->advertising & ADVERTISED_10baseT_Half)
adv |= PHY_M_AN_10_HD;
+
+ /* desired flow control */
+ if (sky2->tx_pause && sky2->rx_pause) /* both */
+ adv |= PHY_M_AN_PC | PHY_M_AN_ASP;
+ else if (sky2->tx_pause)
+ adv |= PHY_M_AN_ASP;
+ else if (sky2->rx_pause)
+ adv |= PHY_M_AN_PC;
+
+
} else { /* special defines for FIBER (88E1040S only) */
if (sky2->advertising & ADVERTISED_1000baseT_Full)
adv |= PHY_M_AN_1000X_AFD;
if (sky2->advertising & ADVERTISED_1000baseT_Half)
adv |= PHY_M_AN_1000X_AHD;
- }
- /* Set Flow-control capabilities */
- if (sky2->tx_pause && sky2->rx_pause)
- adv |= PHY_AN_PAUSE_CAP; /* symmetric */
- else if (sky2->rx_pause && !sky2->tx_pause)
- adv |= PHY_AN_PAUSE_ASYM | PHY_AN_PAUSE_CAP;
- else if (!sky2->rx_pause && sky2->tx_pause)
- adv |= PHY_AN_PAUSE_ASYM; /* local */
+ if (sky2->tx_pause && sky2->rx_pause) /* both */
+ adv |= PHY_M_P_BOTH_MD_X;
+ else if (sky2->tx_pause)
+ adv |= PHY_M_P_ASYM_MD_X;
+ else if (sky2->rx_pause)
+ adv |= PHY_M_P_SYM_MD_X;
+ else
+ adv |= PHY_M_P_NO_PAUSE_X;
+ }
/* Restart Auto-negotiation */
ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 05/10] sky2: advertising register 16 bits
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
` (3 preceding siblings ...)
2006-10-11 21:22 ` [PATCH 04/10] sky2: fiber pause bits Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 06/10] sky2: use duplex result bits Stephen Hemminger
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-advertise-bits.patch --]
[-- Type: text/plain, Size: 627 bytes --]
The advertising bits (from ethtool.h) fit in 16 bits.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
--- sky2.orig/drivers/net/sky2.h 2006-10-11 11:56:25.000000000 -0700
+++ sky2/drivers/net/sky2.h 2006-10-11 11:56:42.000000000 -0700
@@ -1860,7 +1860,7 @@
dma_addr_t rx_le_map;
dma_addr_t tx_le_map;
- u32 advertising; /* ADVERTISED_ bits */
+ u16 advertising; /* ADVERTISED_ bits */
u16 speed; /* SPEED_1000, SPEED_100, ... */
u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */
u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 06/10] sky2: use duplex result bits
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
` (4 preceding siblings ...)
2006-10-11 21:22 ` [PATCH 05/10] sky2: advertising register 16 bits Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 07/10] sky2: dont reset PHY twice Stephen Hemminger
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-duplex-result.patch --]
[-- Type: text/plain, Size: 1327 bytes --]
The result of duplex negotiation is avaliable in the phy status
register, so use that to simplify code and avoid rereading the PHY.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
---
drivers/net/sky2.c | 21 +--------------------
1 file changed, 1 insertion(+), 20 deletions(-)
--- sky2.orig/drivers/net/sky2.c 2006-10-11 11:43:47.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 11:43:50.000000000 -0700
@@ -1714,26 +1714,7 @@
}
sky2->speed = sky2_phy_speed(hw, aux);
- if (sky2->speed == SPEED_1000) {
- u16 ctl2 = gm_phy_read(hw, port, PHY_MARV_1000T_CTRL);
- u16 lpa2 = gm_phy_read(hw, port, PHY_MARV_1000T_STAT);
- if (lpa2 & PHY_B_1000S_MSF) {
- printk(KERN_ERR PFX "%s: master/slave fault",
- sky2->netdev->name);
- return -1;
- }
-
- if ((ctl2 & PHY_M_1000C_AFD) && (lpa2 & PHY_B_1000S_LP_FD))
- sky2->duplex = DUPLEX_FULL;
- else
- sky2->duplex = DUPLEX_HALF;
- } else {
- u16 adv = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
- if ((aux & adv) & PHY_AN_FULL)
- sky2->duplex = DUPLEX_FULL;
- else
- sky2->duplex = DUPLEX_HALF;
- }
+ sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
/* Pause bits are offset (9..8) */
if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 07/10] sky2: dont reset PHY twice
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
` (5 preceding siblings ...)
2006-10-11 21:22 ` [PATCH 06/10] sky2: use duplex result bits Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 08/10] sky2: flow control setting fixes Stephen Hemminger
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-phy-one-reset.patch --]
[-- Type: text/plain, Size: 875 bytes --]
Don't need to reset PHY twice on startup.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
--- sky2.orig/drivers/net/sky2.c 2006-10-11 11:59:45.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 14:21:36.000000000 -0700
@@ -356,16 +356,7 @@
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
}
- ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
- if (sky2->autoneg == AUTONEG_DISABLE)
- ctrl &= ~PHY_CT_ANE;
- else
- ctrl |= PHY_CT_ANE;
-
- ctrl |= PHY_CT_RESET;
- gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
-
- ctrl = 0;
+ ctrl = PHY_CT_RESET;
ct1000 = 0;
adv = PHY_AN_CSMA;
reg = 0;
@@ -450,8 +441,6 @@
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
else
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
-
- ctrl |= PHY_CT_RESET;
}
gma_write16(hw, port, GM_GP_CTRL, reg);
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 08/10] sky2: flow control setting fixes
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
` (6 preceding siblings ...)
2006-10-11 21:22 ` [PATCH 07/10] sky2: dont reset PHY twice Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 09/10] sky2: no message on rx fifo overflow Stephen Hemminger
2006-10-11 21:22 ` [PATCH 10/10] sky2: version 1.9 Stephen Hemminger
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-fc-auto.patch --]
[-- Type: text/plain, Size: 7351 bytes --]
The result of flow control negotiation should not limit the next
negotiatition. If board is plugged into an old half duplex 10Mbit port,
without pause, then replugged into a gigabit port, it should negotiate
what is desired, not inherit that last negotiation.
P.s: many other drivers have this bug.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
---
drivers/net/sky2.c | 132 ++++++++++++++++++++++++++++++-----------------------
drivers/net/sky2.h | 13 ++++-
2 files changed, 86 insertions(+), 59 deletions(-)
--- sky2.orig/drivers/net/sky2.c 2006-10-11 12:00:37.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 12:05:46.000000000 -0700
@@ -284,6 +284,31 @@
gma_write16(hw, port, GM_RX_CTRL, reg);
}
+/* flow control to advertise bits */
+static const u16 copper_fc_adv[] = {
+ [FC_NONE] = 0,
+ [FC_TX] = PHY_M_AN_ASP,
+ [FC_RX] = PHY_M_AN_PC,
+ [FC_BOTH] = PHY_M_AN_PC | PHY_M_AN_ASP,
+};
+
+/* flow control to advertise bits when using 1000BaseX */
+static const u16 fiber_fc_adv[] = {
+ [FC_BOTH] = PHY_M_P_BOTH_MD_X,
+ [FC_TX] = PHY_M_P_ASYM_MD_X,
+ [FC_RX] = PHY_M_P_SYM_MD_X,
+ [FC_NONE] = PHY_M_P_NO_PAUSE_X,
+};
+
+/* flow control to GMA disable bits */
+static const u16 gm_fc_disable[] = {
+ [FC_NONE] = GM_GPCR_FC_RX_DIS | GM_GPCR_FC_TX_DIS,
+ [FC_TX] = GM_GPCR_FC_RX_DIS,
+ [FC_RX] = GM_GPCR_FC_TX_DIS,
+ [FC_BOTH] = 0,
+};
+
+
static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
{
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -376,29 +401,14 @@
if (sky2->advertising & ADVERTISED_10baseT_Half)
adv |= PHY_M_AN_10_HD;
- /* desired flow control */
- if (sky2->tx_pause && sky2->rx_pause) /* both */
- adv |= PHY_M_AN_PC | PHY_M_AN_ASP;
- else if (sky2->tx_pause)
- adv |= PHY_M_AN_ASP;
- else if (sky2->rx_pause)
- adv |= PHY_M_AN_PC;
-
-
+ adv |= copper_fc_adv[sky2->flow_mode];
} else { /* special defines for FIBER (88E1040S only) */
if (sky2->advertising & ADVERTISED_1000baseT_Full)
adv |= PHY_M_AN_1000X_AFD;
if (sky2->advertising & ADVERTISED_1000baseT_Half)
adv |= PHY_M_AN_1000X_AHD;
- if (sky2->tx_pause && sky2->rx_pause) /* both */
- adv |= PHY_M_P_BOTH_MD_X;
- else if (sky2->tx_pause)
- adv |= PHY_M_P_ASYM_MD_X;
- else if (sky2->rx_pause)
- adv |= PHY_M_P_SYM_MD_X;
- else
- adv |= PHY_M_P_NO_PAUSE_X;
+ adv |= fiber_fc_adv[sky2->flow_mode];
}
/* Restart Auto-negotiation */
@@ -424,20 +434,14 @@
if (sky2->duplex == DUPLEX_FULL) {
reg |= GM_GPCR_DUP_FULL;
ctrl |= PHY_CT_DUP_MD;
- } else if (sky2->speed != SPEED_1000 && hw->chip_id != CHIP_ID_YUKON_EC_U) {
- /* Turn off flow control for 10/100mbps */
- sky2->rx_pause = 0;
- sky2->tx_pause = 0;
- }
+ } else if (sky2->speed < SPEED_1000)
+ sky2->flow_mode = FC_NONE;
- if (!sky2->rx_pause)
- reg |= GM_GPCR_FC_RX_DIS;
- if (!sky2->tx_pause)
- reg |= GM_GPCR_FC_TX_DIS;
+ reg |= gm_fc_disable[sky2->flow_mode];
/* Forward pause packets to GMAC? */
- if (sky2->tx_pause || sky2->rx_pause)
+ if (sky2->flow_mode & FC_RX)
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
else
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -1605,6 +1609,12 @@
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
u16 reg;
+ static const char *fc_name[] = {
+ [FC_NONE] = "none",
+ [FC_TX] = "tx",
+ [FC_RX] = "rx",
+ [FC_BOTH] = "both",
+ };
/* enable Rx/Tx */
reg = gma_read16(hw, port, GM_GP_CTRL);
@@ -1648,8 +1658,7 @@
"%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
sky2->netdev->name, sky2->speed,
sky2->duplex == DUPLEX_FULL ? "full" : "half",
- (sky2->tx_pause && sky2->rx_pause) ? "both" :
- sky2->tx_pause ? "tx" : sky2->rx_pause ? "rx" : "none");
+ fc_name[sky2->flow_status]);
}
static void sky2_link_down(struct sky2_port *sky2)
@@ -1664,7 +1673,7 @@
reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
gma_write16(hw, port, GM_GP_CTRL, reg);
- if (sky2->rx_pause && !sky2->tx_pause) {
+ if (sky2->flow_status == FC_RX) {
/* restore Asymmetric Pause bit */
gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
gm_phy_read(hw, port, PHY_MARV_AUNE_ADV)
@@ -1683,6 +1692,14 @@
sky2_phy_init(hw, port);
}
+static enum flow_control sky2_flow(int rx, int tx)
+{
+ if (rx)
+ return tx ? FC_BOTH : FC_RX;
+ else
+ return tx ? FC_TX : FC_NONE;
+}
+
static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
{
struct sky2_hw *hw = sky2->hw;
@@ -1709,14 +1726,14 @@
if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)
aux >>= 6;
- sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0;
- sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0;
+ sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN,
+ aux & PHY_M_PS_TX_P_EN);
- if (sky2->duplex == DUPLEX_HALF && sky2->speed != SPEED_1000
+ if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000
&& hw->chip_id != CHIP_ID_YUKON_EC_U)
- sky2->rx_pause = sky2->tx_pause = 0;
+ sky2->flow_status = FC_NONE;
- if (sky2->rx_pause || sky2->tx_pause)
+ if (aux & PHY_M_PS_RX_P_EN)
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
else
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -2729,7 +2746,7 @@
{
struct sky2_port *sky2 = netdev_priv(dev);
- if (sky2->autoneg != AUTONEG_ENABLE)
+ if (!netif_running(dev) || sky2->autoneg != AUTONEG_ENABLE)
return -EINVAL;
sky2_phy_reinit(sky2);
@@ -2971,8 +2988,20 @@
{
struct sky2_port *sky2 = netdev_priv(dev);
- ecmd->tx_pause = sky2->tx_pause;
- ecmd->rx_pause = sky2->rx_pause;
+ switch (sky2->flow_mode) {
+ case FC_NONE:
+ ecmd->tx_pause = ecmd->rx_pause = 0;
+ break;
+ case FC_TX:
+ ecmd->tx_pause = 1, ecmd->rx_pause = 0;
+ break;
+ case FC_RX:
+ ecmd->tx_pause = 0, ecmd->rx_pause = 1;
+ break;
+ case FC_BOTH:
+ ecmd->tx_pause = ecmd->rx_pause = 1;
+ }
+
ecmd->autoneg = sky2->autoneg;
}
@@ -2982,10 +3011,10 @@
struct sky2_port *sky2 = netdev_priv(dev);
sky2->autoneg = ecmd->autoneg;
- sky2->tx_pause = ecmd->tx_pause != 0;
- sky2->rx_pause = ecmd->rx_pause != 0;
+ sky2->flow_mode = sky2_flow(ecmd->rx_pause, ecmd->tx_pause);
- sky2_phy_reinit(sky2);
+ if (netif_running(dev))
+ sky2_phy_reinit(sky2);
return 0;
}
@@ -3215,8 +3244,8 @@
/* Auto speed and flow control */
sky2->autoneg = AUTONEG_ENABLE;
- sky2->tx_pause = 1;
- sky2->rx_pause = 1;
+ sky2->flow_mode = FC_BOTH;
+
sky2->duplex = -1;
sky2->speed = -1;
sky2->advertising = sky2_supported_modes(hw);
--- sky2.orig/drivers/net/sky2.h 2006-10-11 11:59:32.000000000 -0700
+++ sky2/drivers/net/sky2.h 2006-10-11 12:01:20.000000000 -0700
@@ -1828,6 +1828,13 @@
dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT];
};
+enum flow_control {
+ FC_NONE = 0,
+ FC_TX = 1,
+ FC_RX = 2,
+ FC_BOTH = 3,
+};
+
struct sky2_port {
struct sky2_hw *hw;
struct net_device *netdev;
@@ -1864,9 +1871,9 @@
u16 speed; /* SPEED_1000, SPEED_100, ... */
u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */
u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */
- u8 rx_pause;
- u8 tx_pause;
u8 rx_csum;
+ enum flow_control flow_mode;
+ enum flow_control flow_status;
struct net_device_stats net_stats;
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 09/10] sky2: no message on rx fifo overflow
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
` (7 preceding siblings ...)
2006-10-11 21:22 ` [PATCH 08/10] sky2: flow control setting fixes Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-11 21:22 ` [PATCH 10/10] sky2: version 1.9 Stephen Hemminger
9 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-no-overflow-msg.patch --]
[-- Type: text/plain, Size: 1013 bytes --]
Under high load it is possible to make the receiver FIFO get overloaded.
The driver/hardware recover properly, so there is no reason to fill the log
with lots of extra messages, just update counter.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
---
drivers/net/sky2.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- sky2.orig/drivers/net/sky2.c 2006-10-11 12:05:46.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 12:05:54.000000000 -0700
@@ -2014,6 +2014,10 @@
error:
++sky2->net_stats.rx_errors;
+ if (status & GMR_FS_RX_FF_OV) {
+ sky2->net_stats.rx_fifo_errors++;
+ goto resubmit;
+ }
if (netif_msg_rx_err(sky2) && net_ratelimit())
printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n",
@@ -2025,8 +2029,6 @@
sky2->net_stats.rx_frame_errors++;
if (status & GMR_FS_CRC_ERR)
sky2->net_stats.rx_crc_errors++;
- if (status & GMR_FS_RX_FF_OV)
- sky2->net_stats.rx_fifo_errors++;
goto resubmit;
}
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 10/10] sky2: version 1.9
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
` (8 preceding siblings ...)
2006-10-11 21:22 ` [PATCH 09/10] sky2: no message on rx fifo overflow Stephen Hemminger
@ 2006-10-11 21:22 ` Stephen Hemminger
2006-10-16 20:50 ` [PATCH 1/2] sky2: multicast pause frame receive Stephen Hemminger
2006-10-16 20:52 ` [PATCH 2/2] sky2: don't process pause frames in recveiver Stephen Hemminger
9 siblings, 2 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-11 21:22 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: sky2-1.10.patch --]
[-- Type: text/plain, Size: 437 bytes --]
Mark version, this has been a lot of patches.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
--- sky2.orig/drivers/net/sky2.c 2006-10-11 14:19:14.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-11 14:19:23.000000000 -0700
@@ -50,7 +50,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.9"
+#define DRV_VERSION "1.10"
#define PFX DRV_NAME " "
/*
--
Stephen Hemminger <shemminger@osdl.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/2] sky2: multicast pause frame receive
2006-10-11 21:22 ` [PATCH 10/10] sky2: version 1.9 Stephen Hemminger
@ 2006-10-16 20:50 ` Stephen Hemminger
2006-10-16 20:52 ` [PATCH 2/2] sky2: don't process pause frames in recveiver Stephen Hemminger
1 sibling, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-16 20:50 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
When using flow control, the PHY needs to accept multicast pause frames.
Without this fix, these frames were getting discarded by the PHY before
doing any flow control.
This maybe related to http://bugzilla.kernel.org/show_bug.cgi?id=6839
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
---
drivers/net/sky2.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
--- sky2.orig/drivers/net/sky2.c 2006-10-16 08:38:24.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-10-16 09:48:28.000000000 -0700
@@ -2850,6 +2850,14 @@
return 0;
}
+static void inline sky2_add_filter(u8 filter[8], const u8 *addr)
+{
+ u32 bit;
+
+ bit = ether_crc(ETH_ALEN, addr) & 63;
+ filter[bit >> 3] |= 1 << (bit & 7);
+}
+
static void sky2_set_multicast(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
@@ -2858,7 +2866,10 @@
struct dev_mc_list *list = dev->mc_list;
u16 reg;
u8 filter[8];
+ int rx_pause;
+ static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
+ rx_pause = (sky2->flow_status == FC_RX || sky2->flow_status == FC_BOTH);
memset(filter, 0, sizeof(filter));
reg = gma_read16(hw, port, GM_RX_CTRL);
@@ -2866,18 +2877,19 @@
if (dev->flags & IFF_PROMISC) /* promiscuous */
reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
- else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16) /* all multicast */
+ else if (dev->flags & IFF_ALLMULTI)
memset(filter, 0xff, sizeof(filter));
- else if (dev->mc_count == 0) /* no multicast */
+ else if (dev->mc_count == 0 && !rx_pause)
reg &= ~GM_RXCR_MCF_ENA;
else {
int i;
reg |= GM_RXCR_MCF_ENA;
- for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
- u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
- filter[bit / 8] |= 1 << (bit % 8);
- }
+ if (rx_pause)
+ sky2_add_filter(filter, pause_mc_addr);
+
+ for (i = 0; list && i < dev->mc_count; i++, list = list->next)
+ sky2_add_filter(filter, list->dmi_addr);
}
gma_write16(hw, port, GM_MC_ADDR_H1,
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/2] sky2: don't process pause frames in recveiver.
2006-10-11 21:22 ` [PATCH 10/10] sky2: version 1.9 Stephen Hemminger
2006-10-16 20:50 ` [PATCH 1/2] sky2: multicast pause frame receive Stephen Hemminger
@ 2006-10-16 20:52 ` Stephen Hemminger
1 sibling, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2006-10-16 20:52 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
This reverts earlier change that attempted to fix flow control; but was
broken.
Device needs to discard pause frames at the receive DMA engine, otherwise
the pause frames get received and passed up the stack!
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
---
drivers/net/sky2.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- sky2.orig/drivers/net/sky2.h 2006-10-16 09:44:46.000000000 -0700
+++ sky2/drivers/net/sky2.h 2006-10-16 09:50:07.000000000 -0700
@@ -1576,7 +1576,7 @@
GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
- GMR_FS_MII_ERR | GMR_FS_BAD_FC |
+ GMR_FS_MII_ERR | GMR_FS_GOOD_FC | GMR_FS_BAD_FC |
GMR_FS_UN_SIZE | GMR_FS_JABBER,
};
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2006-10-16 22:11 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-11 21:22 [PATCH 00/10] sky2: version 1.9 patches Stephen Hemminger
2006-10-11 21:22 ` [PATCH 01/10] sky2: MSI test is only a warning Stephen Hemminger
2006-10-11 21:22 ` [PATCH 02/10] sky2: turn of workaround timer Stephen Hemminger
2006-10-11 21:22 ` [PATCH 03/10] sky2: phy irq on shutdown Stephen Hemminger
2006-10-11 21:22 ` [PATCH 04/10] sky2: fiber pause bits Stephen Hemminger
2006-10-11 21:22 ` [PATCH 05/10] sky2: advertising register 16 bits Stephen Hemminger
2006-10-11 21:22 ` [PATCH 06/10] sky2: use duplex result bits Stephen Hemminger
2006-10-11 21:22 ` [PATCH 07/10] sky2: dont reset PHY twice Stephen Hemminger
2006-10-11 21:22 ` [PATCH 08/10] sky2: flow control setting fixes Stephen Hemminger
2006-10-11 21:22 ` [PATCH 09/10] sky2: no message on rx fifo overflow Stephen Hemminger
2006-10-11 21:22 ` [PATCH 10/10] sky2: version 1.9 Stephen Hemminger
2006-10-16 20:50 ` [PATCH 1/2] sky2: multicast pause frame receive Stephen Hemminger
2006-10-16 20:52 ` [PATCH 2/2] sky2: don't process pause frames in recveiver Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).