diff options
Diffstat (limited to 'drivers/net/sky2.c')
| -rw-r--r-- | drivers/net/sky2.c | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 62be6d99d05c..60779ebf2ff6 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 | |
| @@ -1020,19 +1022,26 @@ static int sky2_up(struct net_device *dev) | |||
| 1020 | struct sky2_hw *hw = sky2->hw; | 1022 | struct sky2_hw *hw = sky2->hw; |
| 1021 | unsigned port = sky2->port; | 1023 | unsigned port = sky2->port; |
| 1022 | u32 ramsize, rxspace, imask; | 1024 | u32 ramsize, rxspace, imask; |
| 1023 | int err; | 1025 | int cap, err = -ENOMEM; |
| 1024 | struct net_device *otherdev = hw->dev[sky2->port^1]; | 1026 | struct net_device *otherdev = hw->dev[sky2->port^1]; |
| 1025 | 1027 | ||
| 1026 | /* Block bringing up both ports at the same time on a dual port card. | 1028 | /* |
| 1027 | * There is an unfixed bug where receiver gets confused and picks up | 1029 | * On dual port PCI-X card, there is an problem where status |
| 1028 | * packets out of order. Until this is fixed, prevent data corruption. | 1030 | * can be received out of order due to split transactions |
| 1029 | */ | 1031 | */ |
| 1030 | if (otherdev && netif_running(otherdev)) { | 1032 | if (otherdev && netif_running(otherdev) && |
| 1031 | printk(KERN_INFO PFX "dual port support is disabled.\n"); | 1033 | (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { |
| 1032 | return -EBUSY; | 1034 | struct sky2_port *osky2 = netdev_priv(otherdev); |
| 1033 | } | 1035 | u16 cmd; |
| 1036 | |||
| 1037 | cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); | ||
| 1038 | cmd &= ~PCI_X_CMD_MAX_SPLIT; | ||
| 1039 | sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); | ||
| 1040 | |||
| 1041 | sky2->rx_csum = 0; | ||
| 1042 | osky2->rx_csum = 0; | ||
| 1043 | } | ||
| 1034 | 1044 | ||
| 1035 | err = -ENOMEM; | ||
| 1036 | if (netif_msg_ifup(sky2)) | 1045 | if (netif_msg_ifup(sky2)) |
| 1037 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); | 1046 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); |
| 1038 | 1047 | ||
| @@ -1910,6 +1919,12 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
| 1910 | } | 1919 | } |
| 1911 | } | 1920 | } |
| 1912 | 1921 | ||
| 1922 | /* Is status ring empty or is there more to do? */ | ||
| 1923 | static inline int sky2_more_work(const struct sky2_hw *hw) | ||
| 1924 | { | ||
| 1925 | return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); | ||
| 1926 | } | ||
| 1927 | |||
| 1913 | /* Process status response ring */ | 1928 | /* Process status response ring */ |
| 1914 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 1929 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
| 1915 | { | 1930 | { |
| @@ -2182,19 +2197,19 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2182 | if (status & Y2_IS_CHK_TXA2) | 2197 | if (status & Y2_IS_CHK_TXA2) |
| 2183 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | 2198 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); |
| 2184 | 2199 | ||
| 2185 | if (status & Y2_IS_STAT_BMU) | ||
| 2186 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
| 2187 | |||
| 2188 | work_done = sky2_status_intr(hw, work_limit); | 2200 | work_done = sky2_status_intr(hw, work_limit); |
| 2189 | *budget -= work_done; | 2201 | *budget -= work_done; |
| 2190 | dev0->quota -= work_done; | 2202 | dev0->quota -= work_done; |
| 2191 | 2203 | ||
| 2192 | if (work_done >= work_limit) | 2204 | if (status & Y2_IS_STAT_BMU) |
| 2205 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
| 2206 | |||
| 2207 | if (sky2_more_work(hw)) | ||
| 2193 | return 1; | 2208 | return 1; |
| 2194 | 2209 | ||
| 2195 | netif_rx_complete(dev0); | 2210 | netif_rx_complete(dev0); |
| 2196 | 2211 | ||
| 2197 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2212 | sky2_read32(hw, B0_Y2_SP_LISR); |
| 2198 | return 0; | 2213 | return 0; |
| 2199 | } | 2214 | } |
| 2200 | 2215 | ||
| @@ -3078,12 +3093,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
| 3078 | sky2->duplex = -1; | 3093 | sky2->duplex = -1; |
| 3079 | sky2->speed = -1; | 3094 | sky2->speed = -1; |
| 3080 | sky2->advertising = sky2_supported_modes(hw); | 3095 | sky2->advertising = sky2_supported_modes(hw); |
| 3081 | 3096 | sky2->rx_csum = 1; | |
| 3082 | /* Receive checksum disabled for Yukon XL | ||
| 3083 | * because of observed problems with incorrect | ||
| 3084 | * values when multiple packets are received in one interrupt | ||
| 3085 | */ | ||
| 3086 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); | ||
| 3087 | 3097 | ||
| 3088 | spin_lock_init(&sky2->phy_lock); | 3098 | spin_lock_init(&sky2->phy_lock); |
| 3089 | sky2->tx_pending = TX_DEF_PENDING; | 3099 | sky2->tx_pending = TX_DEF_PENDING; |
