Here is a combined rollup of all the patches to sky2 that I intend
to release and call it 1.0. This includes the fixes for receive and transmit
hang, oversize packets, etc.
Patch against the current 2.6.16-rc4 mainline kernel.
diff -urNp -X dontdiff git-2.6/drivers/net/sky2.c sky2-1.0/drivers/net/sky2.c
--- git-2.6/drivers/net/sky2.c 2006-02-20 09:31:48.000000000 -0800
+++ sky2-1.0/drivers/net/sky2.c 2006-02-20 16:03:55.000000000 -0800
@@ -51,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "0.15"
+#define DRV_VERSION "1.0-rc1"
#define PFX DRV_NAME " "
/*
@@ -195,11 +195,11 @@ static int sky2_set_power_state(struct s
pr_debug("sky2_set_power_state %d\n", state);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control);
+ power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_PMC);
vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
(power_control & PCI_PM_CAP_PME_D3cold);
- pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL,
&power_control);
+ power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL);
power_control |= PCI_PM_CTRL_PME_STATUS;
power_control &= ~(PCI_PM_CTRL_STATE_MASK);
@@ -223,7 +223,7 @@ static int sky2_set_power_state(struct s
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
/* Turn off phy power saving */
- pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
/* looks like this XL is back asswards .. */
@@ -232,18 +232,28 @@ static int sky2_set_power_state(struct s
if (hw->ports > 1)
reg1 |= PCI_Y2_PHY2_COMA;
}
- pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
+ reg1 &= P_ASPM_CONTROL_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
+ sky2_pci_write32(hw, PCI_DEV_REG5, 0);
+ }
+
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+
break;
case PCI_D3hot:
case PCI_D3cold:
/* Turn on phy power saving */
- pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1);
+ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
else
reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
- pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
@@ -265,7 +275,7 @@ static int sky2_set_power_state(struct s
ret = -1;
}
- pci_write_config_byte(hw->pdev, hw->pm_cap + PCI_PM_CTRL,
power_control);
+ sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
return ret;
}
@@ -463,16 +473,31 @@ static void sky2_phy_init(struct sky2_hw
ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
}
- gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
+ /* apply fixes in PHY AFE */
+ gm_phy_write(hw, port, 22, 255);
+ /* increase differential signal amplitude in 10BASE-T */
+ gm_phy_write(hw, port, 24, 0xaa99);
+ gm_phy_write(hw, port, 23, 0x2011);
+
+ /* fix for IEEE A/B Symmetry failure in 1000BASE-T */
+ gm_phy_write(hw, port, 24, 0xa204);
+ gm_phy_write(hw, port, 23, 0x2002);
- if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
- /* turn on 100 Mbps LED (LED_LINK100) */
- ledover |= PHY_M_LED_MO_100(MO_LED_ON);
- }
+ /* set page register to 0 */
+ gm_phy_write(hw, port, 22, 0);
+ } else {
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
- if (ledover)
- gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+ if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed ==
SPEED_100) {
+ /* turn on 100 Mbps LED (LED_LINK100) */
+ ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+ }
+
+ if (ledover)
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+ }
/* Enable phy interrupt on auto-negotiation complete (or link up) */
if (sky2->autoneg == AUTONEG_ENABLE)
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
@@ -607,6 +632,9 @@ static void sky2_mac_init(struct sky2_hw
/* Flush Rx MAC FIFO on any flow control or error */
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
+ /* Truncate frames after mtu + vlan */
+ sky2_write16(hw, SK_REG(port, RX_GMF_TR_THR), sky2->rx_bufsize/8);
+
/* Set threshold to 0xa (64 bytes)
* ASF disabled so no need to do WA dev #4.30
*/
@@ -953,6 +981,12 @@ static int sky2_rx_start(struct sky2_por
sky2->rx_put = sky2->rx_next = 0;
sky2_qset(hw, rxq);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
+ /* MAC Rx RAM Read is controlled by hardware */
+ sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
+ }
+
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
rx_set_checksum(sky2);
@@ -1035,9 +1069,10 @@ static int sky2_up(struct net_device *de
RB_RST_SET);
sky2_qset(hw, txqaddr[port]);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U)
- sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0);
+ /* Set almost empty threshold */
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == 1)
+ sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0);
sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
TX_RING_SIZE - 1);
@@ -1680,7 +1715,7 @@ static void sky2_tx_timeout(struct net_d
/* Want receive buffer size to be multiple of 64 bits, and incl room for vlan
*/
static inline unsigned sky2_buf_size(int mtu)
{
- return roundup(mtu + ETH_HLEN + 4, 8);
+ return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8);
}
static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -1722,6 +1757,8 @@ static int sky2_change_mtu(struct net_de
gma_write16(hw, sky2->port, GM_SERIAL_MODE, mode);
+ sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize/8);
+
sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD);
err = sky2_rx_start(sky2);
@@ -1861,8 +1898,6 @@ static int sky2_poll(struct net_device *
u16 hwidx;
u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS };
- sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-
hwidx = sky2_read16(hw, STAT_PUT_IDX);
BUG_ON(hwidx >= STATUS_RING_SIZE);
rmb();
@@ -1945,13 +1980,12 @@ exit_loop:
sky2_tx_check(hw, 0, tx_done[0]);
sky2_tx_check(hw, 1, tx_done[1]);
- if (likely(work_done < to_do)) {
- /* need to restart TX timer */
- if (is_ec_a1(hw)) {
- sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
- sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
- }
+ if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ }
+ if (likely(work_done < to_do)) {
netif_rx_complete(dev0);
hw->intr_mask |= Y2_IS_STAT_BMU;
sky2_write32(hw, B0_IMSK, hw->intr_mask);
@@ -2017,13 +2051,13 @@ static void sky2_hw_intr(struct sky2_hw
if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
u16 pci_err;
- pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err);
+ pci_err = sky2_pci_read16(hw, PCI_STATUS);
if (net_ratelimit())
printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
pci_name(hw->pdev), pci_err);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- pci_write_config_word(hw->pdev, PCI_STATUS,
+ sky2_pci_write16(hw, PCI_STATUS,
pci_err | PCI_STATUS_ERROR_BITS);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
}
@@ -2032,7 +2066,7 @@ static void sky2_hw_intr(struct sky2_hw
/* PCI-Express uncorrectable Error occurred */
u32 pex_err;
- pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err);
+ pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT);
if (net_ratelimit())
printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
@@ -2040,7 +2074,7 @@ static void sky2_hw_intr(struct sky2_hw
/* clear the interrupt */
sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
+ sky2_pci_write32(hw, PEX_UNC_ERR_STAT,
0xffffffffUL);
sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
@@ -2107,6 +2141,14 @@ static irqreturn_t sky2_intr(int irq, vo
hw->intr_mask &= ~Y2_IS_STAT_BMU;
sky2_write32(hw, B0_IMSK, hw->intr_mask);
+ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
+ /* Force restart of coalescing timer */
+ if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_START) {
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP);
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+ }
+
if (likely(__netif_rx_schedule_prep(dev0))) {
prefetch(&hw->st_le[hw->st_idx]);
__netif_rx_schedule(dev0);
@@ -2170,7 +2212,7 @@ static int sky2_reset(struct sky2_hw *hw
{
u16 status;
u8 t8, pmd_type;
- int i, err;
+ int i;
sky2_write8(hw, B0_CTST, CS_RST_CLR);
@@ -2192,25 +2234,18 @@ static int sky2_reset(struct sky2_hw *hw
sky2_write8(hw, B0_CTST, CS_RST_CLR);
/* clear PCI errors, if any */
- err = pci_read_config_word(hw->pdev, PCI_STATUS, &status);
- if (err)
- goto pci_err;
+ status = sky2_pci_read16(hw, PCI_STATUS);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- err = pci_write_config_word(hw->pdev, PCI_STATUS,
- status | PCI_STATUS_ERROR_BITS);
- if (err)
- goto pci_err;
+ sky2_pci_write16(hw, PCI_STATUS, status | PCI_STATUS_ERROR_BITS);
+
sky2_write8(hw, B0_CTST, CS_MRST_CLR);
/* clear any PEX errors */
- if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) {
- err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
- 0xffffffffUL);
- if (err)
- goto pci_err;
- }
+ if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
+ sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL);
+
pmd_type = sky2_read8(hw, B2_PMD_TYP);
hw->copper = !(pmd_type == 'L' || pmd_type == 'S');
@@ -2309,8 +2344,7 @@ static int sky2_reset(struct sky2_hw *hw
sky2_write8(hw, STAT_FIFO_ISR_WM, 16);
sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000));
- sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100));
- sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20));
+ sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 7));
}
/* enable status unit */
@@ -2321,14 +2355,6 @@ static int sky2_reset(struct sky2_hw *hw
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
return 0;
-
-pci_err:
- /* This is to catch a BIOS bug workaround where
- * mmconfig table doesn't have other buses.
- */
- printk(KERN_ERR PFX "%s: can't access PCI config space\n",
- pci_name(hw->pdev));
- return err;
}
static u32 sky2_supported_modes(const struct sky2_hw *hw)
@@ -2852,11 +2878,11 @@ static int sky2_set_coalesce(struct net_
(ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq
> tmax))
return -EINVAL;
- if (ecmd->tx_max_coalesced_frames > 0xffff)
+ if (ecmd->tx_max_coalesced_frames >= TX_RING_SIZE-1)
return -EINVAL;
- if (ecmd->rx_max_coalesced_frames > 0xff)
+ if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING)
return -EINVAL;
- if (ecmd->rx_max_coalesced_frames_irq > 0xff)
+ if (ecmd->rx_max_coalesced_frames_irq >RX_MAX_PENDING)
return -EINVAL;
if (ecmd->tx_coalesce_usecs == 0)
@@ -3198,17 +3224,6 @@ static int __devinit sky2_probe(struct p
}
}
-#ifdef __BIG_ENDIAN
- /* byte swap descriptors in hardware */
- {
- u32 reg;
-
- pci_read_config_dword(pdev, PCI_DEV_REG2, ®);
- reg |= PCI_REV_DESC;
- pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
- }
-#endif
-
err = -ENOMEM;
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw) {
@@ -3227,6 +3242,17 @@ static int __devinit sky2_probe(struct p
}
hw->pm_cap = pm_cap;
+#ifdef __BIG_ENDIAN
+ /* byte swap descriptors in hardware */
+ {
+ u32 reg;
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG2);
+ reg |= PCI_REV_DESC;
+ sky2_pci_write32(hw, PCI_DEV_REG2, reg);
+ }
+#endif
+
/* ring for status responses */
hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
&hw->st_dma);
diff -urNp -X dontdiff git-2.6/drivers/net/sky2.h sky2-1.0/drivers/net/sky2.h
--- git-2.6/drivers/net/sky2.h 2006-02-07 11:30:37.000000000 -0800
+++ sky2-1.0/drivers/net/sky2.h 2006-02-20 12:12:10.000000000 -0800
@@ -5,14 +5,22 @@
#define _SKY2_H
/* PCI config registers */
-#define PCI_DEV_REG1 0x40
-#define PCI_DEV_REG2 0x44
-#define PCI_DEV_STATUS 0x7c
-#define PCI_OS_PCI_X (1<<26)
-
-#define PEX_LNK_STAT 0xf2
-#define PEX_UNC_ERR_STAT 0x104
-#define PEX_DEV_CTRL 0xe8
+enum {
+ PCI_DEV_REG1 = 0x40,
+ PCI_DEV_REG2 = 0x44,
+ PCI_DEV_STATUS = 0x7c,
+ PCI_DEV_REG3 = 0x80,
+ PCI_DEV_REG4 = 0x84,
+ PCI_DEV_REG5 = 0x88,
+};
+
+enum {
+ PEX_DEV_CAP = 0xe4,
+ PEX_DEV_CTRL = 0xe8,
+ PEX_DEV_STA = 0xea,
+ PEX_LNK_STAT = 0xf2,
+ PEX_UNC_ERR_STAT= 0x104,
+};
/* Yukon-2 */
enum pci_dev_reg_1 {
@@ -37,6 +45,25 @@ enum pci_dev_reg_2 {
PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */
};
+/* PCI_OUR_REG_4 32 bit Our Register 4 (Yukon-ECU only) */
+enum pci_dev_reg_4 {
+ /* (Link Training & Status State
Machine) */
+ P_TIMER_VALUE_MSK = 0xffL<<16, /* Bit 23..16: Timer Value
Mask */
+ /* (Active State Power Management) */
+ P_FORCE_ASPM_REQUEST = 1<<15, /* Force ASPM Request (A1 only) */
+ P_ASPM_GPHY_LINK_DOWN = 1<<14, /* GPHY Link Down (A1 only) */
+ P_ASPM_INT_FIFO_EMPTY = 1<<13, /* Internal FIFO Empty (A1 only) */
+ P_ASPM_CLKRUN_REQUEST = 1<<12, /* CLKRUN Request (A1 only) */
+
+ P_ASPM_FORCE_CLKREQ_ENA = 1<<4, /* Force CLKREQ Enable (A1b only) */
+ P_ASPM_CLKREQ_PAD_CTL = 1<<3, /* CLKREQ PAD Control (A1 only) */
+ P_ASPM_A1_MODE_SELECT = 1<<2, /* A1 Mode Select (A1 only) */
+ P_CLK_GATE_PEX_UNIT_ENA = 1<<1, /* Enable Gate PEX Unit Clock */
+ P_CLK_GATE_ROOT_COR_ENA = 1<<0, /* Enable Gate Root Core Clock */
+ P_ASPM_CONTROL_MSK = P_FORCE_ASPM_REQUEST | P_ASPM_GPHY_LINK_DOWN
+ | P_ASPM_CLKRUN_REQUEST |
P_ASPM_INT_FIFO_EMPTY,
+};
+
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -507,6 +534,16 @@ enum {
};
#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
+/* Q_F 32 bit Flag Register */
+enum {
+ F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
+ F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
+ F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
+ F_WM_REACHED = 1<<25, /* Watermark reached */
+ F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */
+ F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
+ F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
+};
/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
enum {
@@ -909,10 +946,12 @@ enum {
PHY_BCOM_ID1_C0 = 0x6044,
PHY_BCOM_ID1_C5 = 0x6047,
- PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
+ PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */
- PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
- PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
+ PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
+ PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
+ PHY_MARV_ID1_FE = 0x0C83, /* Yukon-FE (PHY 88E3082 Rev.A1) */
+ PHY_MARV_ID1_ECU= 0x0CB0, /* Yukon-ECU (PHY 88E1149 Rev.B2?) */
};
/* Advertisement register bits */
@@ -1912,4 +1951,25 @@ static inline void gma_set_addr(struct s
gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
}
+
+/* PCI config space access */
+static inline u32 sky2_pci_read32(const struct sky2_hw *hw, unsigned reg)
+{
+ return sky2_read32(hw, Y2_CFG_SPC + reg);
+}
+
+static inline u16 sky2_pci_read16(const struct sky2_hw *hw, unsigned reg)
+{
+ return sky2_read16(hw, Y2_CFG_SPC + reg);
+}
+
+static inline void sky2_pci_write32(struct sky2_hw *hw, unsigned reg, u32 val)
+{
+ sky2_write32(hw, Y2_CFG_SPC + reg, val);
+}
+
+static inline void sky2_pci_write16(struct sky2_hw *hw, unsigned reg, u16 val)
+{
+ sky2_write16(hw, Y2_CFG_SPC + reg, val);
+}
#endif
-
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