diff options
Diffstat (limited to 'drivers/net/sky2.c')
| -rw-r--r-- | drivers/net/sky2.c | 449 |
1 files changed, 362 insertions, 87 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index b51d73c8f817..a2f32151559e 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/workqueue.h> | 39 | #include <linux/workqueue.h> |
| 40 | #include <linux/if_vlan.h> | 40 | #include <linux/if_vlan.h> |
| 41 | #include <linux/prefetch.h> | 41 | #include <linux/prefetch.h> |
| 42 | #include <linux/debugfs.h> | ||
| 42 | #include <linux/mii.h> | 43 | #include <linux/mii.h> |
| 43 | 44 | ||
| 44 | #include <asm/irq.h> | 45 | #include <asm/irq.h> |
| @@ -50,7 +51,7 @@ | |||
| 50 | #include "sky2.h" | 51 | #include "sky2.h" |
| 51 | 52 | ||
| 52 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
| 53 | #define DRV_VERSION "1.15" | 54 | #define DRV_VERSION "1.16" |
| 54 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
| 55 | 56 | ||
| 56 | /* | 57 | /* |
| @@ -64,7 +65,6 @@ | |||
| 64 | #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) | 65 | #define RX_MAX_PENDING (RX_LE_SIZE/6 - 2) |
| 65 | #define RX_DEF_PENDING RX_MAX_PENDING | 66 | #define RX_DEF_PENDING RX_MAX_PENDING |
| 66 | #define RX_SKB_ALIGN 8 | 67 | #define RX_SKB_ALIGN 8 |
| 67 | #define RX_BUF_WRITE 16 | ||
| 68 | 68 | ||
| 69 | #define TX_RING_SIZE 512 | 69 | #define TX_RING_SIZE 512 |
| 70 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) | 70 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) |
| @@ -77,6 +77,9 @@ | |||
| 77 | #define NAPI_WEIGHT 64 | 77 | #define NAPI_WEIGHT 64 |
| 78 | #define PHY_RETRIES 1000 | 78 | #define PHY_RETRIES 1000 |
| 79 | 79 | ||
| 80 | #define SKY2_EEPROM_MAGIC 0x9955aabb | ||
| 81 | |||
| 82 | |||
| 80 | #define RING_NEXT(x,s) (((x)+1) & ((s)-1)) | 83 | #define RING_NEXT(x,s) (((x)+1) & ((s)-1)) |
| 81 | 84 | ||
| 82 | static const u32 default_msg = | 85 | static const u32 default_msg = |
| @@ -96,7 +99,7 @@ static int disable_msi = 0; | |||
| 96 | module_param(disable_msi, int, 0); | 99 | module_param(disable_msi, int, 0); |
| 97 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | 100 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); |
| 98 | 101 | ||
| 99 | static int idle_timeout = 0; | 102 | static int idle_timeout = 100; |
| 100 | module_param(idle_timeout, int, 0); | 103 | module_param(idle_timeout, int, 0); |
| 101 | MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); | 104 | MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); |
| 102 | 105 | ||
| @@ -890,24 +893,18 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) | |||
| 890 | return le; | 893 | return le; |
| 891 | } | 894 | } |
| 892 | 895 | ||
| 893 | /* Return high part of DMA address (could be 32 or 64 bit) */ | ||
| 894 | static inline u32 high32(dma_addr_t a) | ||
| 895 | { | ||
| 896 | return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0; | ||
| 897 | } | ||
| 898 | |||
| 899 | /* Build description to hardware for one receive segment */ | 896 | /* Build description to hardware for one receive segment */ |
| 900 | static void sky2_rx_add(struct sky2_port *sky2, u8 op, | 897 | static void sky2_rx_add(struct sky2_port *sky2, u8 op, |
| 901 | dma_addr_t map, unsigned len) | 898 | dma_addr_t map, unsigned len) |
| 902 | { | 899 | { |
| 903 | struct sky2_rx_le *le; | 900 | struct sky2_rx_le *le; |
| 904 | u32 hi = high32(map); | 901 | u32 hi = upper_32_bits(map); |
| 905 | 902 | ||
| 906 | if (sky2->rx_addr64 != hi) { | 903 | if (sky2->rx_addr64 != hi) { |
| 907 | le = sky2_next_rx(sky2); | 904 | le = sky2_next_rx(sky2); |
| 908 | le->addr = cpu_to_le32(hi); | 905 | le->addr = cpu_to_le32(hi); |
| 909 | le->opcode = OP_ADDR64 | HW_OWNER; | 906 | le->opcode = OP_ADDR64 | HW_OWNER; |
| 910 | sky2->rx_addr64 = high32(map + len); | 907 | sky2->rx_addr64 = upper_32_bits(map + len); |
| 911 | } | 908 | } |
| 912 | 909 | ||
| 913 | le = sky2_next_rx(sky2); | 910 | le = sky2_next_rx(sky2); |
| @@ -1137,6 +1134,11 @@ nomem: | |||
| 1137 | return NULL; | 1134 | return NULL; |
| 1138 | } | 1135 | } |
| 1139 | 1136 | ||
| 1137 | static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq) | ||
| 1138 | { | ||
| 1139 | sky2_put_idx(sky2->hw, rxq, sky2->rx_put); | ||
| 1140 | } | ||
| 1141 | |||
| 1140 | /* | 1142 | /* |
| 1141 | * Allocate and setup receiver buffer pool. | 1143 | * Allocate and setup receiver buffer pool. |
| 1142 | * Normal case this ends up creating one list element for skb | 1144 | * Normal case this ends up creating one list element for skb |
| @@ -1172,8 +1174,7 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
| 1172 | rx_set_checksum(sky2); | 1174 | rx_set_checksum(sky2); |
| 1173 | 1175 | ||
| 1174 | /* Space needed for frame data + headers rounded up */ | 1176 | /* Space needed for frame data + headers rounded up */ |
| 1175 | size = ALIGN(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8) | 1177 | size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); |
| 1176 | + 8; | ||
| 1177 | 1178 | ||
| 1178 | /* Stopping point for hardware truncation */ | 1179 | /* Stopping point for hardware truncation */ |
| 1179 | thresh = (size - 8) / sizeof(u32); | 1180 | thresh = (size - 8) / sizeof(u32); |
| @@ -1228,7 +1229,7 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
| 1228 | } | 1229 | } |
| 1229 | 1230 | ||
| 1230 | /* Tell chip about available buffers */ | 1231 | /* Tell chip about available buffers */ |
| 1231 | sky2_put_idx(hw, rxq, sky2->rx_put); | 1232 | sky2_rx_update(sky2, rxq); |
| 1232 | return 0; | 1233 | return 0; |
| 1233 | nomem: | 1234 | nomem: |
| 1234 | sky2_rx_clean(sky2); | 1235 | sky2_rx_clean(sky2); |
| @@ -1265,6 +1266,8 @@ static int sky2_up(struct net_device *dev) | |||
| 1265 | if (netif_msg_ifup(sky2)) | 1266 | if (netif_msg_ifup(sky2)) |
| 1266 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); | 1267 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); |
| 1267 | 1268 | ||
| 1269 | netif_carrier_off(dev); | ||
| 1270 | |||
| 1268 | /* must be power of 2 */ | 1271 | /* must be power of 2 */ |
| 1269 | sky2->tx_le = pci_alloc_consistent(hw->pdev, | 1272 | sky2->tx_le = pci_alloc_consistent(hw->pdev, |
| 1270 | TX_RING_SIZE * | 1273 | TX_RING_SIZE * |
| @@ -1415,14 +1418,15 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 1415 | 1418 | ||
| 1416 | len = skb_headlen(skb); | 1419 | len = skb_headlen(skb); |
| 1417 | mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); | 1420 | mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); |
| 1418 | addr64 = high32(mapping); | 1421 | addr64 = upper_32_bits(mapping); |
| 1419 | 1422 | ||
| 1420 | /* Send high bits if changed or crosses boundary */ | 1423 | /* Send high bits if changed or crosses boundary */ |
| 1421 | if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) { | 1424 | if (addr64 != sky2->tx_addr64 || |
| 1425 | upper_32_bits(mapping + len) != sky2->tx_addr64) { | ||
| 1422 | le = get_tx_le(sky2); | 1426 | le = get_tx_le(sky2); |
| 1423 | le->addr = cpu_to_le32(addr64); | 1427 | le->addr = cpu_to_le32(addr64); |
| 1424 | le->opcode = OP_ADDR64 | HW_OWNER; | 1428 | le->opcode = OP_ADDR64 | HW_OWNER; |
| 1425 | sky2->tx_addr64 = high32(mapping + len); | 1429 | sky2->tx_addr64 = upper_32_bits(mapping + len); |
| 1426 | } | 1430 | } |
| 1427 | 1431 | ||
| 1428 | /* Check for TCP Segmentation Offload */ | 1432 | /* Check for TCP Segmentation Offload */ |
| @@ -1502,7 +1506,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 1502 | 1506 | ||
| 1503 | mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, | 1507 | mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, |
| 1504 | frag->size, PCI_DMA_TODEVICE); | 1508 | frag->size, PCI_DMA_TODEVICE); |
| 1505 | addr64 = high32(mapping); | 1509 | addr64 = upper_32_bits(mapping); |
| 1506 | if (addr64 != sky2->tx_addr64) { | 1510 | if (addr64 != sky2->tx_addr64) { |
| 1507 | le = get_tx_le(sky2); | 1511 | le = get_tx_le(sky2); |
| 1508 | le->addr = cpu_to_le32(addr64); | 1512 | le->addr = cpu_to_le32(addr64); |
| @@ -1572,13 +1576,13 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
| 1572 | if (unlikely(netif_msg_tx_done(sky2))) | 1576 | if (unlikely(netif_msg_tx_done(sky2))) |
| 1573 | printk(KERN_DEBUG "%s: tx done %u\n", | 1577 | printk(KERN_DEBUG "%s: tx done %u\n", |
| 1574 | dev->name, idx); | 1578 | dev->name, idx); |
| 1579 | |||
| 1575 | sky2->net_stats.tx_packets++; | 1580 | sky2->net_stats.tx_packets++; |
| 1576 | sky2->net_stats.tx_bytes += re->skb->len; | 1581 | sky2->net_stats.tx_bytes += re->skb->len; |
| 1577 | 1582 | ||
| 1578 | dev_kfree_skb_any(re->skb); | 1583 | dev_kfree_skb_any(re->skb); |
| 1584 | sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE); | ||
| 1579 | } | 1585 | } |
| 1580 | |||
| 1581 | le->opcode = 0; /* paranoia */ | ||
| 1582 | } | 1586 | } |
| 1583 | 1587 | ||
| 1584 | sky2->tx_cons = idx; | 1588 | sky2->tx_cons = idx; |
| @@ -1616,7 +1620,6 @@ static int sky2_down(struct net_device *dev) | |||
| 1616 | 1620 | ||
| 1617 | /* Stop more packets from being queued */ | 1621 | /* Stop more packets from being queued */ |
| 1618 | netif_stop_queue(dev); | 1622 | netif_stop_queue(dev); |
| 1619 | netif_carrier_off(dev); | ||
| 1620 | 1623 | ||
| 1621 | /* Disable port IRQ */ | 1624 | /* Disable port IRQ */ |
| 1622 | imask = sky2_read32(hw, B0_IMSK); | 1625 | imask = sky2_read32(hw, B0_IMSK); |
| @@ -1668,6 +1671,8 @@ static int sky2_down(struct net_device *dev) | |||
| 1668 | 1671 | ||
| 1669 | sky2_phy_power(hw, port, 0); | 1672 | sky2_phy_power(hw, port, 0); |
| 1670 | 1673 | ||
| 1674 | netif_carrier_off(dev); | ||
| 1675 | |||
| 1671 | /* turn off LED's */ | 1676 | /* turn off LED's */ |
| 1672 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 1677 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
| 1673 | 1678 | ||
| @@ -1732,7 +1737,6 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
| 1732 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); | 1737 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); |
| 1733 | 1738 | ||
| 1734 | netif_carrier_on(sky2->netdev); | 1739 | netif_carrier_on(sky2->netdev); |
| 1735 | netif_wake_queue(sky2->netdev); | ||
| 1736 | 1740 | ||
| 1737 | /* Turn on link LED */ | 1741 | /* Turn on link LED */ |
| 1738 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | 1742 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), |
| @@ -1784,7 +1788,6 @@ static void sky2_link_down(struct sky2_port *sky2) | |||
| 1784 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1788 | gma_write16(hw, port, GM_GP_CTRL, reg); |
| 1785 | 1789 | ||
| 1786 | netif_carrier_off(sky2->netdev); | 1790 | netif_carrier_off(sky2->netdev); |
| 1787 | netif_stop_queue(sky2->netdev); | ||
| 1788 | 1791 | ||
| 1789 | /* Turn on link LED */ | 1792 | /* Turn on link LED */ |
| 1790 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); | 1793 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); |
| @@ -2055,8 +2058,6 @@ static struct sk_buff *receive_new(struct sky2_port *sky2, | |||
| 2055 | struct sk_buff *skb, *nskb; | 2058 | struct sk_buff *skb, *nskb; |
| 2056 | unsigned hdr_space = sky2->rx_data_size; | 2059 | unsigned hdr_space = sky2->rx_data_size; |
| 2057 | 2060 | ||
| 2058 | pr_debug(PFX "receive new length=%d\n", length); | ||
| 2059 | |||
| 2060 | /* Don't be tricky about reusing pages (yet) */ | 2061 | /* Don't be tricky about reusing pages (yet) */ |
| 2061 | nskb = sky2_rx_alloc(sky2); | 2062 | nskb = sky2_rx_alloc(sky2); |
| 2062 | if (unlikely(!nskb)) | 2063 | if (unlikely(!nskb)) |
| @@ -2100,6 +2101,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, | |||
| 2100 | if (!(status & GMR_FS_RX_OK)) | 2101 | if (!(status & GMR_FS_RX_OK)) |
| 2101 | goto resubmit; | 2102 | goto resubmit; |
| 2102 | 2103 | ||
| 2104 | if (status >> 16 != length) | ||
| 2105 | goto len_mismatch; | ||
| 2106 | |||
| 2103 | if (length < copybreak) | 2107 | if (length < copybreak) |
| 2104 | skb = receive_copy(sky2, re, length); | 2108 | skb = receive_copy(sky2, re, length); |
| 2105 | else | 2109 | else |
| @@ -2109,6 +2113,11 @@ resubmit: | |||
| 2109 | 2113 | ||
| 2110 | return skb; | 2114 | return skb; |
| 2111 | 2115 | ||
| 2116 | len_mismatch: | ||
| 2117 | /* Truncation of overlength packets | ||
| 2118 | causes PHY length to not match MAC length */ | ||
| 2119 | ++sky2->net_stats.rx_length_errors; | ||
| 2120 | |||
| 2112 | error: | 2121 | error: |
| 2113 | ++sky2->net_stats.rx_errors; | 2122 | ++sky2->net_stats.rx_errors; |
| 2114 | if (status & GMR_FS_RX_FF_OV) { | 2123 | if (status & GMR_FS_RX_FF_OV) { |
| @@ -2145,14 +2154,14 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
| 2145 | /* Process status response ring */ | 2154 | /* Process status response ring */ |
| 2146 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 2155 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
| 2147 | { | 2156 | { |
| 2148 | struct sky2_port *sky2; | ||
| 2149 | int work_done = 0; | 2157 | int work_done = 0; |
| 2150 | unsigned buf_write[2] = { 0, 0 }; | 2158 | unsigned rx[2] = { 0, 0 }; |
| 2151 | u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); | 2159 | u16 hwidx = sky2_read16(hw, STAT_PUT_IDX); |
| 2152 | 2160 | ||
| 2153 | rmb(); | 2161 | rmb(); |
| 2154 | 2162 | ||
| 2155 | while (hw->st_idx != hwidx) { | 2163 | while (hw->st_idx != hwidx) { |
| 2164 | struct sky2_port *sky2; | ||
| 2156 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 2165 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |
| 2157 | unsigned port = le->css & CSS_LINK_BIT; | 2166 | unsigned port = le->css & CSS_LINK_BIT; |
| 2158 | struct net_device *dev; | 2167 | struct net_device *dev; |
| @@ -2169,10 +2178,11 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
| 2169 | 2178 | ||
| 2170 | switch (le->opcode & ~HW_OWNER) { | 2179 | switch (le->opcode & ~HW_OWNER) { |
| 2171 | case OP_RXSTAT: | 2180 | case OP_RXSTAT: |
| 2181 | ++rx[port]; | ||
| 2172 | skb = sky2_receive(dev, length, status); | 2182 | skb = sky2_receive(dev, length, status); |
| 2173 | if (unlikely(!skb)) { | 2183 | if (unlikely(!skb)) { |
| 2174 | sky2->net_stats.rx_dropped++; | 2184 | sky2->net_stats.rx_dropped++; |
| 2175 | goto force_update; | 2185 | break; |
| 2176 | } | 2186 | } |
| 2177 | 2187 | ||
| 2178 | /* This chip reports checksum status differently */ | 2188 | /* This chip reports checksum status differently */ |
| @@ -2199,13 +2209,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
| 2199 | #endif | 2209 | #endif |
| 2200 | netif_receive_skb(skb); | 2210 | netif_receive_skb(skb); |
| 2201 | 2211 | ||
| 2202 | /* Update receiver after 16 frames */ | ||
| 2203 | if (++buf_write[port] == RX_BUF_WRITE) { | ||
| 2204 | force_update: | ||
| 2205 | sky2_put_idx(hw, rxqaddr[port], sky2->rx_put); | ||
| 2206 | buf_write[port] = 0; | ||
| 2207 | } | ||
| 2208 | |||
| 2209 | /* Stop after net poll weight */ | 2212 | /* Stop after net poll weight */ |
| 2210 | if (++work_done >= to_do) | 2213 | if (++work_done >= to_do) |
| 2211 | goto exit_loop; | 2214 | goto exit_loop; |
| @@ -2261,24 +2264,18 @@ force_update: | |||
| 2261 | if (net_ratelimit()) | 2264 | if (net_ratelimit()) |
| 2262 | printk(KERN_WARNING PFX | 2265 | printk(KERN_WARNING PFX |
| 2263 | "unknown status opcode 0x%x\n", le->opcode); | 2266 | "unknown status opcode 0x%x\n", le->opcode); |
| 2264 | goto exit_loop; | ||
| 2265 | } | 2267 | } |
| 2266 | } | 2268 | } |
| 2267 | 2269 | ||
| 2268 | /* Fully processed status ring so clear irq */ | 2270 | /* Fully processed status ring so clear irq */ |
| 2269 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2271 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
| 2270 | mmiowb(); | ||
| 2271 | 2272 | ||
| 2272 | exit_loop: | 2273 | exit_loop: |
| 2273 | if (buf_write[0]) { | 2274 | if (rx[0]) |
| 2274 | sky2 = netdev_priv(hw->dev[0]); | 2275 | sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1); |
| 2275 | sky2_put_idx(hw, Q_R1, sky2->rx_put); | ||
| 2276 | } | ||
| 2277 | 2276 | ||
| 2278 | if (buf_write[1]) { | 2277 | if (rx[1]) |
| 2279 | sky2 = netdev_priv(hw->dev[1]); | 2278 | sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2); |
| 2280 | sky2_put_idx(hw, Q_R2, sky2->rx_put); | ||
| 2281 | } | ||
| 2282 | 2279 | ||
| 2283 | return work_done; | 2280 | return work_done; |
| 2284 | } | 2281 | } |
| @@ -2475,8 +2472,7 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status) | |||
| 2475 | static int sky2_poll(struct net_device *dev0, int *budget) | 2472 | static int sky2_poll(struct net_device *dev0, int *budget) |
| 2476 | { | 2473 | { |
| 2477 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2474 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
| 2478 | int work_limit = min(dev0->quota, *budget); | 2475 | int work_done; |
| 2479 | int work_done = 0; | ||
| 2480 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2476 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
| 2481 | 2477 | ||
| 2482 | if (unlikely(status & Y2_IS_ERROR)) | 2478 | if (unlikely(status & Y2_IS_ERROR)) |
| @@ -2488,18 +2484,25 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2488 | if (status & Y2_IS_IRQ_PHY2) | 2484 | if (status & Y2_IS_IRQ_PHY2) |
| 2489 | sky2_phy_intr(hw, 1); | 2485 | sky2_phy_intr(hw, 1); |
| 2490 | 2486 | ||
| 2491 | work_done = sky2_status_intr(hw, work_limit); | 2487 | work_done = sky2_status_intr(hw, min(dev0->quota, *budget)); |
| 2492 | if (work_done < work_limit) { | 2488 | *budget -= work_done; |
| 2493 | netif_rx_complete(dev0); | 2489 | dev0->quota -= work_done; |
| 2494 | 2490 | ||
| 2495 | /* end of interrupt, re-enables also acts as I/O synchronization */ | 2491 | /* More work? */ |
| 2496 | sky2_read32(hw, B0_Y2_SP_LISR); | 2492 | if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)) |
| 2497 | return 0; | ||
| 2498 | } else { | ||
| 2499 | *budget -= work_done; | ||
| 2500 | dev0->quota -= work_done; | ||
| 2501 | return 1; | 2493 | return 1; |
| 2494 | |||
| 2495 | /* Bug/Errata workaround? | ||
| 2496 | * Need to kick the TX irq moderation timer. | ||
| 2497 | */ | ||
| 2498 | if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { | ||
| 2499 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | ||
| 2500 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
| 2502 | } | 2501 | } |
| 2502 | netif_rx_complete(dev0); | ||
| 2503 | |||
| 2504 | sky2_read32(hw, B0_Y2_SP_LISR); | ||
| 2505 | return 0; | ||
| 2503 | } | 2506 | } |
| 2504 | 2507 | ||
| 2505 | static irqreturn_t sky2_intr(int irq, void *dev_id) | 2508 | static irqreturn_t sky2_intr(int irq, void *dev_id) |
| @@ -2723,8 +2726,6 @@ static void sky2_restart(struct work_struct *work) | |||
| 2723 | struct net_device *dev; | 2726 | struct net_device *dev; |
| 2724 | int i, err; | 2727 | int i, err; |
| 2725 | 2728 | ||
| 2726 | dev_dbg(&hw->pdev->dev, "restarting\n"); | ||
| 2727 | |||
| 2728 | del_timer_sync(&hw->idle_timer); | 2729 | del_timer_sync(&hw->idle_timer); |
| 2729 | 2730 | ||
| 2730 | rtnl_lock(); | 2731 | rtnl_lock(); |
| @@ -3429,39 +3430,315 @@ static int sky2_set_tso(struct net_device *dev, u32 data) | |||
| 3429 | return ethtool_op_set_tso(dev, data); | 3430 | return ethtool_op_set_tso(dev, data); |
| 3430 | } | 3431 | } |
| 3431 | 3432 | ||
| 3433 | static int sky2_get_eeprom_len(struct net_device *dev) | ||
| 3434 | { | ||
| 3435 | struct sky2_port *sky2 = netdev_priv(dev); | ||
| 3436 | u16 reg2; | ||
| 3437 | |||
| 3438 | reg2 = sky2_pci_read32(sky2->hw, PCI_DEV_REG2); | ||
| 3439 | return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); | ||
| 3440 | } | ||
| 3441 | |||
| 3442 | static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset) | ||
| 3443 | { | ||
| 3444 | sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset); | ||
| 3445 | |||
| 3446 | while (!(sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F)) | ||
| 3447 | cpu_relax(); | ||
| 3448 | return sky2_pci_read32(hw, cap + PCI_VPD_DATA); | ||
| 3449 | } | ||
| 3450 | |||
| 3451 | static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val) | ||
| 3452 | { | ||
| 3453 | sky2_pci_write32(hw, cap + PCI_VPD_DATA, val); | ||
| 3454 | sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); | ||
| 3455 | do { | ||
| 3456 | cpu_relax(); | ||
| 3457 | } while (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F); | ||
| 3458 | } | ||
| 3459 | |||
| 3460 | static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | ||
| 3461 | u8 *data) | ||
| 3462 | { | ||
| 3463 | struct sky2_port *sky2 = netdev_priv(dev); | ||
| 3464 | int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); | ||
| 3465 | int length = eeprom->len; | ||
| 3466 | u16 offset = eeprom->offset; | ||
| 3467 | |||
| 3468 | if (!cap) | ||
| 3469 | return -EINVAL; | ||
| 3470 | |||
| 3471 | eeprom->magic = SKY2_EEPROM_MAGIC; | ||
| 3472 | |||
| 3473 | while (length > 0) { | ||
| 3474 | u32 val = sky2_vpd_read(sky2->hw, cap, offset); | ||
| 3475 | int n = min_t(int, length, sizeof(val)); | ||
| 3476 | |||
| 3477 | memcpy(data, &val, n); | ||
| 3478 | length -= n; | ||
| 3479 | data += n; | ||
| 3480 | offset += n; | ||
| 3481 | } | ||
| 3482 | return 0; | ||
| 3483 | } | ||
| 3484 | |||
| 3485 | static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | ||
| 3486 | u8 *data) | ||
| 3487 | { | ||
| 3488 | struct sky2_port *sky2 = netdev_priv(dev); | ||
| 3489 | int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); | ||
| 3490 | int length = eeprom->len; | ||
| 3491 | u16 offset = eeprom->offset; | ||
| 3492 | |||
| 3493 | if (!cap) | ||
| 3494 | return -EINVAL; | ||
| 3495 | |||
| 3496 | if (eeprom->magic != SKY2_EEPROM_MAGIC) | ||
| 3497 | return -EINVAL; | ||
| 3498 | |||
| 3499 | while (length > 0) { | ||
| 3500 | u32 val; | ||
| 3501 | int n = min_t(int, length, sizeof(val)); | ||
| 3502 | |||
| 3503 | if (n < sizeof(val)) | ||
| 3504 | val = sky2_vpd_read(sky2->hw, cap, offset); | ||
| 3505 | memcpy(&val, data, n); | ||
| 3506 | |||
| 3507 | sky2_vpd_write(sky2->hw, cap, offset, val); | ||
| 3508 | |||
| 3509 | length -= n; | ||
| 3510 | data += n; | ||
| 3511 | offset += n; | ||
| 3512 | } | ||
| 3513 | return 0; | ||
| 3514 | } | ||
| 3515 | |||
| 3516 | |||
| 3432 | static const struct ethtool_ops sky2_ethtool_ops = { | 3517 | static const struct ethtool_ops sky2_ethtool_ops = { |
| 3433 | .get_settings = sky2_get_settings, | 3518 | .get_settings = sky2_get_settings, |
| 3434 | .set_settings = sky2_set_settings, | 3519 | .set_settings = sky2_set_settings, |
| 3435 | .get_drvinfo = sky2_get_drvinfo, | 3520 | .get_drvinfo = sky2_get_drvinfo, |
| 3436 | .get_wol = sky2_get_wol, | 3521 | .get_wol = sky2_get_wol, |
| 3437 | .set_wol = sky2_set_wol, | 3522 | .set_wol = sky2_set_wol, |
| 3438 | .get_msglevel = sky2_get_msglevel, | 3523 | .get_msglevel = sky2_get_msglevel, |
| 3439 | .set_msglevel = sky2_set_msglevel, | 3524 | .set_msglevel = sky2_set_msglevel, |
| 3440 | .nway_reset = sky2_nway_reset, | 3525 | .nway_reset = sky2_nway_reset, |
| 3441 | .get_regs_len = sky2_get_regs_len, | 3526 | .get_regs_len = sky2_get_regs_len, |
| 3442 | .get_regs = sky2_get_regs, | 3527 | .get_regs = sky2_get_regs, |
| 3443 | .get_link = ethtool_op_get_link, | 3528 | .get_link = ethtool_op_get_link, |
| 3444 | .get_sg = ethtool_op_get_sg, | 3529 | .get_eeprom_len = sky2_get_eeprom_len, |
| 3445 | .set_sg = ethtool_op_set_sg, | 3530 | .get_eeprom = sky2_get_eeprom, |
| 3446 | .get_tx_csum = ethtool_op_get_tx_csum, | 3531 | .set_eeprom = sky2_set_eeprom, |
| 3447 | .set_tx_csum = sky2_set_tx_csum, | 3532 | .get_sg = ethtool_op_get_sg, |
| 3448 | .get_tso = ethtool_op_get_tso, | 3533 | .set_sg = ethtool_op_set_sg, |
| 3449 | .set_tso = sky2_set_tso, | 3534 | .get_tx_csum = ethtool_op_get_tx_csum, |
| 3450 | .get_rx_csum = sky2_get_rx_csum, | 3535 | .set_tx_csum = sky2_set_tx_csum, |
| 3451 | .set_rx_csum = sky2_set_rx_csum, | 3536 | .get_tso = ethtool_op_get_tso, |
| 3452 | .get_strings = sky2_get_strings, | 3537 | .set_tso = sky2_set_tso, |
| 3453 | .get_coalesce = sky2_get_coalesce, | 3538 | .get_rx_csum = sky2_get_rx_csum, |
| 3454 | .set_coalesce = sky2_set_coalesce, | 3539 | .set_rx_csum = sky2_set_rx_csum, |
| 3455 | .get_ringparam = sky2_get_ringparam, | 3540 | .get_strings = sky2_get_strings, |
| 3456 | .set_ringparam = sky2_set_ringparam, | 3541 | .get_coalesce = sky2_get_coalesce, |
| 3542 | .set_coalesce = sky2_set_coalesce, | ||
| 3543 | .get_ringparam = sky2_get_ringparam, | ||
| 3544 | .set_ringparam = sky2_set_ringparam, | ||
| 3457 | .get_pauseparam = sky2_get_pauseparam, | 3545 | .get_pauseparam = sky2_get_pauseparam, |
| 3458 | .set_pauseparam = sky2_set_pauseparam, | 3546 | .set_pauseparam = sky2_set_pauseparam, |
| 3459 | .phys_id = sky2_phys_id, | 3547 | .phys_id = sky2_phys_id, |
| 3460 | .get_stats_count = sky2_get_stats_count, | 3548 | .get_stats_count = sky2_get_stats_count, |
| 3461 | .get_ethtool_stats = sky2_get_ethtool_stats, | 3549 | .get_ethtool_stats = sky2_get_ethtool_stats, |
| 3462 | .get_perm_addr = ethtool_op_get_perm_addr, | 3550 | .get_perm_addr = ethtool_op_get_perm_addr, |
| 3463 | }; | 3551 | }; |
| 3464 | 3552 | ||
| 3553 | #ifdef CONFIG_SKY2_DEBUG | ||
| 3554 | |||
| 3555 | static struct dentry *sky2_debug; | ||
| 3556 | |||
| 3557 | static int sky2_debug_show(struct seq_file *seq, void *v) | ||
| 3558 | { | ||
| 3559 | struct net_device *dev = seq->private; | ||
| 3560 | const struct sky2_port *sky2 = netdev_priv(dev); | ||
| 3561 | const struct sky2_hw *hw = sky2->hw; | ||
| 3562 | unsigned port = sky2->port; | ||
| 3563 | unsigned idx, last; | ||
| 3564 | int sop; | ||
| 3565 | |||
| 3566 | if (!netif_running(dev)) | ||
| 3567 | return -ENETDOWN; | ||
| 3568 | |||
| 3569 | seq_printf(seq, "IRQ src=%x mask=%x control=%x\n", | ||
| 3570 | sky2_read32(hw, B0_ISRC), | ||
| 3571 | sky2_read32(hw, B0_IMSK), | ||
| 3572 | sky2_read32(hw, B0_Y2_SP_ICR)); | ||
| 3573 | |||
| 3574 | netif_poll_disable(hw->dev[0]); | ||
| 3575 | last = sky2_read16(hw, STAT_PUT_IDX); | ||
| 3576 | |||
| 3577 | if (hw->st_idx == last) | ||
| 3578 | seq_puts(seq, "Status ring (empty)\n"); | ||
| 3579 | else { | ||
| 3580 | seq_puts(seq, "Status ring\n"); | ||
| 3581 | for (idx = hw->st_idx; idx != last && idx < STATUS_RING_SIZE; | ||
| 3582 | idx = RING_NEXT(idx, STATUS_RING_SIZE)) { | ||
| 3583 | const struct sky2_status_le *le = hw->st_le + idx; | ||
| 3584 | seq_printf(seq, "[%d] %#x %d %#x\n", | ||
| 3585 | idx, le->opcode, le->length, le->status); | ||
| 3586 | } | ||
| 3587 | seq_puts(seq, "\n"); | ||
| 3588 | } | ||
| 3589 | |||
| 3590 | seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n", | ||
| 3591 | sky2->tx_cons, sky2->tx_prod, | ||
| 3592 | sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), | ||
| 3593 | sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE))); | ||
| 3594 | |||
| 3595 | /* Dump contents of tx ring */ | ||
| 3596 | sop = 1; | ||
| 3597 | for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < TX_RING_SIZE; | ||
| 3598 | idx = RING_NEXT(idx, TX_RING_SIZE)) { | ||
| 3599 | const struct sky2_tx_le *le = sky2->tx_le + idx; | ||
| 3600 | u32 a = le32_to_cpu(le->addr); | ||
| 3601 | |||
| 3602 | if (sop) | ||
| 3603 | seq_printf(seq, "%u:", idx); | ||
| 3604 | sop = 0; | ||
| 3605 | |||
| 3606 | switch(le->opcode & ~HW_OWNER) { | ||
| 3607 | case OP_ADDR64: | ||
| 3608 | seq_printf(seq, " %#x:", a); | ||
| 3609 | break; | ||
| 3610 | case OP_LRGLEN: | ||
| 3611 | seq_printf(seq, " mtu=%d", a); | ||
| 3612 | break; | ||
| 3613 | case OP_VLAN: | ||
| 3614 | seq_printf(seq, " vlan=%d", be16_to_cpu(le->length)); | ||
| 3615 | break; | ||
| 3616 | case OP_TCPLISW: | ||
| 3617 | seq_printf(seq, " csum=%#x", a); | ||
| 3618 | break; | ||
| 3619 | case OP_LARGESEND: | ||
| 3620 | seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length)); | ||
| 3621 | break; | ||
| 3622 | case OP_PACKET: | ||
| 3623 | seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length)); | ||
| 3624 | break; | ||
| 3625 | case OP_BUFFER: | ||
| 3626 | seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length)); | ||
| 3627 | break; | ||
| 3628 | default: | ||
| 3629 | seq_printf(seq, " op=%#x,%#x(%d)", le->opcode, | ||
| 3630 | a, le16_to_cpu(le->length)); | ||
| 3631 | } | ||
| 3632 | |||
| 3633 | if (le->ctrl & EOP) { | ||
| 3634 | seq_putc(seq, '\n'); | ||
| 3635 | sop = 1; | ||
| 3636 | } | ||
| 3637 | } | ||
| 3638 | |||
| 3639 | seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n", | ||
| 3640 | sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)), | ||
| 3641 | last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)), | ||
| 3642 | sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX))); | ||
| 3643 | |||
| 3644 | netif_poll_enable(hw->dev[0]); | ||
| 3645 | return 0; | ||
| 3646 | } | ||
| 3647 | |||
| 3648 | static int sky2_debug_open(struct inode *inode, struct file *file) | ||
| 3649 | { | ||
| 3650 | return single_open(file, sky2_debug_show, inode->i_private); | ||
| 3651 | } | ||
| 3652 | |||
| 3653 | static const struct file_operations sky2_debug_fops = { | ||
| 3654 | .owner = THIS_MODULE, | ||
| 3655 | .open = sky2_debug_open, | ||
| 3656 | .read = seq_read, | ||
| 3657 | .llseek = seq_lseek, | ||
| 3658 | .release = single_release, | ||
| 3659 | }; | ||
| 3660 | |||
| 3661 | /* | ||
| 3662 | * Use network device events to create/remove/rename | ||
| 3663 | * debugfs file entries | ||
| 3664 | */ | ||
| 3665 | static int sky2_device_event(struct notifier_block *unused, | ||
| 3666 | unsigned long event, void *ptr) | ||
| 3667 | { | ||
| 3668 | struct net_device *dev = ptr; | ||
| 3669 | |||
| 3670 | if (dev->open == sky2_up) { | ||
| 3671 | struct sky2_port *sky2 = netdev_priv(dev); | ||
| 3672 | |||
| 3673 | switch(event) { | ||
| 3674 | case NETDEV_CHANGENAME: | ||
| 3675 | if (!netif_running(dev)) | ||
| 3676 | break; | ||
| 3677 | /* fallthrough */ | ||
| 3678 | case NETDEV_DOWN: | ||
| 3679 | case NETDEV_GOING_DOWN: | ||
| 3680 | if (sky2->debugfs) { | ||
| 3681 | printk(KERN_DEBUG PFX "%s: remove debugfs\n", | ||
| 3682 | dev->name); | ||
| 3683 | debugfs_remove(sky2->debugfs); | ||
| 3684 | sky2->debugfs = NULL; | ||
| 3685 | } | ||
| 3686 | |||
| 3687 | if (event != NETDEV_CHANGENAME) | ||
| 3688 | break; | ||
| 3689 | /* fallthrough for changename */ | ||
| 3690 | case NETDEV_UP: | ||
| 3691 | if (sky2_debug) { | ||
| 3692 | struct dentry *d; | ||
| 3693 | d = debugfs_create_file(dev->name, S_IRUGO, | ||
| 3694 | sky2_debug, dev, | ||
| 3695 | &sky2_debug_fops); | ||
| 3696 | if (d == NULL || IS_ERR(d)) | ||
| 3697 | printk(KERN_INFO PFX | ||
| 3698 | "%s: debugfs create failed\n", | ||
| 3699 | dev->name); | ||
| 3700 | else | ||
| 3701 | sky2->debugfs = d; | ||
| 3702 | } | ||
| 3703 | break; | ||
| 3704 | } | ||
| 3705 | } | ||
| 3706 | |||
| 3707 | return NOTIFY_DONE; | ||
| 3708 | } | ||
| 3709 | |||
| 3710 | static struct notifier_block sky2_notifier = { | ||
| 3711 | .notifier_call = sky2_device_event, | ||
| 3712 | }; | ||
| 3713 | |||
| 3714 | |||
| 3715 | static __init void sky2_debug_init(void) | ||
| 3716 | { | ||
| 3717 | struct dentry *ent; | ||
| 3718 | |||
| 3719 | ent = debugfs_create_dir("sky2", NULL); | ||
| 3720 | if (!ent || IS_ERR(ent)) | ||
| 3721 | return; | ||
| 3722 | |||
| 3723 | sky2_debug = ent; | ||
| 3724 | register_netdevice_notifier(&sky2_notifier); | ||
| 3725 | } | ||
| 3726 | |||
| 3727 | static __exit void sky2_debug_cleanup(void) | ||
| 3728 | { | ||
| 3729 | if (sky2_debug) { | ||
| 3730 | unregister_netdevice_notifier(&sky2_notifier); | ||
| 3731 | debugfs_remove(sky2_debug); | ||
| 3732 | sky2_debug = NULL; | ||
| 3733 | } | ||
| 3734 | } | ||
| 3735 | |||
| 3736 | #else | ||
| 3737 | #define sky2_debug_init() | ||
| 3738 | #define sky2_debug_cleanup() | ||
| 3739 | #endif | ||
| 3740 | |||
| 3741 | |||
| 3465 | /* Initialize network device */ | 3742 | /* Initialize network device */ |
| 3466 | static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | 3743 | static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, |
| 3467 | unsigned port, | 3744 | unsigned port, |
| @@ -3536,10 +3813,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
| 3536 | memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); | 3813 | memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); |
| 3537 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); | 3814 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); |
| 3538 | 3815 | ||
| 3539 | /* device is off until link detection */ | ||
| 3540 | netif_carrier_off(dev); | ||
| 3541 | netif_stop_queue(dev); | ||
| 3542 | |||
| 3543 | return dev; | 3816 | return dev; |
| 3544 | } | 3817 | } |
| 3545 | 3818 | ||
| @@ -3956,12 +4229,14 @@ static struct pci_driver sky2_driver = { | |||
| 3956 | 4229 | ||
| 3957 | static int __init sky2_init_module(void) | 4230 | static int __init sky2_init_module(void) |
| 3958 | { | 4231 | { |
| 4232 | sky2_debug_init(); | ||
| 3959 | return pci_register_driver(&sky2_driver); | 4233 | return pci_register_driver(&sky2_driver); |
| 3960 | } | 4234 | } |
| 3961 | 4235 | ||
| 3962 | static void __exit sky2_cleanup_module(void) | 4236 | static void __exit sky2_cleanup_module(void) |
| 3963 | { | 4237 | { |
| 3964 | pci_unregister_driver(&sky2_driver); | 4238 | pci_unregister_driver(&sky2_driver); |
| 4239 | sky2_debug_cleanup(); | ||
| 3965 | } | 4240 | } |
| 3966 | 4241 | ||
| 3967 | module_init(sky2_init_module); | 4242 | module_init(sky2_init_module); |
