diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 68 |
1 files changed, 51 insertions, 17 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ffd267fab21d..959109609d85 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include "sky2.h" | 51 | #include "sky2.h" |
52 | 52 | ||
53 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
54 | #define DRV_VERSION "1.3" | 54 | #define DRV_VERSION "1.4" |
55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -105,6 +105,7 @@ MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms) | |||
105 | static const struct pci_device_id sky2_id_table[] = { | 105 | static const struct pci_device_id sky2_id_table[] = { |
106 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 106 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
107 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 107 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
108 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ | ||
108 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, | 109 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, |
109 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, | 110 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, |
110 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, | 111 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, |
@@ -235,6 +236,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | |||
235 | } | 236 | } |
236 | 237 | ||
237 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | 238 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { |
239 | sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON); | ||
238 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); | 240 | sky2_pci_write32(hw, PCI_DEV_REG3, 0); |
239 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); | 241 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); |
240 | reg1 &= P_ASPM_CONTROL_MSK; | 242 | reg1 &= P_ASPM_CONTROL_MSK; |
@@ -306,7 +308,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
306 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; | 308 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; |
307 | 309 | ||
308 | if (sky2->autoneg == AUTONEG_ENABLE && | 310 | if (sky2->autoneg == AUTONEG_ENABLE && |
309 | (hw->chip_id != CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { | 311 | !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { |
310 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); | 312 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); |
311 | 313 | ||
312 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | | 314 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | |
@@ -977,6 +979,7 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
977 | struct sky2_hw *hw = sky2->hw; | 979 | struct sky2_hw *hw = sky2->hw; |
978 | unsigned rxq = rxqaddr[sky2->port]; | 980 | unsigned rxq = rxqaddr[sky2->port]; |
979 | int i; | 981 | int i; |
982 | unsigned thresh; | ||
980 | 983 | ||
981 | sky2->rx_put = sky2->rx_next = 0; | 984 | sky2->rx_put = sky2->rx_next = 0; |
982 | sky2_qset(hw, rxq); | 985 | sky2_qset(hw, rxq); |
@@ -1001,9 +1004,21 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
1001 | sky2_rx_add(sky2, re->mapaddr); | 1004 | sky2_rx_add(sky2, re->mapaddr); |
1002 | } | 1005 | } |
1003 | 1006 | ||
1004 | /* Truncate oversize frames */ | 1007 | |
1005 | sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8); | 1008 | /* |
1006 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); | 1009 | * The receiver hangs if it receives frames larger than the |
1010 | * packet buffer. As a workaround, truncate oversize frames, but | ||
1011 | * the register is limited to 9 bits, so if you do frames > 2052 | ||
1012 | * you better get the MTU right! | ||
1013 | */ | ||
1014 | thresh = (sky2->rx_bufsize - 8) / sizeof(u32); | ||
1015 | if (thresh > 0x1ff) | ||
1016 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF); | ||
1017 | else { | ||
1018 | sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh); | ||
1019 | sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); | ||
1020 | } | ||
1021 | |||
1007 | 1022 | ||
1008 | /* Tell chip about available buffers */ | 1023 | /* Tell chip about available buffers */ |
1009 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); | 1024 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); |
@@ -1020,7 +1035,25 @@ static int sky2_up(struct net_device *dev) | |||
1020 | struct sky2_hw *hw = sky2->hw; | 1035 | struct sky2_hw *hw = sky2->hw; |
1021 | unsigned port = sky2->port; | 1036 | unsigned port = sky2->port; |
1022 | u32 ramsize, rxspace, imask; | 1037 | u32 ramsize, rxspace, imask; |
1023 | int err = -ENOMEM; | 1038 | int cap, err = -ENOMEM; |
1039 | struct net_device *otherdev = hw->dev[sky2->port^1]; | ||
1040 | |||
1041 | /* | ||
1042 | * On dual port PCI-X card, there is an problem where status | ||
1043 | * can be received out of order due to split transactions | ||
1044 | */ | ||
1045 | if (otherdev && netif_running(otherdev) && | ||
1046 | (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { | ||
1047 | struct sky2_port *osky2 = netdev_priv(otherdev); | ||
1048 | u16 cmd; | ||
1049 | |||
1050 | cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); | ||
1051 | cmd &= ~PCI_X_CMD_MAX_SPLIT; | ||
1052 | sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); | ||
1053 | |||
1054 | sky2->rx_csum = 0; | ||
1055 | osky2->rx_csum = 0; | ||
1056 | } | ||
1024 | 1057 | ||
1025 | if (netif_msg_ifup(sky2)) | 1058 | if (netif_msg_ifup(sky2)) |
1026 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); | 1059 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); |
@@ -1899,6 +1932,12 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
1899 | } | 1932 | } |
1900 | } | 1933 | } |
1901 | 1934 | ||
1935 | /* Is status ring empty or is there more to do? */ | ||
1936 | static inline int sky2_more_work(const struct sky2_hw *hw) | ||
1937 | { | ||
1938 | return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); | ||
1939 | } | ||
1940 | |||
1902 | /* Process status response ring */ | 1941 | /* Process status response ring */ |
1903 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 1942 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
1904 | { | 1943 | { |
@@ -2171,19 +2210,19 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2171 | if (status & Y2_IS_CHK_TXA2) | 2210 | if (status & Y2_IS_CHK_TXA2) |
2172 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | 2211 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); |
2173 | 2212 | ||
2174 | if (status & Y2_IS_STAT_BMU) | ||
2175 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
2176 | |||
2177 | work_done = sky2_status_intr(hw, work_limit); | 2213 | work_done = sky2_status_intr(hw, work_limit); |
2178 | *budget -= work_done; | 2214 | *budget -= work_done; |
2179 | dev0->quota -= work_done; | 2215 | dev0->quota -= work_done; |
2180 | 2216 | ||
2181 | if (work_done >= work_limit) | 2217 | if (status & Y2_IS_STAT_BMU) |
2218 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
2219 | |||
2220 | if (sky2_more_work(hw)) | ||
2182 | return 1; | 2221 | return 1; |
2183 | 2222 | ||
2184 | netif_rx_complete(dev0); | 2223 | netif_rx_complete(dev0); |
2185 | 2224 | ||
2186 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2225 | sky2_read32(hw, B0_Y2_SP_LISR); |
2187 | return 0; | 2226 | return 0; |
2188 | } | 2227 | } |
2189 | 2228 | ||
@@ -3067,12 +3106,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3067 | sky2->duplex = -1; | 3106 | sky2->duplex = -1; |
3068 | sky2->speed = -1; | 3107 | sky2->speed = -1; |
3069 | sky2->advertising = sky2_supported_modes(hw); | 3108 | sky2->advertising = sky2_supported_modes(hw); |
3070 | 3109 | sky2->rx_csum = 1; | |
3071 | /* Receive checksum disabled for Yukon XL | ||
3072 | * because of observed problems with incorrect | ||
3073 | * values when multiple packets are received in one interrupt | ||
3074 | */ | ||
3075 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); | ||
3076 | 3110 | ||
3077 | spin_lock_init(&sky2->phy_lock); | 3111 | spin_lock_init(&sky2->phy_lock); |
3078 | sky2->tx_pending = TX_DEF_PENDING; | 3112 | sky2->tx_pending = TX_DEF_PENDING; |