diff options
Diffstat (limited to 'drivers/net/myri10ge/myri10ge.c')
-rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 268 |
1 files changed, 183 insertions, 85 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index bf84849600ce..1d2247554a35 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /************************************************************************* | 1 | /************************************************************************* |
2 | * myri10ge.c: Myricom Myri-10G Ethernet driver. | 2 | * myri10ge.c: Myricom Myri-10G Ethernet driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2005 - 2009 Myricom, Inc. | 4 | * Copyright (C) 2005 - 2011 Myricom, Inc. |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without |
@@ -79,7 +79,7 @@ | |||
79 | #include "myri10ge_mcp.h" | 79 | #include "myri10ge_mcp.h" |
80 | #include "myri10ge_mcp_gen_header.h" | 80 | #include "myri10ge_mcp_gen_header.h" |
81 | 81 | ||
82 | #define MYRI10GE_VERSION_STR "1.5.2-1.459" | 82 | #define MYRI10GE_VERSION_STR "1.5.3-1.534" |
83 | 83 | ||
84 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); | 84 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); |
85 | MODULE_AUTHOR("Maintainer: help@myri.com"); | 85 | MODULE_AUTHOR("Maintainer: help@myri.com"); |
@@ -193,6 +193,7 @@ struct myri10ge_slice_state { | |||
193 | int watchdog_tx_done; | 193 | int watchdog_tx_done; |
194 | int watchdog_tx_req; | 194 | int watchdog_tx_req; |
195 | int watchdog_rx_done; | 195 | int watchdog_rx_done; |
196 | int stuck; | ||
196 | #ifdef CONFIG_MYRI10GE_DCA | 197 | #ifdef CONFIG_MYRI10GE_DCA |
197 | int cached_dca_tag; | 198 | int cached_dca_tag; |
198 | int cpu; | 199 | int cpu; |
@@ -210,7 +211,6 @@ struct myri10ge_priv { | |||
210 | int big_bytes; | 211 | int big_bytes; |
211 | int max_intr_slots; | 212 | int max_intr_slots; |
212 | struct net_device *dev; | 213 | struct net_device *dev; |
213 | spinlock_t stats_lock; | ||
214 | u8 __iomem *sram; | 214 | u8 __iomem *sram; |
215 | int sram_size; | 215 | int sram_size; |
216 | unsigned long board_span; | 216 | unsigned long board_span; |
@@ -377,7 +377,8 @@ static inline void put_be32(__be32 val, __be32 __iomem * p) | |||
377 | __raw_writel((__force __u32) val, (__force void __iomem *)p); | 377 | __raw_writel((__force __u32) val, (__force void __iomem *)p); |
378 | } | 378 | } |
379 | 379 | ||
380 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev); | 380 | static struct rtnl_link_stats64 *myri10ge_get_stats(struct net_device *dev, |
381 | struct rtnl_link_stats64 *stats); | ||
381 | 382 | ||
382 | static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated) | 383 | static void set_fw_name(struct myri10ge_priv *mgp, char *name, bool allocated) |
383 | { | 384 | { |
@@ -1013,7 +1014,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) | |||
1013 | cmd.data2 = i; | 1014 | cmd.data2 = i; |
1014 | status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, | 1015 | status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, |
1015 | &cmd, 0); | 1016 | &cmd, 0); |
1016 | }; | 1017 | } |
1017 | 1018 | ||
1018 | status |= | 1019 | status |= |
1019 | myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0); | 1020 | myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0); |
@@ -1080,11 +1081,14 @@ static int myri10ge_toggle_relaxed(struct pci_dev *pdev, int on) | |||
1080 | int ret, cap, err; | 1081 | int ret, cap, err; |
1081 | u16 ctl; | 1082 | u16 ctl; |
1082 | 1083 | ||
1083 | cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 1084 | cap = pci_pcie_cap(pdev); |
1084 | if (!cap) | 1085 | if (!cap) |
1085 | return 0; | 1086 | return 0; |
1086 | 1087 | ||
1087 | err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); | 1088 | err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); |
1089 | if (err) | ||
1090 | return 0; | ||
1091 | |||
1088 | ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4; | 1092 | ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4; |
1089 | if (ret != on) { | 1093 | if (ret != on) { |
1090 | ctl &= ~PCI_EXP_DEVCTL_RELAX_EN; | 1094 | ctl &= ~PCI_EXP_DEVCTL_RELAX_EN; |
@@ -1139,20 +1143,19 @@ static void myri10ge_setup_dca(struct myri10ge_priv *mgp) | |||
1139 | mgp->ss[i].cpu = -1; | 1143 | mgp->ss[i].cpu = -1; |
1140 | mgp->ss[i].cached_dca_tag = -1; | 1144 | mgp->ss[i].cached_dca_tag = -1; |
1141 | myri10ge_update_dca(&mgp->ss[i]); | 1145 | myri10ge_update_dca(&mgp->ss[i]); |
1142 | } | 1146 | } |
1143 | } | 1147 | } |
1144 | 1148 | ||
1145 | static void myri10ge_teardown_dca(struct myri10ge_priv *mgp) | 1149 | static void myri10ge_teardown_dca(struct myri10ge_priv *mgp) |
1146 | { | 1150 | { |
1147 | struct pci_dev *pdev = mgp->pdev; | 1151 | struct pci_dev *pdev = mgp->pdev; |
1148 | int err; | ||
1149 | 1152 | ||
1150 | if (!mgp->dca_enabled) | 1153 | if (!mgp->dca_enabled) |
1151 | return; | 1154 | return; |
1152 | mgp->dca_enabled = 0; | 1155 | mgp->dca_enabled = 0; |
1153 | if (mgp->relaxed_order) | 1156 | if (mgp->relaxed_order) |
1154 | myri10ge_toggle_relaxed(pdev, 1); | 1157 | myri10ge_toggle_relaxed(pdev, 1); |
1155 | err = dca_remove_requester(&pdev->dev); | 1158 | dca_remove_requester(&pdev->dev); |
1156 | } | 1159 | } |
1157 | 1160 | ||
1158 | static int myri10ge_notify_dca_device(struct device *dev, void *data) | 1161 | static int myri10ge_notify_dca_device(struct device *dev, void *data) |
@@ -1313,7 +1316,7 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev, | |||
1313 | 1316 | ||
1314 | static inline int | 1317 | static inline int |
1315 | myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum, | 1318 | myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum, |
1316 | int lro_enabled) | 1319 | bool lro_enabled) |
1317 | { | 1320 | { |
1318 | struct myri10ge_priv *mgp = ss->mgp; | 1321 | struct myri10ge_priv *mgp = ss->mgp; |
1319 | struct sk_buff *skb; | 1322 | struct sk_buff *skb; |
@@ -1461,7 +1464,8 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index) | |||
1461 | 1464 | ||
1462 | /* start the queue if we've stopped it */ | 1465 | /* start the queue if we've stopped it */ |
1463 | if (netif_tx_queue_stopped(dev_queue) && | 1466 | if (netif_tx_queue_stopped(dev_queue) && |
1464 | tx->req - tx->done < (tx->mask >> 1)) { | 1467 | tx->req - tx->done < (tx->mask >> 1) && |
1468 | ss->mgp->running == MYRI10GE_ETH_RUNNING) { | ||
1465 | tx->wake_queue++; | 1469 | tx->wake_queue++; |
1466 | netif_tx_wake_queue(dev_queue); | 1470 | netif_tx_wake_queue(dev_queue); |
1467 | } | 1471 | } |
@@ -1472,11 +1476,9 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) | |||
1472 | { | 1476 | { |
1473 | struct myri10ge_rx_done *rx_done = &ss->rx_done; | 1477 | struct myri10ge_rx_done *rx_done = &ss->rx_done; |
1474 | struct myri10ge_priv *mgp = ss->mgp; | 1478 | struct myri10ge_priv *mgp = ss->mgp; |
1475 | |||
1476 | unsigned long rx_bytes = 0; | 1479 | unsigned long rx_bytes = 0; |
1477 | unsigned long rx_packets = 0; | 1480 | unsigned long rx_packets = 0; |
1478 | unsigned long rx_ok; | 1481 | unsigned long rx_ok; |
1479 | |||
1480 | int idx = rx_done->idx; | 1482 | int idx = rx_done->idx; |
1481 | int cnt = rx_done->cnt; | 1483 | int cnt = rx_done->cnt; |
1482 | int work_done = 0; | 1484 | int work_done = 0; |
@@ -1529,16 +1531,14 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) | |||
1529 | mgp->link_state = link_up; | 1531 | mgp->link_state = link_up; |
1530 | 1532 | ||
1531 | if (mgp->link_state == MXGEFW_LINK_UP) { | 1533 | if (mgp->link_state == MXGEFW_LINK_UP) { |
1532 | if (netif_msg_link(mgp)) | 1534 | netif_info(mgp, link, mgp->dev, "link up\n"); |
1533 | netdev_info(mgp->dev, "link up\n"); | ||
1534 | netif_carrier_on(mgp->dev); | 1535 | netif_carrier_on(mgp->dev); |
1535 | mgp->link_changes++; | 1536 | mgp->link_changes++; |
1536 | } else { | 1537 | } else { |
1537 | if (netif_msg_link(mgp)) | 1538 | netif_info(mgp, link, mgp->dev, "link %s\n", |
1538 | netdev_info(mgp->dev, "link %s\n", | 1539 | (link_up == MXGEFW_LINK_MYRINET ? |
1539 | link_up == MXGEFW_LINK_MYRINET ? | ||
1540 | "mismatch (Myrinet detected)" : | 1540 | "mismatch (Myrinet detected)" : |
1541 | "down"); | 1541 | "down")); |
1542 | netif_carrier_off(mgp->dev); | 1542 | netif_carrier_off(mgp->dev); |
1543 | mgp->link_changes++; | 1543 | mgp->link_changes++; |
1544 | } | 1544 | } |
@@ -1619,7 +1619,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) | |||
1619 | if (send_done_count != tx->pkt_done) | 1619 | if (send_done_count != tx->pkt_done) |
1620 | myri10ge_tx_done(ss, (int)send_done_count); | 1620 | myri10ge_tx_done(ss, (int)send_done_count); |
1621 | if (unlikely(i > myri10ge_max_irq_loops)) { | 1621 | if (unlikely(i > myri10ge_max_irq_loops)) { |
1622 | netdev_err(mgp->dev, "irq stuck?\n"); | 1622 | netdev_warn(mgp->dev, "irq stuck?\n"); |
1623 | stats->valid = 0; | 1623 | stats->valid = 0; |
1624 | schedule_work(&mgp->watchdog_work); | 1624 | schedule_work(&mgp->watchdog_work); |
1625 | } | 1625 | } |
@@ -1783,9 +1783,8 @@ static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = { | |||
1783 | "----------- slice ---------", | 1783 | "----------- slice ---------", |
1784 | "tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done", | 1784 | "tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done", |
1785 | "rx_small_cnt", "rx_big_cnt", | 1785 | "rx_small_cnt", "rx_big_cnt", |
1786 | "wake_queue", "stop_queue", "tx_linearized", "LRO aggregated", | 1786 | "wake_queue", "stop_queue", "tx_linearized", |
1787 | "LRO flushed", | 1787 | "LRO aggregated", "LRO flushed", "LRO avg aggr", "LRO no_desc", |
1788 | "LRO avg aggr", "LRO no_desc" | ||
1789 | }; | 1788 | }; |
1790 | 1789 | ||
1791 | #define MYRI10GE_NET_STATS_LEN 21 | 1790 | #define MYRI10GE_NET_STATS_LEN 21 |
@@ -1831,13 +1830,15 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, | |||
1831 | { | 1830 | { |
1832 | struct myri10ge_priv *mgp = netdev_priv(netdev); | 1831 | struct myri10ge_priv *mgp = netdev_priv(netdev); |
1833 | struct myri10ge_slice_state *ss; | 1832 | struct myri10ge_slice_state *ss; |
1833 | struct rtnl_link_stats64 link_stats; | ||
1834 | int slice; | 1834 | int slice; |
1835 | int i; | 1835 | int i; |
1836 | 1836 | ||
1837 | /* force stats update */ | 1837 | /* force stats update */ |
1838 | (void)myri10ge_get_stats(netdev); | 1838 | memset(&link_stats, 0, sizeof(link_stats)); |
1839 | (void)myri10ge_get_stats(netdev, &link_stats); | ||
1839 | for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++) | 1840 | for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++) |
1840 | data[i] = ((unsigned long *)&netdev->stats)[i]; | 1841 | data[i] = ((u64 *)&link_stats)[i]; |
1841 | 1842 | ||
1842 | data[i++] = (unsigned int)mgp->tx_boundary; | 1843 | data[i++] = (unsigned int)mgp->tx_boundary; |
1843 | data[i++] = (unsigned int)mgp->wc_enabled; | 1844 | data[i++] = (unsigned int)mgp->wc_enabled; |
@@ -1907,6 +1908,60 @@ static u32 myri10ge_get_msglevel(struct net_device *netdev) | |||
1907 | return mgp->msg_enable; | 1908 | return mgp->msg_enable; |
1908 | } | 1909 | } |
1909 | 1910 | ||
1911 | /* | ||
1912 | * Use a low-level command to change the LED behavior. Rather than | ||
1913 | * blinking (which is the normal case), when identify is used, the | ||
1914 | * yellow LED turns solid. | ||
1915 | */ | ||
1916 | static int myri10ge_led(struct myri10ge_priv *mgp, int on) | ||
1917 | { | ||
1918 | struct mcp_gen_header *hdr; | ||
1919 | struct device *dev = &mgp->pdev->dev; | ||
1920 | size_t hdr_off, pattern_off, hdr_len; | ||
1921 | u32 pattern = 0xfffffffe; | ||
1922 | |||
1923 | /* find running firmware header */ | ||
1924 | hdr_off = swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET)); | ||
1925 | if ((hdr_off & 3) || hdr_off + sizeof(*hdr) > mgp->sram_size) { | ||
1926 | dev_err(dev, "Running firmware has bad header offset (%d)\n", | ||
1927 | (int)hdr_off); | ||
1928 | return -EIO; | ||
1929 | } | ||
1930 | hdr_len = swab32(readl(mgp->sram + hdr_off + | ||
1931 | offsetof(struct mcp_gen_header, header_length))); | ||
1932 | pattern_off = hdr_off + offsetof(struct mcp_gen_header, led_pattern); | ||
1933 | if (pattern_off >= (hdr_len + hdr_off)) { | ||
1934 | dev_info(dev, "Firmware does not support LED identification\n"); | ||
1935 | return -EINVAL; | ||
1936 | } | ||
1937 | if (!on) | ||
1938 | pattern = swab32(readl(mgp->sram + pattern_off + 4)); | ||
1939 | writel(htonl(pattern), mgp->sram + pattern_off); | ||
1940 | return 0; | ||
1941 | } | ||
1942 | |||
1943 | static int | ||
1944 | myri10ge_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) | ||
1945 | { | ||
1946 | struct myri10ge_priv *mgp = netdev_priv(netdev); | ||
1947 | int rc; | ||
1948 | |||
1949 | switch (state) { | ||
1950 | case ETHTOOL_ID_ACTIVE: | ||
1951 | rc = myri10ge_led(mgp, 1); | ||
1952 | break; | ||
1953 | |||
1954 | case ETHTOOL_ID_INACTIVE: | ||
1955 | rc = myri10ge_led(mgp, 0); | ||
1956 | break; | ||
1957 | |||
1958 | default: | ||
1959 | rc = -EINVAL; | ||
1960 | } | ||
1961 | |||
1962 | return rc; | ||
1963 | } | ||
1964 | |||
1910 | static const struct ethtool_ops myri10ge_ethtool_ops = { | 1965 | static const struct ethtool_ops myri10ge_ethtool_ops = { |
1911 | .get_settings = myri10ge_get_settings, | 1966 | .get_settings = myri10ge_get_settings, |
1912 | .get_drvinfo = myri10ge_get_drvinfo, | 1967 | .get_drvinfo = myri10ge_get_drvinfo, |
@@ -1921,6 +1976,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { | |||
1921 | .get_ethtool_stats = myri10ge_get_ethtool_stats, | 1976 | .get_ethtool_stats = myri10ge_get_ethtool_stats, |
1922 | .set_msglevel = myri10ge_set_msglevel, | 1977 | .set_msglevel = myri10ge_set_msglevel, |
1923 | .get_msglevel = myri10ge_get_msglevel, | 1978 | .get_msglevel = myri10ge_get_msglevel, |
1979 | .set_phys_id = myri10ge_phys_id, | ||
1924 | }; | 1980 | }; |
1925 | 1981 | ||
1926 | static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss) | 1982 | static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss) |
@@ -2000,8 +2056,12 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss) | |||
2000 | ss->rx_big.page_offset = MYRI10GE_ALLOC_SIZE; | 2056 | ss->rx_big.page_offset = MYRI10GE_ALLOC_SIZE; |
2001 | ss->rx_small.watchdog_needed = 0; | 2057 | ss->rx_small.watchdog_needed = 0; |
2002 | ss->rx_big.watchdog_needed = 0; | 2058 | ss->rx_big.watchdog_needed = 0; |
2003 | myri10ge_alloc_rx_pages(mgp, &ss->rx_small, | 2059 | if (mgp->small_bytes == 0) { |
2004 | mgp->small_bytes + MXGEFW_PAD, 0); | 2060 | ss->rx_small.fill_cnt = ss->rx_small.mask + 1; |
2061 | } else { | ||
2062 | myri10ge_alloc_rx_pages(mgp, &ss->rx_small, | ||
2063 | mgp->small_bytes + MXGEFW_PAD, 0); | ||
2064 | } | ||
2005 | 2065 | ||
2006 | if (ss->rx_small.fill_cnt < ss->rx_small.mask + 1) { | 2066 | if (ss->rx_small.fill_cnt < ss->rx_small.mask + 1) { |
2007 | netdev_err(dev, "slice-%d: alloced only %d small bufs\n", | 2067 | netdev_err(dev, "slice-%d: alloced only %d small bufs\n", |
@@ -2027,6 +2087,8 @@ abort_with_rx_big_ring: | |||
2027 | } | 2087 | } |
2028 | 2088 | ||
2029 | abort_with_rx_small_ring: | 2089 | abort_with_rx_small_ring: |
2090 | if (mgp->small_bytes == 0) | ||
2091 | ss->rx_small.fill_cnt = ss->rx_small.cnt; | ||
2030 | for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) { | 2092 | for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) { |
2031 | int idx = i & ss->rx_small.mask; | 2093 | int idx = i & ss->rx_small.mask; |
2032 | myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_small.info[idx], | 2094 | myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_small.info[idx], |
@@ -2077,6 +2139,8 @@ static void myri10ge_free_rings(struct myri10ge_slice_state *ss) | |||
2077 | put_page(ss->rx_big.info[idx].page); | 2139 | put_page(ss->rx_big.info[idx].page); |
2078 | } | 2140 | } |
2079 | 2141 | ||
2142 | if (mgp->small_bytes == 0) | ||
2143 | ss->rx_small.fill_cnt = ss->rx_small.cnt; | ||
2080 | for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) { | 2144 | for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) { |
2081 | idx = i & ss->rx_small.mask; | 2145 | idx = i & ss->rx_small.mask; |
2082 | if (i == ss->rx_small.fill_cnt - 1) | 2146 | if (i == ss->rx_small.fill_cnt - 1) |
@@ -2255,7 +2319,7 @@ myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, | |||
2255 | *ip_hdr = iph; | 2319 | *ip_hdr = iph; |
2256 | if (iph->protocol != IPPROTO_TCP) | 2320 | if (iph->protocol != IPPROTO_TCP) |
2257 | return -1; | 2321 | return -1; |
2258 | if (iph->frag_off & htons(IP_MF | IP_OFFSET)) | 2322 | if (ip_is_fragment(iph)) |
2259 | return -1; | 2323 | return -1; |
2260 | *hdr_flags |= LRO_TCP; | 2324 | *hdr_flags |= LRO_TCP; |
2261 | *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); | 2325 | *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); |
@@ -2414,7 +2478,7 @@ static int myri10ge_open(struct net_device *dev) | |||
2414 | mgp->small_bytes = VLAN_ETH_FRAME_LEN; | 2478 | mgp->small_bytes = VLAN_ETH_FRAME_LEN; |
2415 | 2479 | ||
2416 | /* Override the small buffer size? */ | 2480 | /* Override the small buffer size? */ |
2417 | if (myri10ge_small_bytes > 0) | 2481 | if (myri10ge_small_bytes >= 0) |
2418 | mgp->small_bytes = myri10ge_small_bytes; | 2482 | mgp->small_bytes = myri10ge_small_bytes; |
2419 | 2483 | ||
2420 | /* Firmware needs the big buff size as a power of 2. Lie and | 2484 | /* Firmware needs the big buff size as a power of 2. Lie and |
@@ -2976,15 +3040,13 @@ drop: | |||
2976 | return NETDEV_TX_OK; | 3040 | return NETDEV_TX_OK; |
2977 | } | 3041 | } |
2978 | 3042 | ||
2979 | static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) | 3043 | static struct rtnl_link_stats64 *myri10ge_get_stats(struct net_device *dev, |
3044 | struct rtnl_link_stats64 *stats) | ||
2980 | { | 3045 | { |
2981 | struct myri10ge_priv *mgp = netdev_priv(dev); | 3046 | const struct myri10ge_priv *mgp = netdev_priv(dev); |
2982 | struct myri10ge_slice_netstats *slice_stats; | 3047 | const struct myri10ge_slice_netstats *slice_stats; |
2983 | struct net_device_stats *stats = &dev->stats; | ||
2984 | int i; | 3048 | int i; |
2985 | 3049 | ||
2986 | spin_lock(&mgp->stats_lock); | ||
2987 | memset(stats, 0, sizeof(*stats)); | ||
2988 | for (i = 0; i < mgp->num_slices; i++) { | 3050 | for (i = 0; i < mgp->num_slices; i++) { |
2989 | slice_stats = &mgp->ss[i].stats; | 3051 | slice_stats = &mgp->ss[i].stats; |
2990 | stats->rx_packets += slice_stats->rx_packets; | 3052 | stats->rx_packets += slice_stats->rx_packets; |
@@ -2994,7 +3056,6 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) | |||
2994 | stats->rx_dropped += slice_stats->rx_dropped; | 3056 | stats->rx_dropped += slice_stats->rx_dropped; |
2995 | stats->tx_dropped += slice_stats->tx_dropped; | 3057 | stats->tx_dropped += slice_stats->tx_dropped; |
2996 | } | 3058 | } |
2997 | spin_unlock(&mgp->stats_lock); | ||
2998 | return stats; | 3059 | return stats; |
2999 | } | 3060 | } |
3000 | 3061 | ||
@@ -3127,7 +3188,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) | |||
3127 | { | 3188 | { |
3128 | struct pci_dev *bridge = mgp->pdev->bus->self; | 3189 | struct pci_dev *bridge = mgp->pdev->bus->self; |
3129 | struct device *dev = &mgp->pdev->dev; | 3190 | struct device *dev = &mgp->pdev->dev; |
3130 | unsigned cap; | 3191 | int cap; |
3131 | unsigned err_cap; | 3192 | unsigned err_cap; |
3132 | u16 val; | 3193 | u16 val; |
3133 | u8 ext_type; | 3194 | u8 ext_type; |
@@ -3137,7 +3198,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) | |||
3137 | return; | 3198 | return; |
3138 | 3199 | ||
3139 | /* check that the bridge is a root port */ | 3200 | /* check that the bridge is a root port */ |
3140 | cap = pci_find_capability(bridge, PCI_CAP_ID_EXP); | 3201 | cap = pci_pcie_cap(bridge); |
3141 | pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val); | 3202 | pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val); |
3142 | ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; | 3203 | ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; |
3143 | if (ext_type != PCI_EXP_TYPE_ROOT_PORT) { | 3204 | if (ext_type != PCI_EXP_TYPE_ROOT_PORT) { |
@@ -3155,8 +3216,7 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) | |||
3155 | " to force ECRC\n"); | 3216 | " to force ECRC\n"); |
3156 | return; | 3217 | return; |
3157 | } | 3218 | } |
3158 | cap = | 3219 | cap = pci_pcie_cap(bridge); |
3159 | pci_find_capability(bridge, PCI_CAP_ID_EXP); | ||
3160 | pci_read_config_word(bridge, | 3220 | pci_read_config_word(bridge, |
3161 | cap + PCI_CAP_FLAGS, &val); | 3221 | cap + PCI_CAP_FLAGS, &val); |
3162 | ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; | 3222 | ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; |
@@ -3266,7 +3326,6 @@ abort: | |||
3266 | /* fall back to using the unaligned firmware */ | 3326 | /* fall back to using the unaligned firmware */ |
3267 | mgp->tx_boundary = 2048; | 3327 | mgp->tx_boundary = 2048; |
3268 | set_fw_name(mgp, myri10ge_fw_unaligned, false); | 3328 | set_fw_name(mgp, myri10ge_fw_unaligned, false); |
3269 | |||
3270 | } | 3329 | } |
3271 | 3330 | ||
3272 | static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | 3331 | static void myri10ge_select_firmware(struct myri10ge_priv *mgp) |
@@ -3277,7 +3336,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
3277 | int link_width, exp_cap; | 3336 | int link_width, exp_cap; |
3278 | u16 lnk; | 3337 | u16 lnk; |
3279 | 3338 | ||
3280 | exp_cap = pci_find_capability(mgp->pdev, PCI_CAP_ID_EXP); | 3339 | exp_cap = pci_pcie_cap(mgp->pdev); |
3281 | pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk); | 3340 | pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk); |
3282 | link_width = (lnk >> 4) & 0x3f; | 3341 | link_width = (lnk >> 4) & 0x3f; |
3283 | 3342 | ||
@@ -3327,6 +3386,26 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) | |||
3327 | mgp->fw_name); | 3386 | mgp->fw_name); |
3328 | } | 3387 | } |
3329 | 3388 | ||
3389 | static void myri10ge_mask_surprise_down(struct pci_dev *pdev) | ||
3390 | { | ||
3391 | struct pci_dev *bridge = pdev->bus->self; | ||
3392 | int cap; | ||
3393 | u32 mask; | ||
3394 | |||
3395 | if (bridge == NULL) | ||
3396 | return; | ||
3397 | |||
3398 | cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR); | ||
3399 | if (cap) { | ||
3400 | /* a sram parity error can cause a surprise link | ||
3401 | * down; since we expect and can recover from sram | ||
3402 | * parity errors, mask surprise link down events */ | ||
3403 | pci_read_config_dword(bridge, cap + PCI_ERR_UNCOR_MASK, &mask); | ||
3404 | mask |= 0x20; | ||
3405 | pci_write_config_dword(bridge, cap + PCI_ERR_UNCOR_MASK, mask); | ||
3406 | } | ||
3407 | } | ||
3408 | |||
3330 | #ifdef CONFIG_PM | 3409 | #ifdef CONFIG_PM |
3331 | static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) | 3410 | static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) |
3332 | { | 3411 | { |
@@ -3422,6 +3501,42 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) | |||
3422 | return reboot; | 3501 | return reboot; |
3423 | } | 3502 | } |
3424 | 3503 | ||
3504 | static void | ||
3505 | myri10ge_check_slice(struct myri10ge_slice_state *ss, int *reset_needed, | ||
3506 | int *busy_slice_cnt, u32 rx_pause_cnt) | ||
3507 | { | ||
3508 | struct myri10ge_priv *mgp = ss->mgp; | ||
3509 | int slice = ss - mgp->ss; | ||
3510 | |||
3511 | if (ss->tx.req != ss->tx.done && | ||
3512 | ss->tx.done == ss->watchdog_tx_done && | ||
3513 | ss->watchdog_tx_req != ss->watchdog_tx_done) { | ||
3514 | /* nic seems like it might be stuck.. */ | ||
3515 | if (rx_pause_cnt != mgp->watchdog_pause) { | ||
3516 | if (net_ratelimit()) | ||
3517 | netdev_warn(mgp->dev, "slice %d: TX paused, " | ||
3518 | "check link partner\n", slice); | ||
3519 | } else { | ||
3520 | netdev_warn(mgp->dev, | ||
3521 | "slice %d: TX stuck %d %d %d %d %d %d\n", | ||
3522 | slice, ss->tx.queue_active, ss->tx.req, | ||
3523 | ss->tx.done, ss->tx.pkt_start, | ||
3524 | ss->tx.pkt_done, | ||
3525 | (int)ntohl(mgp->ss[slice].fw_stats-> | ||
3526 | send_done_count)); | ||
3527 | *reset_needed = 1; | ||
3528 | ss->stuck = 1; | ||
3529 | } | ||
3530 | } | ||
3531 | if (ss->watchdog_tx_done != ss->tx.done || | ||
3532 | ss->watchdog_rx_done != ss->rx_done.cnt) { | ||
3533 | *busy_slice_cnt += 1; | ||
3534 | } | ||
3535 | ss->watchdog_tx_done = ss->tx.done; | ||
3536 | ss->watchdog_tx_req = ss->tx.req; | ||
3537 | ss->watchdog_rx_done = ss->rx_done.cnt; | ||
3538 | } | ||
3539 | |||
3425 | /* | 3540 | /* |
3426 | * This watchdog is used to check whether the board has suffered | 3541 | * This watchdog is used to check whether the board has suffered |
3427 | * from a parity error and needs to be recovered. | 3542 | * from a parity error and needs to be recovered. |
@@ -3430,10 +3545,12 @@ static void myri10ge_watchdog(struct work_struct *work) | |||
3430 | { | 3545 | { |
3431 | struct myri10ge_priv *mgp = | 3546 | struct myri10ge_priv *mgp = |
3432 | container_of(work, struct myri10ge_priv, watchdog_work); | 3547 | container_of(work, struct myri10ge_priv, watchdog_work); |
3433 | struct myri10ge_tx_buf *tx; | 3548 | struct myri10ge_slice_state *ss; |
3434 | u32 reboot; | 3549 | u32 reboot, rx_pause_cnt; |
3435 | int status, rebooted; | 3550 | int status, rebooted; |
3436 | int i; | 3551 | int i; |
3552 | int reset_needed = 0; | ||
3553 | int busy_slice_cnt = 0; | ||
3437 | u16 cmd, vendor; | 3554 | u16 cmd, vendor; |
3438 | 3555 | ||
3439 | mgp->watchdog_resets++; | 3556 | mgp->watchdog_resets++; |
@@ -3445,8 +3562,7 @@ static void myri10ge_watchdog(struct work_struct *work) | |||
3445 | * For now, just report it */ | 3562 | * For now, just report it */ |
3446 | reboot = myri10ge_read_reboot(mgp); | 3563 | reboot = myri10ge_read_reboot(mgp); |
3447 | netdev_err(mgp->dev, "NIC rebooted (0x%x),%s resetting\n", | 3564 | netdev_err(mgp->dev, "NIC rebooted (0x%x),%s resetting\n", |
3448 | reboot, | 3565 | reboot, myri10ge_reset_recover ? "" : " not"); |
3449 | myri10ge_reset_recover ? "" : " not"); | ||
3450 | if (myri10ge_reset_recover == 0) | 3566 | if (myri10ge_reset_recover == 0) |
3451 | return; | 3567 | return; |
3452 | rtnl_lock(); | 3568 | rtnl_lock(); |
@@ -3478,23 +3594,24 @@ static void myri10ge_watchdog(struct work_struct *work) | |||
3478 | return; | 3594 | return; |
3479 | } | 3595 | } |
3480 | } | 3596 | } |
3481 | /* Perhaps it is a software error. Try to reset */ | 3597 | /* Perhaps it is a software error. See if stuck slice |
3482 | 3598 | * has recovered, reset if not */ | |
3483 | netdev_err(mgp->dev, "device timeout, resetting\n"); | 3599 | rx_pause_cnt = ntohl(mgp->ss[0].fw_stats->dropped_pause); |
3484 | for (i = 0; i < mgp->num_slices; i++) { | 3600 | for (i = 0; i < mgp->num_slices; i++) { |
3485 | tx = &mgp->ss[i].tx; | 3601 | ss = mgp->ss; |
3486 | netdev_err(mgp->dev, "(%d): %d %d %d %d %d %d\n", | 3602 | if (ss->stuck) { |
3487 | i, tx->queue_active, tx->req, | 3603 | myri10ge_check_slice(ss, &reset_needed, |
3488 | tx->done, tx->pkt_start, tx->pkt_done, | 3604 | &busy_slice_cnt, |
3489 | (int)ntohl(mgp->ss[i].fw_stats-> | 3605 | rx_pause_cnt); |
3490 | send_done_count)); | 3606 | ss->stuck = 0; |
3491 | msleep(2000); | 3607 | } |
3492 | netdev_info(mgp->dev, "(%d): %d %d %d %d %d %d\n", | ||
3493 | i, tx->queue_active, tx->req, | ||
3494 | tx->done, tx->pkt_start, tx->pkt_done, | ||
3495 | (int)ntohl(mgp->ss[i].fw_stats-> | ||
3496 | send_done_count)); | ||
3497 | } | 3608 | } |
3609 | if (!reset_needed) { | ||
3610 | netdev_dbg(mgp->dev, "not resetting\n"); | ||
3611 | return; | ||
3612 | } | ||
3613 | |||
3614 | netdev_err(mgp->dev, "device timeout, resetting\n"); | ||
3498 | } | 3615 | } |
3499 | 3616 | ||
3500 | if (!rebooted) { | 3617 | if (!rebooted) { |
@@ -3547,27 +3664,8 @@ static void myri10ge_watchdog_timer(unsigned long arg) | |||
3547 | myri10ge_fill_thresh) | 3664 | myri10ge_fill_thresh) |
3548 | ss->rx_big.watchdog_needed = 0; | 3665 | ss->rx_big.watchdog_needed = 0; |
3549 | } | 3666 | } |
3550 | 3667 | myri10ge_check_slice(ss, &reset_needed, &busy_slice_cnt, | |
3551 | if (ss->tx.req != ss->tx.done && | 3668 | rx_pause_cnt); |
3552 | ss->tx.done == ss->watchdog_tx_done && | ||
3553 | ss->watchdog_tx_req != ss->watchdog_tx_done) { | ||
3554 | /* nic seems like it might be stuck.. */ | ||
3555 | if (rx_pause_cnt != mgp->watchdog_pause) { | ||
3556 | if (net_ratelimit()) | ||
3557 | netdev_err(mgp->dev, "slice %d: TX paused, check link partner\n", | ||
3558 | i); | ||
3559 | } else { | ||
3560 | netdev_warn(mgp->dev, "slice %d stuck:", i); | ||
3561 | reset_needed = 1; | ||
3562 | } | ||
3563 | } | ||
3564 | if (ss->watchdog_tx_done != ss->tx.done || | ||
3565 | ss->watchdog_rx_done != ss->rx_done.cnt) { | ||
3566 | busy_slice_cnt++; | ||
3567 | } | ||
3568 | ss->watchdog_tx_done = ss->tx.done; | ||
3569 | ss->watchdog_tx_req = ss->tx.req; | ||
3570 | ss->watchdog_rx_done = ss->rx_done.cnt; | ||
3571 | } | 3669 | } |
3572 | /* if we've sent or received no traffic, poll the NIC to | 3670 | /* if we've sent or received no traffic, poll the NIC to |
3573 | * ensure it is still there. Otherwise, we risk not noticing | 3671 | * ensure it is still there. Otherwise, we risk not noticing |
@@ -3613,8 +3711,8 @@ static void myri10ge_free_slices(struct myri10ge_priv *mgp) | |||
3613 | dma_free_coherent(&pdev->dev, bytes, | 3711 | dma_free_coherent(&pdev->dev, bytes, |
3614 | ss->fw_stats, ss->fw_stats_bus); | 3712 | ss->fw_stats, ss->fw_stats_bus); |
3615 | ss->fw_stats = NULL; | 3713 | ss->fw_stats = NULL; |
3616 | netif_napi_del(&ss->napi); | ||
3617 | } | 3714 | } |
3715 | netif_napi_del(&ss->napi); | ||
3618 | } | 3716 | } |
3619 | kfree(mgp->ss); | 3717 | kfree(mgp->ss); |
3620 | mgp->ss = NULL; | 3718 | mgp->ss = NULL; |
@@ -3790,7 +3888,7 @@ static const struct net_device_ops myri10ge_netdev_ops = { | |||
3790 | .ndo_open = myri10ge_open, | 3888 | .ndo_open = myri10ge_open, |
3791 | .ndo_stop = myri10ge_close, | 3889 | .ndo_stop = myri10ge_close, |
3792 | .ndo_start_xmit = myri10ge_xmit, | 3890 | .ndo_start_xmit = myri10ge_xmit, |
3793 | .ndo_get_stats = myri10ge_get_stats, | 3891 | .ndo_get_stats64 = myri10ge_get_stats, |
3794 | .ndo_validate_addr = eth_validate_addr, | 3892 | .ndo_validate_addr = eth_validate_addr, |
3795 | .ndo_change_mtu = myri10ge_change_mtu, | 3893 | .ndo_change_mtu = myri10ge_change_mtu, |
3796 | .ndo_fix_features = myri10ge_fix_features, | 3894 | .ndo_fix_features = myri10ge_fix_features, |
@@ -3845,6 +3943,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3845 | goto abort_with_enabled; | 3943 | goto abort_with_enabled; |
3846 | } | 3944 | } |
3847 | 3945 | ||
3946 | myri10ge_mask_surprise_down(pdev); | ||
3848 | pci_set_master(pdev); | 3947 | pci_set_master(pdev); |
3849 | dac_enabled = 1; | 3948 | dac_enabled = 1; |
3850 | status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); | 3949 | status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); |
@@ -3964,7 +4063,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3964 | setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer, | 4063 | setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer, |
3965 | (unsigned long)mgp); | 4064 | (unsigned long)mgp); |
3966 | 4065 | ||
3967 | spin_lock_init(&mgp->stats_lock); | ||
3968 | SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); | 4066 | SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); |
3969 | INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog); | 4067 | INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog); |
3970 | status = register_netdev(netdev); | 4068 | status = register_netdev(netdev); |