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); |