diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 187 |
1 files changed, 116 insertions, 71 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 4a009b7b1777..238c2ca34da6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/ethtool.h> | 32 | #include <linux/ethtool.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/ip.h> | 34 | #include <linux/ip.h> |
35 | #include <net/ip.h> | ||
35 | #include <linux/tcp.h> | 36 | #include <linux/tcp.h> |
36 | #include <linux/in.h> | 37 | #include <linux/in.h> |
37 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
@@ -49,7 +50,7 @@ | |||
49 | #include "sky2.h" | 50 | #include "sky2.h" |
50 | 51 | ||
51 | #define DRV_NAME "sky2" | 52 | #define DRV_NAME "sky2" |
52 | #define DRV_VERSION "1.13" | 53 | #define DRV_VERSION "1.14" |
53 | #define PFX DRV_NAME " " | 54 | #define PFX DRV_NAME " " |
54 | 55 | ||
55 | /* | 56 | /* |
@@ -123,7 +124,10 @@ static const struct pci_device_id sky2_id_table[] = { | |||
123 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ | 124 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ |
124 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ | 125 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ |
125 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ | 126 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ |
127 | #ifdef broken | ||
128 | /* This device causes data corruption problems that are not resolved */ | ||
126 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ | 129 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ |
130 | #endif | ||
127 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ | 131 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ |
128 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ | 132 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ |
129 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ | 133 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ |
@@ -740,12 +744,17 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
740 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { | 744 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { |
741 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); | 745 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); |
742 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); | 746 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); |
743 | if (hw->dev[port]->mtu > ETH_DATA_LEN) { | 747 | |
744 | /* set Tx GMAC FIFO Almost Empty Threshold */ | 748 | /* set Tx GMAC FIFO Almost Empty Threshold */ |
745 | sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), 0x180); | 749 | sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), |
746 | /* Disable Store & Forward mode for TX */ | 750 | (ECU_JUMBO_WM << 16) | ECU_AE_THR); |
747 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS); | 751 | |
748 | } | 752 | if (hw->dev[port]->mtu > ETH_DATA_LEN) |
753 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | ||
754 | TX_JUMBO_ENA | TX_STFW_DIS); | ||
755 | else | ||
756 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | ||
757 | TX_JUMBO_DIS | TX_STFW_ENA); | ||
749 | } | 758 | } |
750 | 759 | ||
751 | } | 760 | } |
@@ -1278,7 +1287,7 @@ static int sky2_up(struct net_device *dev) | |||
1278 | /* Set almost empty threshold */ | 1287 | /* Set almost empty threshold */ |
1279 | if (hw->chip_id == CHIP_ID_YUKON_EC_U | 1288 | if (hw->chip_id == CHIP_ID_YUKON_EC_U |
1280 | && hw->chip_rev == CHIP_REV_YU_EC_U_A0) | 1289 | && hw->chip_rev == CHIP_REV_YU_EC_U_A0) |
1281 | sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0); | 1290 | sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), ECU_TXFF_LEV); |
1282 | 1291 | ||
1283 | sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, | 1292 | sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, |
1284 | TX_RING_SIZE - 1); | 1293 | TX_RING_SIZE - 1); |
@@ -1383,8 +1392,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1383 | /* Check for TCP Segmentation Offload */ | 1392 | /* Check for TCP Segmentation Offload */ |
1384 | mss = skb_shinfo(skb)->gso_size; | 1393 | mss = skb_shinfo(skb)->gso_size; |
1385 | if (mss != 0) { | 1394 | if (mss != 0) { |
1386 | mss += ((skb->h.th->doff - 5) * 4); /* TCP options */ | 1395 | mss += tcp_optlen(skb); /* TCP options */ |
1387 | mss += (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); | 1396 | mss += ip_hdrlen(skb) + sizeof(struct tcphdr); |
1388 | mss += ETH_HLEN; | 1397 | mss += ETH_HLEN; |
1389 | 1398 | ||
1390 | if (mss != sky2->tx_last_mss) { | 1399 | if (mss != sky2->tx_last_mss) { |
@@ -1412,14 +1421,14 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1412 | 1421 | ||
1413 | /* Handle TCP checksum offload */ | 1422 | /* Handle TCP checksum offload */ |
1414 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 1423 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
1415 | unsigned offset = skb->h.raw - skb->data; | 1424 | const unsigned offset = skb_transport_offset(skb); |
1416 | u32 tcpsum; | 1425 | u32 tcpsum; |
1417 | 1426 | ||
1418 | tcpsum = offset << 16; /* sum start */ | 1427 | tcpsum = offset << 16; /* sum start */ |
1419 | tcpsum |= offset + skb->csum_offset; /* sum write */ | 1428 | tcpsum |= offset + skb->csum_offset; /* sum write */ |
1420 | 1429 | ||
1421 | ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; | 1430 | ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; |
1422 | if (skb->nh.iph->protocol == IPPROTO_UDP) | 1431 | if (ip_hdr(skb)->protocol == IPPROTO_UDP) |
1423 | ctrl |= UDPTCP; | 1432 | ctrl |= UDPTCP; |
1424 | 1433 | ||
1425 | if (tcpsum != sky2->tx_tcpsum) { | 1434 | if (tcpsum != sky2->tx_tcpsum) { |
@@ -1584,13 +1593,6 @@ static int sky2_down(struct net_device *dev) | |||
1584 | sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), | 1593 | sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), |
1585 | RB_RST_SET | RB_DIS_OP_MD); | 1594 | RB_RST_SET | RB_DIS_OP_MD); |
1586 | 1595 | ||
1587 | /* WA for dev. #4.209 */ | ||
1588 | if (hw->chip_id == CHIP_ID_YUKON_EC_U | ||
1589 | && (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) | ||
1590 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | ||
1591 | sky2->speed != SPEED_1000 ? | ||
1592 | TX_STFW_ENA : TX_STFW_DIS); | ||
1593 | |||
1594 | ctrl = gma_read16(hw, port, GM_GP_CTRL); | 1596 | ctrl = gma_read16(hw, port, GM_GP_CTRL); |
1595 | ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA); | 1597 | ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA); |
1596 | gma_write16(hw, port, GM_GP_CTRL, ctrl); | 1598 | gma_write16(hw, port, GM_GP_CTRL, ctrl); |
@@ -1890,6 +1892,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1890 | { | 1892 | { |
1891 | struct sky2_port *sky2 = netdev_priv(dev); | 1893 | struct sky2_port *sky2 = netdev_priv(dev); |
1892 | struct sky2_hw *hw = sky2->hw; | 1894 | struct sky2_hw *hw = sky2->hw; |
1895 | unsigned port = sky2->port; | ||
1893 | int err; | 1896 | int err; |
1894 | u16 ctl, mode; | 1897 | u16 ctl, mode; |
1895 | u32 imask; | 1898 | u32 imask; |
@@ -1897,9 +1900,8 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1897 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) | 1900 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) |
1898 | return -EINVAL; | 1901 | return -EINVAL; |
1899 | 1902 | ||
1900 | /* TSO on Yukon Ultra and MTU > 1500 not supported */ | 1903 | if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE) |
1901 | if (hw->chip_id == CHIP_ID_YUKON_EC_U && new_mtu > ETH_DATA_LEN) | 1904 | return -EINVAL; |
1902 | dev->features &= ~NETIF_F_TSO; | ||
1903 | 1905 | ||
1904 | if (!netif_running(dev)) { | 1906 | if (!netif_running(dev)) { |
1905 | dev->mtu = new_mtu; | 1907 | dev->mtu = new_mtu; |
@@ -1915,8 +1917,18 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1915 | 1917 | ||
1916 | synchronize_irq(hw->pdev->irq); | 1918 | synchronize_irq(hw->pdev->irq); |
1917 | 1919 | ||
1918 | ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); | 1920 | if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { |
1919 | gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); | 1921 | if (new_mtu > ETH_DATA_LEN) { |
1922 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | ||
1923 | TX_JUMBO_ENA | TX_STFW_DIS); | ||
1924 | dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; | ||
1925 | } else | ||
1926 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | ||
1927 | TX_JUMBO_DIS | TX_STFW_ENA); | ||
1928 | } | ||
1929 | |||
1930 | ctl = gma_read16(hw, port, GM_GP_CTRL); | ||
1931 | gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); | ||
1920 | sky2_rx_stop(sky2); | 1932 | sky2_rx_stop(sky2); |
1921 | sky2_rx_clean(sky2); | 1933 | sky2_rx_clean(sky2); |
1922 | 1934 | ||
@@ -1928,9 +1940,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1928 | if (dev->mtu > ETH_DATA_LEN) | 1940 | if (dev->mtu > ETH_DATA_LEN) |
1929 | mode |= GM_SMOD_JUMBO_ENA; | 1941 | mode |= GM_SMOD_JUMBO_ENA; |
1930 | 1942 | ||
1931 | gma_write16(hw, sky2->port, GM_SERIAL_MODE, mode); | 1943 | gma_write16(hw, port, GM_SERIAL_MODE, mode); |
1932 | 1944 | ||
1933 | sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); | 1945 | sky2_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD); |
1934 | 1946 | ||
1935 | err = sky2_rx_start(sky2); | 1947 | err = sky2_rx_start(sky2); |
1936 | sky2_write32(hw, B0_IMSK, imask); | 1948 | sky2_write32(hw, B0_IMSK, imask); |
@@ -1938,7 +1950,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1938 | if (err) | 1950 | if (err) |
1939 | dev_close(dev); | 1951 | dev_close(dev); |
1940 | else { | 1952 | else { |
1941 | gma_write16(hw, sky2->port, GM_GP_CTRL, ctl); | 1953 | gma_write16(hw, port, GM_GP_CTRL, ctl); |
1942 | 1954 | ||
1943 | netif_poll_enable(hw->dev[0]); | 1955 | netif_poll_enable(hw->dev[0]); |
1944 | netif_wake_queue(dev); | 1956 | netif_wake_queue(dev); |
@@ -1959,7 +1971,7 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2, | |||
1959 | skb_reserve(skb, 2); | 1971 | skb_reserve(skb, 2); |
1960 | pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr, | 1972 | pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->data_addr, |
1961 | length, PCI_DMA_FROMDEVICE); | 1973 | length, PCI_DMA_FROMDEVICE); |
1962 | memcpy(skb->data, re->skb->data, length); | 1974 | skb_copy_from_linear_data(re->skb, skb->data, length); |
1963 | skb->ip_summed = re->skb->ip_summed; | 1975 | skb->ip_summed = re->skb->ip_summed; |
1964 | skb->csum = re->skb->csum; | 1976 | skb->csum = re->skb->csum; |
1965 | pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr, | 1977 | pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr, |
@@ -2340,26 +2352,22 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) | |||
2340 | } | 2352 | } |
2341 | } | 2353 | } |
2342 | 2354 | ||
2343 | /* This should never happen it is a fatal situation */ | 2355 | /* This should never happen it is a bug. */ |
2344 | static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | 2356 | static void sky2_le_error(struct sky2_hw *hw, unsigned port, |
2345 | const char *rxtx, u32 mask) | 2357 | u16 q, unsigned ring_size) |
2346 | { | 2358 | { |
2347 | struct net_device *dev = hw->dev[port]; | 2359 | struct net_device *dev = hw->dev[port]; |
2348 | struct sky2_port *sky2 = netdev_priv(dev); | 2360 | struct sky2_port *sky2 = netdev_priv(dev); |
2349 | u32 imask; | 2361 | unsigned idx; |
2350 | 2362 | const u64 *le = (q == Q_R1 || q == Q_R2) | |
2351 | printk(KERN_ERR PFX "%s: %s descriptor error (hardware problem)\n", | 2363 | ? (u64 *) sky2->rx_le : (u64 *) sky2->tx_le; |
2352 | dev ? dev->name : "<not registered>", rxtx); | ||
2353 | 2364 | ||
2354 | imask = sky2_read32(hw, B0_IMSK); | 2365 | idx = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX)); |
2355 | imask &= ~mask; | 2366 | printk(KERN_ERR PFX "%s: descriptor error q=%#x get=%u [%llx] put=%u\n", |
2356 | sky2_write32(hw, B0_IMSK, imask); | 2367 | dev->name, (unsigned) q, idx, (unsigned long long) le[idx], |
2368 | (unsigned) sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX))); | ||
2357 | 2369 | ||
2358 | if (dev) { | 2370 | sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); |
2359 | spin_lock(&sky2->phy_lock); | ||
2360 | sky2_link_down(sky2); | ||
2361 | spin_unlock(&sky2->phy_lock); | ||
2362 | } | ||
2363 | } | 2371 | } |
2364 | 2372 | ||
2365 | /* If idle then force a fake soft NAPI poll once a second | 2373 | /* If idle then force a fake soft NAPI poll once a second |
@@ -2383,23 +2391,15 @@ static void sky2_idle(unsigned long arg) | |||
2383 | mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout)); | 2391 | mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout)); |
2384 | } | 2392 | } |
2385 | 2393 | ||
2386 | 2394 | /* Hardware/software error handling */ | |
2387 | static int sky2_poll(struct net_device *dev0, int *budget) | 2395 | static void sky2_err_intr(struct sky2_hw *hw, u32 status) |
2388 | { | 2396 | { |
2389 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2397 | if (net_ratelimit()) |
2390 | int work_limit = min(dev0->quota, *budget); | 2398 | dev_warn(&hw->pdev->dev, "error interrupt status=%#x\n", status); |
2391 | int work_done = 0; | ||
2392 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | ||
2393 | 2399 | ||
2394 | if (status & Y2_IS_HW_ERR) | 2400 | if (status & Y2_IS_HW_ERR) |
2395 | sky2_hw_intr(hw); | 2401 | sky2_hw_intr(hw); |
2396 | 2402 | ||
2397 | if (status & Y2_IS_IRQ_PHY1) | ||
2398 | sky2_phy_intr(hw, 0); | ||
2399 | |||
2400 | if (status & Y2_IS_IRQ_PHY2) | ||
2401 | sky2_phy_intr(hw, 1); | ||
2402 | |||
2403 | if (status & Y2_IS_IRQ_MAC1) | 2403 | if (status & Y2_IS_IRQ_MAC1) |
2404 | sky2_mac_intr(hw, 0); | 2404 | sky2_mac_intr(hw, 0); |
2405 | 2405 | ||
@@ -2407,16 +2407,33 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2407 | sky2_mac_intr(hw, 1); | 2407 | sky2_mac_intr(hw, 1); |
2408 | 2408 | ||
2409 | if (status & Y2_IS_CHK_RX1) | 2409 | if (status & Y2_IS_CHK_RX1) |
2410 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); | 2410 | sky2_le_error(hw, 0, Q_R1, RX_LE_SIZE); |
2411 | 2411 | ||
2412 | if (status & Y2_IS_CHK_RX2) | 2412 | if (status & Y2_IS_CHK_RX2) |
2413 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); | 2413 | sky2_le_error(hw, 1, Q_R2, RX_LE_SIZE); |
2414 | 2414 | ||
2415 | if (status & Y2_IS_CHK_TXA1) | 2415 | if (status & Y2_IS_CHK_TXA1) |
2416 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); | 2416 | sky2_le_error(hw, 0, Q_XA1, TX_RING_SIZE); |
2417 | 2417 | ||
2418 | if (status & Y2_IS_CHK_TXA2) | 2418 | if (status & Y2_IS_CHK_TXA2) |
2419 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | 2419 | sky2_le_error(hw, 1, Q_XA2, TX_RING_SIZE); |
2420 | } | ||
2421 | |||
2422 | static int sky2_poll(struct net_device *dev0, int *budget) | ||
2423 | { | ||
2424 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | ||
2425 | int work_limit = min(dev0->quota, *budget); | ||
2426 | int work_done = 0; | ||
2427 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | ||
2428 | |||
2429 | if (unlikely(status & Y2_IS_ERROR)) | ||
2430 | sky2_err_intr(hw, status); | ||
2431 | |||
2432 | if (status & Y2_IS_IRQ_PHY1) | ||
2433 | sky2_phy_intr(hw, 0); | ||
2434 | |||
2435 | if (status & Y2_IS_IRQ_PHY2) | ||
2436 | sky2_phy_intr(hw, 1); | ||
2420 | 2437 | ||
2421 | work_done = sky2_status_intr(hw, work_limit); | 2438 | work_done = sky2_status_intr(hw, work_limit); |
2422 | if (work_done < work_limit) { | 2439 | if (work_done < work_limit) { |
@@ -2534,16 +2551,14 @@ static void sky2_reset(struct sky2_hw *hw) | |||
2534 | int i; | 2551 | int i; |
2535 | 2552 | ||
2536 | /* disable ASF */ | 2553 | /* disable ASF */ |
2537 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | 2554 | if (hw->chip_id == CHIP_ID_YUKON_EX) { |
2538 | if (hw->chip_id == CHIP_ID_YUKON_EX) { | 2555 | status = sky2_read16(hw, HCU_CCSR); |
2539 | status = sky2_read16(hw, HCU_CCSR); | 2556 | status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE | |
2540 | status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE | | 2557 | HCU_CCSR_UC_STATE_MSK); |
2541 | HCU_CCSR_UC_STATE_MSK); | 2558 | sky2_write16(hw, HCU_CCSR, status); |
2542 | sky2_write16(hw, HCU_CCSR, status); | 2559 | } else |
2543 | } else | 2560 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); |
2544 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | 2561 | sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); |
2545 | sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); | ||
2546 | } | ||
2547 | 2562 | ||
2548 | /* do a SW reset */ | 2563 | /* do a SW reset */ |
2549 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 2564 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
@@ -3328,6 +3343,36 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
3328 | regs->len - B3_RI_WTO_R1); | 3343 | regs->len - B3_RI_WTO_R1); |
3329 | } | 3344 | } |
3330 | 3345 | ||
3346 | /* In order to do Jumbo packets on these chips, need to turn off the | ||
3347 | * transmit store/forward. Therefore checksum offload won't work. | ||
3348 | */ | ||
3349 | static int no_tx_offload(struct net_device *dev) | ||
3350 | { | ||
3351 | const struct sky2_port *sky2 = netdev_priv(dev); | ||
3352 | const struct sky2_hw *hw = sky2->hw; | ||
3353 | |||
3354 | return dev->mtu > ETH_DATA_LEN && | ||
3355 | (hw->chip_id == CHIP_ID_YUKON_EX | ||
3356 | || hw->chip_id == CHIP_ID_YUKON_EC_U); | ||
3357 | } | ||
3358 | |||
3359 | static int sky2_set_tx_csum(struct net_device *dev, u32 data) | ||
3360 | { | ||
3361 | if (data && no_tx_offload(dev)) | ||
3362 | return -EINVAL; | ||
3363 | |||
3364 | return ethtool_op_set_tx_csum(dev, data); | ||
3365 | } | ||
3366 | |||
3367 | |||
3368 | static int sky2_set_tso(struct net_device *dev, u32 data) | ||
3369 | { | ||
3370 | if (data && no_tx_offload(dev)) | ||
3371 | return -EINVAL; | ||
3372 | |||
3373 | return ethtool_op_set_tso(dev, data); | ||
3374 | } | ||
3375 | |||
3331 | static const struct ethtool_ops sky2_ethtool_ops = { | 3376 | static const struct ethtool_ops sky2_ethtool_ops = { |
3332 | .get_settings = sky2_get_settings, | 3377 | .get_settings = sky2_get_settings, |
3333 | .set_settings = sky2_set_settings, | 3378 | .set_settings = sky2_set_settings, |
@@ -3343,9 +3388,9 @@ static const struct ethtool_ops sky2_ethtool_ops = { | |||
3343 | .get_sg = ethtool_op_get_sg, | 3388 | .get_sg = ethtool_op_get_sg, |
3344 | .set_sg = ethtool_op_set_sg, | 3389 | .set_sg = ethtool_op_set_sg, |
3345 | .get_tx_csum = ethtool_op_get_tx_csum, | 3390 | .get_tx_csum = ethtool_op_get_tx_csum, |
3346 | .set_tx_csum = ethtool_op_set_tx_csum, | 3391 | .set_tx_csum = sky2_set_tx_csum, |
3347 | .get_tso = ethtool_op_get_tso, | 3392 | .get_tso = ethtool_op_get_tso, |
3348 | .set_tso = ethtool_op_set_tso, | 3393 | .set_tso = sky2_set_tso, |
3349 | .get_rx_csum = sky2_get_rx_csum, | 3394 | .get_rx_csum = sky2_get_rx_csum, |
3350 | .set_rx_csum = sky2_set_rx_csum, | 3395 | .set_rx_csum = sky2_set_rx_csum, |
3351 | .get_strings = sky2_get_strings, | 3396 | .get_strings = sky2_get_strings, |