* [PATCH 3/6] sky2: reorganize chip revision features
2007-09-19 22:36 [PATCH 0/6] sky2: version 1.18 (rev2) Stephen Hemminger
@ 2007-09-19 22:36 ` Stephen Hemminger
2007-09-19 23:27 ` Rick Jones
0 siblings, 1 reply; 9+ messages in thread
From: Stephen Hemminger @ 2007-09-19 22:36 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
[-- Attachment #1: sky2-flags.patch --]
[-- Type: text/plain, Size: 11779 bytes --]
This patch should cause no functional changes in driver behaviour.
There are (too) many revisions of the Yukon 2 chip now. Instead of
adding more conditionals based on chip revision; rerganize into a
set of feature flags so adding new versions is less problematic.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 09:19:35.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 09:57:41.000000000 -0700
@@ -217,8 +217,7 @@ static void sky2_power_on(struct sky2_hw
else
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
- hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
u32 reg;
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
@@ -311,10 +310,8 @@ static void sky2_phy_init(struct sky2_hw
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
- if (sky2->autoneg == AUTONEG_ENABLE
- && !(hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX)) {
+ if (sky2->autoneg == AUTONEG_ENABLE &&
+ !(hw->flags & SKY2_HW_NEWER_PHY)) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
@@ -346,9 +343,7 @@ static void sky2_phy_init(struct sky2_hw
/* downshift on PHY 88E1112 and 88E1149 is changed */
if (sky2->autoneg == AUTONEG_ENABLE
- && (hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX)) {
+ && (hw->flags & SKY2_HW_NEWER_PHY)) {
/* set downshift counter to 3x and enable downshift */
ctrl &= ~PHY_M_PC_DSC_MSK;
ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
@@ -364,7 +359,7 @@ static void sky2_phy_init(struct sky2_hw
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
/* special setup for PHY 88E1112 Fiber */
- if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) {
+ if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) {
pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
/* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
@@ -788,7 +783,7 @@ static void sky2_mac_init(struct sky2_hw
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (!(hw->flags & SKY2_HW_RAMBUFFER)) {
sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
@@ -967,19 +962,15 @@ static void sky2_rx_unmap_skb(struct pci
*/
static void rx_set_checksum(struct sky2_port *sky2)
{
- struct sky2_rx_le *le;
+ struct sky2_rx_le *le = sky2_next_rx(sky2);
- if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
- le = sky2_next_rx(sky2);
- le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
- le->ctrl = 0;
- le->opcode = OP_TCPSTART | HW_OWNER;
-
- sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[sky2->port], Q_CSR),
- sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
- }
+ le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
}
/*
@@ -1175,7 +1166,8 @@ static int sky2_rx_start(struct sky2_por
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
- rx_set_checksum(sky2);
+ if (!(hw->flags & SKY2_HW_NEW_LE))
+ rx_set_checksum(sky2);
/* Space needed for frame data + headers rounded up */
size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
@@ -1246,7 +1238,7 @@ static int sky2_up(struct net_device *de
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
- u32 ramsize, imask;
+ u32 imask;
int cap, err = -ENOMEM;
struct net_device *otherdev = hw->dev[sky2->port^1];
@@ -1301,13 +1293,13 @@ static int sky2_up(struct net_device *de
sky2_mac_init(hw, port);
- /* Register is number of 4K blocks on internal RAM buffer. */
- ramsize = sky2_read8(hw, B2_E_0) * 4;
- printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize);
-
- if (ramsize > 0) {
+ if (hw->flags & SKY2_HW_RAMBUFFER) {
+ /* Register is number of 4K blocks on internal RAM buffer. */
+ u32 ramsize = sky2_read8(hw, B2_E_0) * 4;
u32 rxspace;
+ printk(KERN_DEBUG PFX "%s: ram buffer %dK\n", dev->name, ramsize);
+
if (ramsize < 16)
rxspace = ramsize / 2;
else
@@ -1436,13 +1428,15 @@ static int sky2_xmit_frame(struct sk_buf
/* Check for TCP Segmentation Offload */
mss = skb_shinfo(skb)->gso_size;
if (mss != 0) {
- if (hw->chip_id != CHIP_ID_YUKON_EX)
+
+ if (!(hw->flags & SKY2_HW_NEW_LE))
mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
if (mss != sky2->tx_last_mss) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(mss);
- if (hw->chip_id == CHIP_ID_YUKON_EX)
+
+ if (hw->flags & SKY2_HW_NEW_LE)
le->opcode = OP_MSS | HW_OWNER;
else
le->opcode = OP_LRGLEN | HW_OWNER;
@@ -1468,8 +1462,7 @@ static int sky2_xmit_frame(struct sk_buf
/* Handle TCP checksum offload */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
/* On Yukon EX (some versions) encoding change. */
- if (hw->chip_id == CHIP_ID_YUKON_EX
- && hw->chip_rev != CHIP_REV_YU_EX_B0)
+ if (hw->flags & SKY2_HW_AUTO_TX_SUM)
ctrl |= CALSUM; /* auto checksum */
else {
const unsigned offset = skb_transport_offset(skb);
@@ -1708,7 +1701,7 @@ static int sky2_down(struct net_device *
static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
{
- if (!sky2_is_copper(hw))
+ if (hw->flags & SKY2_HW_FIBRE_PHY)
return SPEED_1000;
if (hw->chip_id == CHIP_ID_YUKON_FE)
@@ -1753,9 +1746,7 @@ static void sky2_link_up(struct sky2_por
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
- if (hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->flags & SKY2_HW_NEWER_PHY) {
u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */
@@ -1847,7 +1838,7 @@ static int sky2_autoneg_done(struct sky2
/* Since the pause result bits seem to in different positions on
* different chips. look at registers.
*/
- if (!sky2_is_copper(hw)) {
+ if (hw->flags & SKY2_HW_FIBRE_PHY) {
/* Shift for bits in fiber PHY */
advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
@@ -2593,23 +2584,56 @@ static int __devinit sky2_init(struct sk
sky2_write8(hw, B0_CTST, CS_RST_CLR);
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
- if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
+ hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+
+ switch(hw->chip_id) {
+ case CHIP_ID_YUKON_XL:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_RAMBUFFER;
+ break;
+
+ case CHIP_ID_YUKON_EC_U:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_EX:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_ADV_POWER_CTL;
+
+ /* New transmit checksum */
+ if (hw->chip_rev != CHIP_REV_YU_EX_B0)
+ hw->flags |= SKY2_HW_AUTO_TX_SUM;
+ break;
+
+ case CHIP_ID_YUKON_EC:
+ /* This rev is really old, and requires untested workarounds */
+ if (hw->chip_rev == CHIP_REV_YU_EC_A1) {
+ dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n");
+ return -EOPNOTSUPP;
+ }
+ hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RAMBUFFER;
+ break;
+
+ case CHIP_ID_YUKON_FE:
+ hw->flags = SKY2_HW_RAMBUFFER;
+ break;
+
+ default:
dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
hw->chip_id);
return -EOPNOTSUPP;
}
- hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+ hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
+ if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P')
+ hw->flags |= SKY2_HW_FIBRE_PHY;
- /* This rev is really old, and requires untested workarounds */
- if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) {
- dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n",
- yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
- hw->chip_id, hw->chip_rev);
- return -EOPNOTSUPP;
- }
- hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
hw->ports = 1;
t8 = sky2_read8(hw, B2_Y2_HW_RES);
if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
@@ -2821,7 +2845,7 @@ static u32 sky2_supported_modes(const st
| SUPPORTED_100baseT_Full
| SUPPORTED_Autoneg | SUPPORTED_TP;
- if (hw->chip_id != CHIP_ID_YUKON_FE)
+ if (hw->flags & SKY2_HW_GIGABIT)
modes |= SUPPORTED_1000baseT_Half
| SUPPORTED_1000baseT_Full;
return modes;
@@ -3851,7 +3875,7 @@ static irqreturn_t __devinit sky2_test_i
return IRQ_NONE;
if (status & Y2_IS_IRQ_SW) {
- hw->msi = 1;
+ hw->flags |= SKY2_HW_USE_MSI;
wake_up(&hw->msi_wait);
sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
}
@@ -3879,9 +3903,9 @@ static int __devinit sky2_test_msi(struc
sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
sky2_read8(hw, B0_CTST);
- wait_event_timeout(hw->msi_wait, hw->msi, HZ/10);
+ wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10);
- if (!hw->msi) {
+ if (!(hw->flags & SKY2_HW_USE_MSI)) {
/* MSI test failed, go back to INTx mode */
dev_info(&pdev->dev, "No interrupt generated using MSI, "
"switching to INTx mode.\n");
@@ -4014,7 +4038,8 @@ static int __devinit sky2_probe(struct p
goto err_out_free_netdev;
}
- err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED,
+ err = request_irq(pdev->irq, sky2_intr,
+ (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
dev->name, hw);
if (err) {
dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
@@ -4047,7 +4072,7 @@ static int __devinit sky2_probe(struct p
return 0;
err_out_unregister:
- if (hw->msi)
+ if (hw->flags & SKY2_HW_USE_MSI)
pci_disable_msi(pdev);
unregister_netdev(dev);
err_out_free_netdev:
@@ -4096,7 +4121,7 @@ static void __devexit sky2_remove(struct
sky2_read8(hw, B0_CTST);
free_irq(pdev->irq, hw);
- if (hw->msi)
+ if (hw->flags & SKY2_HW_USE_MSI)
pci_disable_msi(pdev);
pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
pci_release_regions(pdev);
--- a/drivers/net/sky2.h 2007-09-19 09:18:50.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-19 09:19:40.000000000 -0700
@@ -2040,6 +2040,15 @@ struct sky2_hw {
void __iomem *regs;
struct pci_dev *pdev;
struct net_device *dev[2];
+ unsigned long flags;
+#define SKY2_HW_USE_MSI 0x00000001
+#define SKY2_HW_FIBRE_PHY 0x00000002
+#define SKY2_HW_GIGABIT 0x00000004
+#define SKY2_HW_NEWER_PHY 0x00000008
+#define SKY2_HW_RAMBUFFER 0x00000010 /* chip has RAM FIFO */
+#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */
+#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */
+#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
u8 chip_id;
u8 chip_rev;
@@ -2053,13 +2062,12 @@ struct sky2_hw {
struct timer_list watchdog_timer;
struct work_struct restart_work;
- int msi;
wait_queue_head_t msi_wait;
};
static inline int sky2_is_copper(const struct sky2_hw *hw)
{
- return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P');
+ return !(hw->flags & SKY2_HW_FIBRE_PHY);
}
/* Register accessor for memory mapped device */
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/6] sky2: reorganize chip revision features
2007-09-19 22:36 ` [PATCH 3/6] sky2: reorganize chip revision features Stephen Hemminger
@ 2007-09-19 23:27 ` Rick Jones
0 siblings, 0 replies; 9+ messages in thread
From: Rick Jones @ 2007-09-19 23:27 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Jeff Garzk, netdev
Stephen Hemminger wrote:
> This patch should cause no functional changes in driver behaviour.
> There are (too) many revisions of the Yukon 2 chip now. Instead of
> adding more conditionals based on chip revision; rerganize into a
> set of feature flags so adding new versions is less problematic.
> @@ -311,10 +310,8 @@ static void sky2_phy_init(struct sky2_hw
> struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
> u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
>
> - if (sky2->autoneg == AUTONEG_ENABLE
> - && !(hw->chip_id == CHIP_ID_YUKON_XL
> - || hw->chip_id == CHIP_ID_YUKON_EC_U
> - || hw->chip_id == CHIP_ID_YUKON_EX)) {
> + if (sky2->autoneg == AUTONEG_ENABLE &&
> + !(hw->flags & SKY2_HW_NEWER_PHY)) {
Will something like SKY2_HW_NEWER_PHY age well? Won't that leave things
vulnerable to needing a SKY2_HW_NEWER_NEWER_PHY?
> @@ -1436,13 +1428,15 @@ static int sky2_xmit_frame(struct sk_buf
> /* Check for TCP Segmentation Offload */
> mss = skb_shinfo(skb)->gso_size;
> if (mss != 0) {
> - if (hw->chip_id != CHIP_ID_YUKON_EX)
> +
> + if (!(hw->flags & SKY2_HW_NEW_LE))
> mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
Might the same thing apply with SKY2_HW_NEW_LE?
rick jones
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 0/6] sky2: merged for netdev-2.6 upstream
@ 2007-09-20 5:05 Stephen Hemminger
2007-09-20 5:06 ` [PATCH 1/6] sky2: fix VLAN receive processing Stephen Hemminger
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: Stephen Hemminger @ 2007-09-20 5:05 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
Basically, same patches as earlier, but these are for 2.6.24
(via netdev-2.6 upstream branch).
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/6] sky2: fix VLAN receive processing
2007-09-20 5:05 [PATCH 0/6] sky2: merged for netdev-2.6 upstream Stephen Hemminger
@ 2007-09-20 5:06 ` Stephen Hemminger
2007-09-20 5:06 ` [PATCH 2/6] sky2: ethtool speed report bug Stephen Hemminger
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2007-09-20 5:06 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev, Pierre-Yves Ritschard
[-- Attachment #1: sky2-vlan-len.patch --]
[-- Type: text/plain, Size: 2111 bytes --]
The length check for truncated frames was not correctly handling
the case where VLAN acceleration had already read the tag.
Also, the Yukon EX has some features that use high bit of status
as security tag.
Signed-off-by: Pierre-Yves Ritschard <pyr@spootnik.org>
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 21:35:38.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 21:35:53.000000000 -0700
@@ -2146,6 +2146,13 @@ static struct sk_buff *sky2_receive(stru
struct sky2_port *sky2 = netdev_priv(dev);
struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next;
struct sk_buff *skb = NULL;
+ u16 count = (status & GMR_FS_LEN) >> 16;
+
+#ifdef SKY2_VLAN_TAG_USED
+ /* Account for vlan tag */
+ if (sky2->vlgrp && (status & GMR_FS_VLAN))
+ count -= VLAN_HLEN;
+#endif
if (unlikely(netif_msg_rx_status(sky2)))
printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n",
@@ -2160,7 +2167,8 @@ static struct sk_buff *sky2_receive(stru
if (!(status & GMR_FS_RX_OK))
goto resubmit;
- if (status >> 16 != length)
+ /* if length reported by DMA does not match PHY, packet was truncated */
+ if (length != count)
goto len_mismatch;
if (length < copybreak)
@@ -2176,6 +2184,10 @@ len_mismatch:
/* Truncation of overlength packets
causes PHY length to not match MAC length */
++sky2->net_stats.rx_length_errors;
+ if (netif_msg_rx_err(sky2) && net_ratelimit())
+ pr_info(PFX "%s: rx length mismatch: length %d status %#x\n",
+ dev->name, length, status);
+ goto resubmit;
error:
++sky2->net_stats.rx_errors;
--- a/drivers/net/sky2.h 2007-09-19 21:35:38.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-19 21:35:53.000000000 -0700
@@ -1633,7 +1633,7 @@ enum {
/* Receive Frame Status Encoding */
enum {
- GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */
+ GMR_FS_LEN = 0x7fff<<16, /* Bit 30..16: Rx Frame Length */
GMR_FS_VLAN = 1<<13, /* VLAN Packet */
GMR_FS_JABBER = 1<<12, /* Jabber Packet */
GMR_FS_UN_SIZE = 1<<11, /* Undersize Packet */
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/6] sky2: ethtool speed report bug
2007-09-20 5:05 [PATCH 0/6] sky2: merged for netdev-2.6 upstream Stephen Hemminger
2007-09-20 5:06 ` [PATCH 1/6] sky2: fix VLAN receive processing Stephen Hemminger
@ 2007-09-20 5:06 ` Stephen Hemminger
2007-09-20 5:06 ` [PATCH 3/6] sky2: reorganize chip revision features Stephen Hemminger
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2007-09-20 5:06 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
[-- Attachment #1: sky2-ethtool-100mbit.patch --]
[-- Type: text/plain, Size: 874 bytes --]
On 100mbit versions, the driver always reports gigabit speed
available. The correct modes are already computed, then overwritten.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 21:35:53.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 21:35:57.000000000 -0700
@@ -2880,13 +2880,6 @@ static int sky2_get_settings(struct net_
ecmd->supported = sky2_supported_modes(hw);
ecmd->phy_address = PHY_ADDR_MARV;
if (sky2_is_copper(hw)) {
- ecmd->supported = SUPPORTED_10baseT_Half
- | SUPPORTED_10baseT_Full
- | SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full
- | SUPPORTED_1000baseT_Half
- | SUPPORTED_1000baseT_Full
- | SUPPORTED_Autoneg | SUPPORTED_TP;
ecmd->port = PORT_TP;
ecmd->speed = sky2->speed;
} else {
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/6] sky2: reorganize chip revision features
2007-09-20 5:05 [PATCH 0/6] sky2: merged for netdev-2.6 upstream Stephen Hemminger
2007-09-20 5:06 ` [PATCH 1/6] sky2: fix VLAN receive processing Stephen Hemminger
2007-09-20 5:06 ` [PATCH 2/6] sky2: ethtool speed report bug Stephen Hemminger
@ 2007-09-20 5:06 ` Stephen Hemminger
2007-09-20 5:06 ` [PATCH 4/6] sky2: fe+ chip support Stephen Hemminger
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2007-09-20 5:06 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
[-- Attachment #1: sky2-flags.patch --]
[-- Type: text/plain, Size: 11746 bytes --]
This patch should cause no functional changes in driver behaviour.
There are (too) many revisions of the Yukon 2 chip now. Instead of
adding more conditionals based on chip revision; rerganize into a
set of feature flags so adding new versions is less problematic.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 21:57:42.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 21:57:59.000000000 -0700
@@ -222,8 +222,7 @@ static void sky2_power_on(struct sky2_hw
else
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
- hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
struct pci_dev *pdev = hw->pdev;
u32 reg;
@@ -317,10 +316,8 @@ static void sky2_phy_init(struct sky2_hw
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
- if (sky2->autoneg == AUTONEG_ENABLE
- && !(hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX)) {
+ if (sky2->autoneg == AUTONEG_ENABLE &&
+ !(hw->flags & SKY2_HW_NEWER_PHY)) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
@@ -353,9 +350,7 @@ static void sky2_phy_init(struct sky2_hw
/* downshift on PHY 88E1112 and 88E1149 is changed */
if (sky2->autoneg == AUTONEG_ENABLE
- && (hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX)) {
+ && (hw->flags & SKY2_HW_NEWER_PHY)) {
/* set downshift counter to 3x and enable downshift */
ctrl &= ~PHY_M_PC_DSC_MSK;
ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
@@ -371,7 +366,7 @@ static void sky2_phy_init(struct sky2_hw
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
/* special setup for PHY 88E1112 Fiber */
- if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) {
+ if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) {
pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
/* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
@@ -815,7 +810,7 @@ static void sky2_mac_init(struct sky2_hw
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (!(hw->flags & SKY2_HW_RAMBUFFER)) {
sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
@@ -994,19 +989,15 @@ static void sky2_rx_unmap_skb(struct pci
*/
static void rx_set_checksum(struct sky2_port *sky2)
{
- struct sky2_rx_le *le;
+ struct sky2_rx_le *le = sky2_next_rx(sky2);
- if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
- le = sky2_next_rx(sky2);
- le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
- le->ctrl = 0;
- le->opcode = OP_TCPSTART | HW_OWNER;
-
- sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[sky2->port], Q_CSR),
- sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
- }
+ le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
}
/*
@@ -1202,7 +1193,8 @@ static int sky2_rx_start(struct sky2_por
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
- rx_set_checksum(sky2);
+ if (!(hw->flags & SKY2_HW_NEW_LE))
+ rx_set_checksum(sky2);
/* Space needed for frame data + headers rounded up */
size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
@@ -1273,7 +1265,7 @@ static int sky2_up(struct net_device *de
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
- u32 ramsize, imask;
+ u32 imask;
int cap, err = -ENOMEM;
struct net_device *otherdev = hw->dev[sky2->port^1];
@@ -1328,13 +1320,13 @@ static int sky2_up(struct net_device *de
sky2_mac_init(hw, port);
- /* Register is number of 4K blocks on internal RAM buffer. */
- ramsize = sky2_read8(hw, B2_E_0) * 4;
- printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize);
-
- if (ramsize > 0) {
+ if (hw->flags & SKY2_HW_RAMBUFFER) {
+ /* Register is number of 4K blocks on internal RAM buffer. */
+ u32 ramsize = sky2_read8(hw, B2_E_0) * 4;
u32 rxspace;
+ printk(KERN_DEBUG PFX "%s: ram buffer %dK\n", dev->name, ramsize);
+
if (ramsize < 16)
rxspace = ramsize / 2;
else
@@ -1467,13 +1459,15 @@ static int sky2_xmit_frame(struct sk_buf
/* Check for TCP Segmentation Offload */
mss = skb_shinfo(skb)->gso_size;
if (mss != 0) {
- if (hw->chip_id != CHIP_ID_YUKON_EX)
+
+ if (!(hw->flags & SKY2_HW_NEW_LE))
mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
if (mss != sky2->tx_last_mss) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(mss);
- if (hw->chip_id == CHIP_ID_YUKON_EX)
+
+ if (hw->flags & SKY2_HW_NEW_LE)
le->opcode = OP_MSS | HW_OWNER;
else
le->opcode = OP_LRGLEN | HW_OWNER;
@@ -1499,8 +1493,7 @@ static int sky2_xmit_frame(struct sk_buf
/* Handle TCP checksum offload */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
/* On Yukon EX (some versions) encoding change. */
- if (hw->chip_id == CHIP_ID_YUKON_EX
- && hw->chip_rev != CHIP_REV_YU_EX_B0)
+ if (hw->flags & SKY2_HW_AUTO_TX_SUM)
ctrl |= CALSUM; /* auto checksum */
else {
const unsigned offset = skb_transport_offset(skb);
@@ -1741,7 +1734,7 @@ static int sky2_down(struct net_device *
static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
{
- if (!sky2_is_copper(hw))
+ if (hw->flags & SKY2_HW_FIBRE_PHY)
return SPEED_1000;
if (!sky2_is_gigabit(hw)) {
@@ -1790,9 +1783,7 @@ static void sky2_link_up(struct sky2_por
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
- if (hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->flags & SKY2_HW_NEWER_PHY) {
u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */
@@ -1884,7 +1875,7 @@ static int sky2_autoneg_done(struct sky2
/* Since the pause result bits seem to in different positions on
* different chips. look at registers.
*/
- if (!sky2_is_copper(hw)) {
+ if (hw->flags & SKY2_HW_FIBRE_PHY) {
/* Shift for bits in fiber PHY */
advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
@@ -2627,24 +2618,55 @@ static int __devinit sky2_init(struct sk
sky2_write8(hw, B0_CTST, CS_RST_CLR);
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
- if (hw->chip_id < CHIP_ID_YUKON_XL ||
- hw->chip_id > CHIP_ID_YUKON_FE_P) {
- dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
- hw->chip_id);
- return -EOPNOTSUPP;
- }
-
hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
- /* This rev is really old, and requires untested workarounds */
- if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) {
- dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n",
- yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
- hw->chip_id, hw->chip_rev);
+ switch(hw->chip_id) {
+ case CHIP_ID_YUKON_XL:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_RAMBUFFER;
+ break;
+
+ case CHIP_ID_YUKON_EC_U:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_EX:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_ADV_POWER_CTL;
+
+ /* New transmit checksum */
+ if (hw->chip_rev != CHIP_REV_YU_EX_B0)
+ hw->flags |= SKY2_HW_AUTO_TX_SUM;
+ break;
+
+ case CHIP_ID_YUKON_EC:
+ /* This rev is really old, and requires untested workarounds */
+ if (hw->chip_rev == CHIP_REV_YU_EC_A1) {
+ dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n");
+ return -EOPNOTSUPP;
+ }
+ hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RAMBUFFER;
+ break;
+
+ case CHIP_ID_YUKON_FE:
+ hw->flags = SKY2_HW_RAMBUFFER;
+ break;
+
+ default:
+ dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
+ hw->chip_id);
return -EOPNOTSUPP;
}
hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
+ if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P')
+ hw->flags |= SKY2_HW_FIBRE_PHY;
+
hw->ports = 1;
t8 = sky2_read8(hw, B2_Y2_HW_RES);
if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
@@ -2860,7 +2882,7 @@ static u32 sky2_supported_modes(const st
| SUPPORTED_100baseT_Full
| SUPPORTED_Autoneg | SUPPORTED_TP;
- if (hw->chip_id != CHIP_ID_YUKON_FE)
+ if (hw->flags & SKY2_HW_GIGABIT)
modes |= SUPPORTED_1000baseT_Half
| SUPPORTED_1000baseT_Full;
return modes;
@@ -3880,7 +3902,7 @@ static irqreturn_t __devinit sky2_test_i
return IRQ_NONE;
if (status & Y2_IS_IRQ_SW) {
- hw->msi = 1;
+ hw->flags |= SKY2_HW_USE_MSI;
wake_up(&hw->msi_wait);
sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
}
@@ -3908,9 +3930,9 @@ static int __devinit sky2_test_msi(struc
sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
sky2_read8(hw, B0_CTST);
- wait_event_timeout(hw->msi_wait, hw->msi, HZ/10);
+ wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10);
- if (!hw->msi) {
+ if (!(hw->flags & SKY2_HW_USE_MSI)) {
/* MSI test failed, go back to INTx mode */
dev_info(&pdev->dev, "No interrupt generated using MSI, "
"switching to INTx mode.\n");
@@ -4043,7 +4065,8 @@ static int __devinit sky2_probe(struct p
goto err_out_free_netdev;
}
- err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED,
+ err = request_irq(pdev->irq, sky2_intr,
+ (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
dev->name, hw);
if (err) {
dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
@@ -4076,7 +4099,7 @@ static int __devinit sky2_probe(struct p
return 0;
err_out_unregister:
- if (hw->msi)
+ if (hw->flags & SKY2_HW_USE_MSI)
pci_disable_msi(pdev);
unregister_netdev(dev);
err_out_free_netdev:
@@ -4125,7 +4148,7 @@ static void __devexit sky2_remove(struct
sky2_read8(hw, B0_CTST);
free_irq(pdev->irq, hw);
- if (hw->msi)
+ if (hw->flags & SKY2_HW_USE_MSI)
pci_disable_msi(pdev);
pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
pci_release_regions(pdev);
--- a/drivers/net/sky2.h 2007-09-19 21:57:42.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-19 21:57:42.000000000 -0700
@@ -2028,6 +2028,15 @@ struct sky2_hw {
struct pci_dev *pdev;
struct napi_struct napi;
struct net_device *dev[2];
+ unsigned long flags;
+#define SKY2_HW_USE_MSI 0x00000001
+#define SKY2_HW_FIBRE_PHY 0x00000002
+#define SKY2_HW_GIGABIT 0x00000004
+#define SKY2_HW_NEWER_PHY 0x00000008
+#define SKY2_HW_RAMBUFFER 0x00000010 /* chip has RAM FIFO */
+#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */
+#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */
+#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
u8 chip_id;
u8 chip_rev;
@@ -2041,13 +2050,12 @@ struct sky2_hw {
struct timer_list watchdog_timer;
struct work_struct restart_work;
- int msi;
wait_queue_head_t msi_wait;
};
static inline int sky2_is_copper(const struct sky2_hw *hw)
{
- return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P');
+ return !(hw->flags & SKY2_HW_FIBRE_PHY);
}
static inline int sky2_is_gigabit(const struct sky2_hw *hw)
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/6] sky2: fe+ chip support
2007-09-20 5:05 [PATCH 0/6] sky2: merged for netdev-2.6 upstream Stephen Hemminger
` (2 preceding siblings ...)
2007-09-20 5:06 ` [PATCH 3/6] sky2: reorganize chip revision features Stephen Hemminger
@ 2007-09-20 5:06 ` Stephen Hemminger
2007-09-20 5:06 ` [PATCH 5/6] sky2: receive FIFO checking Stephen Hemminger
2007-09-20 5:06 ` [PATCH 6/6] sky2: version 1.18 Stephen Hemminger
5 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2007-09-20 5:06 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
[-- Attachment #1: sky2-fe-p.patch --]
[-- Type: text/plain, Size: 8482 bytes --]
Modifications to support for Yukon FE plus chip.
Earlier code was speculative, this is tested on hardware evaluation boards.
This version of the patch is for 2.6.23. It supersedes
the two previous patches that are sitting in netdev-2.6 (upstream branch).
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 21:57:59.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 21:58:08.000000000 -0700
@@ -119,7 +119,7 @@ static const struct pci_device_id sky2_i
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88E8033 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */
@@ -337,8 +337,7 @@ static void sky2_phy_init(struct sky2_hw
ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
if (sky2_is_copper(hw)) {
- if (hw->chip_id == CHIP_ID_YUKON_FE ||
- hw->chip_id == CHIP_ID_YUKON_FE_P) {
+ if (!(hw->flags & SKY2_HW_GIGABIT)) {
/* enable automatic crossover */
ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
} else {
@@ -457,7 +456,7 @@ static void sky2_phy_init(struct sky2_hw
gma_write16(hw, port, GM_GP_CTRL, reg);
- if (sky2_is_gigabit(hw))
+ if (hw->flags & SKY2_HW_GIGABIT)
gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
@@ -483,11 +482,12 @@ static void sky2_phy_init(struct sky2_hw
case CHIP_ID_YUKON_FE_P:
/* Enable Link Partner Next Page */
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
ctrl |= PHY_M_PC_ENA_LIP_NP;
/* disable Energy Detect and enable scrambler */
ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB);
- gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
/* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */
ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) |
@@ -691,25 +691,25 @@ static void sky2_wol_init(struct sky2_po
static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
{
- if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+ struct net_device *dev = hw->dev[port];
+
+ if (dev->mtu <= ETH_DATA_LEN)
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_STFW_ENA |
- (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
- } else {
- if (hw->dev[port]->mtu > ETH_DATA_LEN) {
- /* set Tx GMAC FIFO Almost Empty Threshold */
- sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
- (ECU_JUMBO_WM << 16) | ECU_AE_THR);
-
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_ENA | TX_STFW_DIS);
-
- /* Can't do offload because of lack of store/forward */
- hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
- | NETIF_F_ALL_CSUM);
- } else
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_DIS | TX_STFW_ENA);
+ TX_JUMBO_DIS | TX_STFW_ENA);
+
+ else if (hw->chip_id != CHIP_ID_YUKON_EC_U)
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_STFW_ENA | TX_JUMBO_ENA);
+ else {
+ /* set Tx GMAC FIFO Almost Empty Threshold */
+ sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+ (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_ENA | TX_STFW_DIS);
+
+ /* Can't do offload because of lack of store/forward */
+ dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM);
}
}
@@ -795,7 +795,8 @@ static void sky2_mac_init(struct sky2_hw
/* Configure Rx MAC FIFO */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
- if (hw->chip_id == CHIP_ID_YUKON_EX)
+ if (hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
rx_reg |= GMF_RX_OVER_ON;
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg);
@@ -804,7 +805,12 @@ static void sky2_mac_init(struct sky2_hw
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
/* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */
- sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
+ reg = RX_GMF_FL_THR_DEF + 1;
+ /* Another magic mystery workaround from sk98lin */
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0)
+ reg = 0x178;
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg);
/* Configure Tx MAC FIFO */
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
@@ -1737,7 +1743,7 @@ static u16 sky2_phy_speed(const struct s
if (hw->flags & SKY2_HW_FIBRE_PHY)
return SPEED_1000;
- if (!sky2_is_gigabit(hw)) {
+ if (!(hw->flags & SKY2_HW_GIGABIT)) {
if (aux & PHY_M_PS_SPEED_100)
return SPEED_100;
else
@@ -2005,7 +2011,7 @@ static int sky2_change_mtu(struct net_de
synchronize_irq(hw->pdev->irq);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+ if (!(hw->flags & SKY2_HW_RAMBUFFER))
sky2_set_tx_stfwd(hw, port);
ctl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2248,7 +2254,7 @@ static int sky2_status_intr(struct sky2_
}
/* This chip reports checksum status differently */
- if (hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->flags & SKY2_HW_NEW_LE) {
if (sky2->rx_csum &&
(le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
(le->css & CSS_TCPUDPCSOK))
@@ -2289,8 +2295,14 @@ static int sky2_status_intr(struct sky2_
if (!sky2->rx_csum)
break;
- if (hw->chip_id == CHIP_ID_YUKON_EX)
+ /* If this happens then driver assuming wrong format */
+ if (unlikely(hw->flags & SKY2_HW_NEW_LE)) {
+ if (net_ratelimit())
+ printk(KERN_NOTICE "%s: unexpected"
+ " checksum status\n",
+ dev->name);
break;
+ }
/* Both checksum counters are programmed to start at
* the same offset, so unless there is a problem they
@@ -2657,6 +2669,12 @@ static int __devinit sky2_init(struct sk
hw->flags = SKY2_HW_RAMBUFFER;
break;
+ case CHIP_ID_YUKON_FE_P:
+ hw->flags = SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_AUTO_TX_SUM
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
default:
dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
hw->chip_id);
@@ -2864,7 +2882,9 @@ static int sky2_set_wol(struct net_devic
sky2->wol = wol->wolopts;
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
+ hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
sky2_write32(hw, B0_CTST, sky2->wol
? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
@@ -3848,6 +3868,13 @@ static __devinit struct net_device *sky2
sky2->hw = hw;
sky2->msg_enable = netif_msg_init(debug, default_msg);
+ /* This chip has hardware problems that generates
+ * bogus PHY receive status so by default shut up the message.
+ */
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0)
+ sky2->msg_enable &= ~NETIF_MSG_RX_ERR;
+
/* Auto speed and flow control */
sky2->autoneg = AUTONEG_ENABLE;
sky2->flow_mode = FC_BOTH;
@@ -4214,7 +4241,7 @@ static int sky2_resume(struct pci_dev *p
pci_enable_wake(pdev, PCI_D0, 0);
/* Re-enable all clocks */
- if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
+ if (hw->flags & SKY2_HW_ADV_POWER_CTL)
pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
sky2_reset(hw);
--- a/drivers/net/sky2.h 2007-09-19 21:57:42.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-19 21:58:08.000000000 -0700
@@ -1694,6 +1694,10 @@ enum {
GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON,
};
+/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */
+enum {
+ TX_DYN_WM_ENA = 3, /* Yukon-FE+ specific */
+};
/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
enum {
@@ -2058,12 +2062,6 @@ static inline int sky2_is_copper(const s
return !(hw->flags & SKY2_HW_FIBRE_PHY);
}
-static inline int sky2_is_gigabit(const struct sky2_hw *hw)
-{
- return !(hw->chip_id == CHIP_ID_YUKON_FE
- || hw->chip_id == CHIP_ID_YUKON_FE_P);
-}
-
/* Register accessor for memory mapped device */
static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg)
{
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/6] sky2: receive FIFO checking
2007-09-20 5:05 [PATCH 0/6] sky2: merged for netdev-2.6 upstream Stephen Hemminger
` (3 preceding siblings ...)
2007-09-20 5:06 ` [PATCH 4/6] sky2: fe+ chip support Stephen Hemminger
@ 2007-09-20 5:06 ` Stephen Hemminger
2007-09-20 5:06 ` [PATCH 6/6] sky2: version 1.18 Stephen Hemminger
5 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2007-09-20 5:06 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
[-- Attachment #1: sky2-rx-watch.patch --]
[-- Type: text/plain, Size: 4199 bytes --]
A driver writer from another operating system hinted that
the versions of Yukon 2 chip with rambuffer (EC and XL) have
a hardware bug that if the FIFO ever gets completely full it
will hang. Sounds like a classic ring full vs ring empty wrap around
bug.
As a workaround, use the existing watchdog timer to check for
ring full lockup.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 21:58:08.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 21:58:09.000000000 -0700
@@ -1652,9 +1652,6 @@ static int sky2_down(struct net_device *
if (netif_msg_ifdown(sky2))
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
- if (netif_carrier_ok(dev) && --hw->active == 0)
- del_timer(&hw->watchdog_timer);
-
/* Stop more packets from being queued */
netif_stop_queue(dev);
@@ -1781,9 +1778,7 @@ static void sky2_link_up(struct sky2_por
netif_carrier_on(sky2->netdev);
- if (hw->active++ == 0)
- mod_timer(&hw->watchdog_timer, jiffies + 1);
-
+ mod_timer(&hw->watchdog_timer, jiffies + 1);
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
@@ -1834,11 +1829,6 @@ static void sky2_link_down(struct sky2_p
netif_carrier_off(sky2->netdev);
- /* Stop watchdog if both ports are not active */
- if (--hw->active == 0)
- del_timer(&hw->watchdog_timer);
-
-
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
@@ -2484,16 +2474,70 @@ static void sky2_le_error(struct sky2_hw
sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK);
}
-/* Check for lost IRQ once a second */
+static int sky2_rx_hung(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ unsigned rxq = rxqaddr[port];
+ u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP));
+ u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV));
+ u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP));
+ u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL));
+
+ /* If idle and MAC or PCI is stuck */
+ if (sky2->check.last == dev->last_rx &&
+ ((mac_rp == sky2->check.mac_rp &&
+ mac_lev != 0 && mac_lev >= sky2->check.mac_lev) ||
+ /* Check if the PCI RX hang */
+ (fifo_rp == sky2->check.fifo_rp &&
+ fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) {
+ printk(KERN_DEBUG PFX "%s: hung mac %d:%d fifo %d (%d:%d)\n",
+ dev->name, mac_lev, mac_rp, fifo_lev, fifo_rp,
+ sky2_read8(hw, Q_ADDR(rxq, Q_WP)));
+ return 1;
+ } else {
+ sky2->check.last = dev->last_rx;
+ sky2->check.mac_rp = mac_rp;
+ sky2->check.mac_lev = mac_lev;
+ sky2->check.fifo_rp = fifo_rp;
+ sky2->check.fifo_lev = fifo_lev;
+ return 0;
+ }
+}
+
static void sky2_watchdog(unsigned long arg)
{
struct sky2_hw *hw = (struct sky2_hw *) arg;
+ struct net_device *dev;
+ /* Check for lost IRQ */
if (sky2_read32(hw, B0_ISRC))
napi_schedule(&hw->napi);
+ else {
+ int i, active = 0;
+
+ for (i = 0; i < hw->ports; i++) {
+ dev = hw->dev[i];
+ if (!netif_running(dev))
+ continue;
+ ++active;
+
+ /* For chips with Rx FIFO, check if stuck */
+ if ((hw->flags & SKY2_HW_RAMBUFFER) &&
+ sky2_rx_hung(dev)) {
+ pr_info(PFX "%s: receiver hang detected\n",
+ dev->name);
+ schedule_work(&hw->restart_work);
+ return;
+ }
+ }
+
+ if (active == 0)
+ return;
+ }
- if (hw->active > 0)
- mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
+ mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
}
/* Hardware/software error handling */
--- a/drivers/net/sky2.h 2007-09-19 21:58:08.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-19 21:58:09.000000000 -0700
@@ -2008,6 +2008,14 @@ struct sky2_port {
u16 rx_tag;
struct vlan_group *vlgrp;
#endif
+ struct {
+ unsigned long last;
+ u32 mac_rp;
+ u8 mac_lev;
+ u8 fifo_rp;
+ u8 fifo_lev;
+ } check;
+
dma_addr_t rx_le_map;
dma_addr_t tx_le_map;
@@ -2046,7 +2054,6 @@ struct sky2_hw {
u8 chip_rev;
u8 pmd_type;
u8 ports;
- u8 active;
struct sky2_status_le *st_le;
u32 st_idx;
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/6] sky2: version 1.18
2007-09-20 5:05 [PATCH 0/6] sky2: merged for netdev-2.6 upstream Stephen Hemminger
` (4 preceding siblings ...)
2007-09-20 5:06 ` [PATCH 5/6] sky2: receive FIFO checking Stephen Hemminger
@ 2007-09-20 5:06 ` Stephen Hemminger
5 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2007-09-20 5:06 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
[-- Attachment #1: sky2-1.19 --]
[-- Type: text/plain, Size: 430 bytes --]
Update version number
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 21:58:09.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 21:58:09.000000000 -0700
@@ -52,7 +52,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.17"
+#define DRV_VERSION "1.18.1"
#define PFX DRV_NAME " "
/*
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2007-09-20 5:07 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-20 5:05 [PATCH 0/6] sky2: merged for netdev-2.6 upstream Stephen Hemminger
2007-09-20 5:06 ` [PATCH 1/6] sky2: fix VLAN receive processing Stephen Hemminger
2007-09-20 5:06 ` [PATCH 2/6] sky2: ethtool speed report bug Stephen Hemminger
2007-09-20 5:06 ` [PATCH 3/6] sky2: reorganize chip revision features Stephen Hemminger
2007-09-20 5:06 ` [PATCH 4/6] sky2: fe+ chip support Stephen Hemminger
2007-09-20 5:06 ` [PATCH 5/6] sky2: receive FIFO checking Stephen Hemminger
2007-09-20 5:06 ` [PATCH 6/6] sky2: version 1.18 Stephen Hemminger
-- strict thread matches above, loose matches on Subject: below --
2007-09-19 22:36 [PATCH 0/6] sky2: version 1.18 (rev2) Stephen Hemminger
2007-09-19 22:36 ` [PATCH 3/6] sky2: reorganize chip revision features Stephen Hemminger
2007-09-19 23:27 ` Rick Jones
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).