diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 583 |
1 files changed, 291 insertions, 292 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 73260364cba3..f08fe6c884b2 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include "sky2.h" | 51 | #include "sky2.h" |
52 | 52 | ||
53 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
54 | #define DRV_VERSION "0.15" | 54 | #define DRV_VERSION "1.1" |
55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -61,10 +61,6 @@ | |||
61 | * a receive requires one (or two if using 64 bit dma). | 61 | * a receive requires one (or two if using 64 bit dma). |
62 | */ | 62 | */ |
63 | 63 | ||
64 | #define is_ec_a1(hw) \ | ||
65 | unlikely((hw)->chip_id == CHIP_ID_YUKON_EC && \ | ||
66 | (hw)->chip_rev == CHIP_REV_YU_EC_A1) | ||
67 | |||
68 | #define RX_LE_SIZE 512 | 64 | #define RX_LE_SIZE 512 |
69 | #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) | 65 | #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) |
70 | #define RX_MAX_PENDING (RX_LE_SIZE/2 - 2) | 66 | #define RX_MAX_PENDING (RX_LE_SIZE/2 - 2) |
@@ -96,6 +92,10 @@ static int copybreak __read_mostly = 256; | |||
96 | module_param(copybreak, int, 0); | 92 | module_param(copybreak, int, 0); |
97 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); | 93 | MODULE_PARM_DESC(copybreak, "Receive copy threshold"); |
98 | 94 | ||
95 | static int disable_msi = 0; | ||
96 | module_param(disable_msi, int, 0); | ||
97 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | ||
98 | |||
99 | static const struct pci_device_id sky2_id_table[] = { | 99 | static const struct pci_device_id sky2_id_table[] = { |
100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
@@ -504,9 +504,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
504 | /* Force a renegotiation */ | 504 | /* Force a renegotiation */ |
505 | static void sky2_phy_reinit(struct sky2_port *sky2) | 505 | static void sky2_phy_reinit(struct sky2_port *sky2) |
506 | { | 506 | { |
507 | down(&sky2->phy_sema); | 507 | spin_lock_bh(&sky2->phy_lock); |
508 | sky2_phy_init(sky2->hw, sky2->port); | 508 | sky2_phy_init(sky2->hw, sky2->port); |
509 | up(&sky2->phy_sema); | 509 | spin_unlock_bh(&sky2->phy_lock); |
510 | } | 510 | } |
511 | 511 | ||
512 | static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | 512 | static void sky2_mac_init(struct sky2_hw *hw, unsigned port) |
@@ -571,9 +571,9 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
571 | 571 | ||
572 | sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); | 572 | sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); |
573 | 573 | ||
574 | down(&sky2->phy_sema); | 574 | spin_lock_bh(&sky2->phy_lock); |
575 | sky2_phy_init(hw, port); | 575 | sky2_phy_init(hw, port); |
576 | up(&sky2->phy_sema); | 576 | spin_unlock_bh(&sky2->phy_lock); |
577 | 577 | ||
578 | /* MIB clear */ | 578 | /* MIB clear */ |
579 | reg = gma_read16(hw, port, GM_PHY_ADDR); | 579 | reg = gma_read16(hw, port, GM_PHY_ADDR); |
@@ -725,37 +725,11 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) | |||
725 | return le; | 725 | return le; |
726 | } | 726 | } |
727 | 727 | ||
728 | /* | 728 | /* Update chip's next pointer */ |
729 | * This is a workaround code taken from SysKonnect sk98lin driver | 729 | static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx) |
730 | * to deal with chip bug on Yukon EC rev 0 in the wraparound case. | ||
731 | */ | ||
732 | static void sky2_put_idx(struct sky2_hw *hw, unsigned q, | ||
733 | u16 idx, u16 *last, u16 size) | ||
734 | { | 730 | { |
735 | wmb(); | 731 | wmb(); |
736 | if (is_ec_a1(hw) && idx < *last) { | 732 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); |
737 | u16 hwget = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX)); | ||
738 | |||
739 | if (hwget == 0) { | ||
740 | /* Start prefetching again */ | ||
741 | sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 0xe0); | ||
742 | goto setnew; | ||
743 | } | ||
744 | |||
745 | if (hwget == size - 1) { | ||
746 | /* set watermark to one list element */ | ||
747 | sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 8); | ||
748 | |||
749 | /* set put index to first list element */ | ||
750 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), 0); | ||
751 | } else /* have hardware go to end of list */ | ||
752 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), | ||
753 | size - 1); | ||
754 | } else { | ||
755 | setnew: | ||
756 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); | ||
757 | } | ||
758 | *last = idx; | ||
759 | mmiowb(); | 733 | mmiowb(); |
760 | } | 734 | } |
761 | 735 | ||
@@ -878,7 +852,7 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
878 | if (!netif_running(dev)) | 852 | if (!netif_running(dev)) |
879 | return -ENODEV; /* Phy still in reset */ | 853 | return -ENODEV; /* Phy still in reset */ |
880 | 854 | ||
881 | switch(cmd) { | 855 | switch (cmd) { |
882 | case SIOCGMIIPHY: | 856 | case SIOCGMIIPHY: |
883 | data->phy_id = PHY_ADDR_MARV; | 857 | data->phy_id = PHY_ADDR_MARV; |
884 | 858 | ||
@@ -886,9 +860,9 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
886 | case SIOCGMIIREG: { | 860 | case SIOCGMIIREG: { |
887 | u16 val = 0; | 861 | u16 val = 0; |
888 | 862 | ||
889 | down(&sky2->phy_sema); | 863 | spin_lock_bh(&sky2->phy_lock); |
890 | err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val); | 864 | err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val); |
891 | up(&sky2->phy_sema); | 865 | spin_unlock_bh(&sky2->phy_lock); |
892 | 866 | ||
893 | data->val_out = val; | 867 | data->val_out = val; |
894 | break; | 868 | break; |
@@ -898,10 +872,10 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
898 | if (!capable(CAP_NET_ADMIN)) | 872 | if (!capable(CAP_NET_ADMIN)) |
899 | return -EPERM; | 873 | return -EPERM; |
900 | 874 | ||
901 | down(&sky2->phy_sema); | 875 | spin_lock_bh(&sky2->phy_lock); |
902 | err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f, | 876 | err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f, |
903 | data->val_in); | 877 | data->val_in); |
904 | up(&sky2->phy_sema); | 878 | spin_unlock_bh(&sky2->phy_lock); |
905 | break; | 879 | break; |
906 | } | 880 | } |
907 | return err; | 881 | return err; |
@@ -1001,7 +975,6 @@ static int sky2_rx_start(struct sky2_port *sky2) | |||
1001 | 975 | ||
1002 | /* Tell chip about available buffers */ | 976 | /* Tell chip about available buffers */ |
1003 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); | 977 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); |
1004 | sky2->rx_last_put = sky2_read16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX)); | ||
1005 | return 0; | 978 | return 0; |
1006 | nomem: | 979 | nomem: |
1007 | sky2_rx_clean(sky2); | 980 | sky2_rx_clean(sky2); |
@@ -1014,7 +987,7 @@ static int sky2_up(struct net_device *dev) | |||
1014 | struct sky2_port *sky2 = netdev_priv(dev); | 987 | struct sky2_port *sky2 = netdev_priv(dev); |
1015 | struct sky2_hw *hw = sky2->hw; | 988 | struct sky2_hw *hw = sky2->hw; |
1016 | unsigned port = sky2->port; | 989 | unsigned port = sky2->port; |
1017 | u32 ramsize, rxspace; | 990 | u32 ramsize, rxspace, imask; |
1018 | int err = -ENOMEM; | 991 | int err = -ENOMEM; |
1019 | 992 | ||
1020 | if (netif_msg_ifup(sky2)) | 993 | if (netif_msg_ifup(sky2)) |
@@ -1079,10 +1052,10 @@ static int sky2_up(struct net_device *dev) | |||
1079 | goto err_out; | 1052 | goto err_out; |
1080 | 1053 | ||
1081 | /* Enable interrupts from phy/mac for port */ | 1054 | /* Enable interrupts from phy/mac for port */ |
1082 | spin_lock_irq(&hw->hw_lock); | 1055 | imask = sky2_read32(hw, B0_IMSK); |
1083 | hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | 1056 | imask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; |
1084 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1057 | sky2_write32(hw, B0_IMSK, imask); |
1085 | spin_unlock_irq(&hw->hw_lock); | 1058 | |
1086 | return 0; | 1059 | return 0; |
1087 | 1060 | ||
1088 | err_out: | 1061 | err_out: |
@@ -1299,8 +1272,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
1299 | netif_stop_queue(dev); | 1272 | netif_stop_queue(dev); |
1300 | } | 1273 | } |
1301 | 1274 | ||
1302 | sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod, | 1275 | sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod); |
1303 | &sky2->tx_last_put, TX_RING_SIZE); | ||
1304 | 1276 | ||
1305 | out_unlock: | 1277 | out_unlock: |
1306 | spin_unlock(&sky2->tx_lock); | 1278 | spin_unlock(&sky2->tx_lock); |
@@ -1332,7 +1304,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1332 | struct tx_ring_info *re = sky2->tx_ring + put; | 1304 | struct tx_ring_info *re = sky2->tx_ring + put; |
1333 | struct sk_buff *skb = re->skb; | 1305 | struct sk_buff *skb = re->skb; |
1334 | 1306 | ||
1335 | nxt = re->idx; | 1307 | nxt = re->idx; |
1336 | BUG_ON(nxt >= TX_RING_SIZE); | 1308 | BUG_ON(nxt >= TX_RING_SIZE); |
1337 | prefetch(sky2->tx_ring + nxt); | 1309 | prefetch(sky2->tx_ring + nxt); |
1338 | 1310 | ||
@@ -1348,7 +1320,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1348 | struct tx_ring_info *fre; | 1320 | struct tx_ring_info *fre; |
1349 | fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE; | 1321 | fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE; |
1350 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), | 1322 | pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr), |
1351 | skb_shinfo(skb)->frags[i].size, | 1323 | skb_shinfo(skb)->frags[i].size, |
1352 | PCI_DMA_TODEVICE); | 1324 | PCI_DMA_TODEVICE); |
1353 | } | 1325 | } |
1354 | 1326 | ||
@@ -1356,7 +1328,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | |||
1356 | } | 1328 | } |
1357 | 1329 | ||
1358 | sky2->tx_cons = put; | 1330 | sky2->tx_cons = put; |
1359 | if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE) | 1331 | if (tx_avail(sky2) > MAX_SKB_TX_LE) |
1360 | netif_wake_queue(dev); | 1332 | netif_wake_queue(dev); |
1361 | } | 1333 | } |
1362 | 1334 | ||
@@ -1375,6 +1347,7 @@ static int sky2_down(struct net_device *dev) | |||
1375 | struct sky2_hw *hw = sky2->hw; | 1347 | struct sky2_hw *hw = sky2->hw; |
1376 | unsigned port = sky2->port; | 1348 | unsigned port = sky2->port; |
1377 | u16 ctrl; | 1349 | u16 ctrl; |
1350 | u32 imask; | ||
1378 | 1351 | ||
1379 | /* Never really got started! */ | 1352 | /* Never really got started! */ |
1380 | if (!sky2->tx_le) | 1353 | if (!sky2->tx_le) |
@@ -1386,14 +1359,6 @@ static int sky2_down(struct net_device *dev) | |||
1386 | /* Stop more packets from being queued */ | 1359 | /* Stop more packets from being queued */ |
1387 | netif_stop_queue(dev); | 1360 | netif_stop_queue(dev); |
1388 | 1361 | ||
1389 | /* Disable port IRQ */ | ||
1390 | spin_lock_irq(&hw->hw_lock); | ||
1391 | hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); | ||
1392 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1393 | spin_unlock_irq(&hw->hw_lock); | ||
1394 | |||
1395 | flush_scheduled_work(); | ||
1396 | |||
1397 | sky2_phy_reset(hw, port); | 1362 | sky2_phy_reset(hw, port); |
1398 | 1363 | ||
1399 | /* Stop transmitter */ | 1364 | /* Stop transmitter */ |
@@ -1437,6 +1402,11 @@ static int sky2_down(struct net_device *dev) | |||
1437 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); | 1402 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); |
1438 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); | 1403 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); |
1439 | 1404 | ||
1405 | /* Disable port IRQ */ | ||
1406 | imask = sky2_read32(hw, B0_IMSK); | ||
1407 | imask &= ~(sky2->port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | ||
1408 | sky2_write32(hw, B0_IMSK, imask); | ||
1409 | |||
1440 | /* turn off LED's */ | 1410 | /* turn off LED's */ |
1441 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 1411 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
1442 | 1412 | ||
@@ -1631,20 +1601,19 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1631 | return 0; | 1601 | return 0; |
1632 | } | 1602 | } |
1633 | 1603 | ||
1634 | /* | 1604 | /* Interrupt from PHY */ |
1635 | * Interrupt from PHY are handled outside of interrupt context | 1605 | static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) |
1636 | * because accessing phy registers requires spin wait which might | ||
1637 | * cause excess interrupt latency. | ||
1638 | */ | ||
1639 | static void sky2_phy_task(void *arg) | ||
1640 | { | 1606 | { |
1641 | struct sky2_port *sky2 = arg; | 1607 | struct net_device *dev = hw->dev[port]; |
1642 | struct sky2_hw *hw = sky2->hw; | 1608 | struct sky2_port *sky2 = netdev_priv(dev); |
1643 | u16 istatus, phystat; | 1609 | u16 istatus, phystat; |
1644 | 1610 | ||
1645 | down(&sky2->phy_sema); | 1611 | spin_lock(&sky2->phy_lock); |
1646 | istatus = gm_phy_read(hw, sky2->port, PHY_MARV_INT_STAT); | 1612 | istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); |
1647 | phystat = gm_phy_read(hw, sky2->port, PHY_MARV_PHY_STAT); | 1613 | phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); |
1614 | |||
1615 | if (!netif_running(dev)) | ||
1616 | goto out; | ||
1648 | 1617 | ||
1649 | if (netif_msg_intr(sky2)) | 1618 | if (netif_msg_intr(sky2)) |
1650 | printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", | 1619 | printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", |
@@ -1670,12 +1639,7 @@ static void sky2_phy_task(void *arg) | |||
1670 | sky2_link_down(sky2); | 1639 | sky2_link_down(sky2); |
1671 | } | 1640 | } |
1672 | out: | 1641 | out: |
1673 | up(&sky2->phy_sema); | 1642 | spin_unlock(&sky2->phy_lock); |
1674 | |||
1675 | spin_lock_irq(&hw->hw_lock); | ||
1676 | hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2; | ||
1677 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1678 | spin_unlock_irq(&hw->hw_lock); | ||
1679 | } | 1643 | } |
1680 | 1644 | ||
1681 | 1645 | ||
@@ -1687,31 +1651,40 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1687 | struct sky2_port *sky2 = netdev_priv(dev); | 1651 | struct sky2_port *sky2 = netdev_priv(dev); |
1688 | struct sky2_hw *hw = sky2->hw; | 1652 | struct sky2_hw *hw = sky2->hw; |
1689 | unsigned txq = txqaddr[sky2->port]; | 1653 | unsigned txq = txqaddr[sky2->port]; |
1690 | u16 ridx; | 1654 | u16 report, done; |
1691 | |||
1692 | /* Maybe we just missed an status interrupt */ | ||
1693 | spin_lock(&sky2->tx_lock); | ||
1694 | ridx = sky2_read16(hw, | ||
1695 | sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX); | ||
1696 | sky2_tx_complete(sky2, ridx); | ||
1697 | spin_unlock(&sky2->tx_lock); | ||
1698 | |||
1699 | if (!netif_queue_stopped(dev)) { | ||
1700 | if (net_ratelimit()) | ||
1701 | pr_info(PFX "transmit interrupt missed? recovered\n"); | ||
1702 | return; | ||
1703 | } | ||
1704 | 1655 | ||
1705 | if (netif_msg_timer(sky2)) | 1656 | if (netif_msg_timer(sky2)) |
1706 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); | 1657 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); |
1707 | 1658 | ||
1708 | sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); | 1659 | report = sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX); |
1709 | sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | 1660 | done = sky2_read16(hw, Q_ADDR(txq, Q_DONE)); |
1710 | 1661 | ||
1711 | sky2_tx_clean(sky2); | 1662 | printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", |
1663 | dev->name, | ||
1664 | sky2->tx_cons, sky2->tx_prod, report, done); | ||
1712 | 1665 | ||
1713 | sky2_qset(hw, txq); | 1666 | if (report != done) { |
1714 | sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); | 1667 | printk(KERN_INFO PFX "status burst pending (irq moderation?)\n"); |
1668 | |||
1669 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | ||
1670 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
1671 | } else if (report != sky2->tx_cons) { | ||
1672 | printk(KERN_INFO PFX "status report lost?\n"); | ||
1673 | |||
1674 | spin_lock_bh(&sky2->tx_lock); | ||
1675 | sky2_tx_complete(sky2, report); | ||
1676 | spin_unlock_bh(&sky2->tx_lock); | ||
1677 | } else { | ||
1678 | printk(KERN_INFO PFX "hardware hung? flushing\n"); | ||
1679 | |||
1680 | sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); | ||
1681 | sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | ||
1682 | |||
1683 | sky2_tx_clean(sky2); | ||
1684 | |||
1685 | sky2_qset(hw, txq); | ||
1686 | sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); | ||
1687 | } | ||
1715 | } | 1688 | } |
1716 | 1689 | ||
1717 | 1690 | ||
@@ -1730,6 +1703,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1730 | struct sky2_hw *hw = sky2->hw; | 1703 | struct sky2_hw *hw = sky2->hw; |
1731 | int err; | 1704 | int err; |
1732 | u16 ctl, mode; | 1705 | u16 ctl, mode; |
1706 | u32 imask; | ||
1733 | 1707 | ||
1734 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) | 1708 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) |
1735 | return -EINVAL; | 1709 | return -EINVAL; |
@@ -1742,12 +1716,15 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1742 | return 0; | 1716 | return 0; |
1743 | } | 1717 | } |
1744 | 1718 | ||
1719 | imask = sky2_read32(hw, B0_IMSK); | ||
1745 | sky2_write32(hw, B0_IMSK, 0); | 1720 | sky2_write32(hw, B0_IMSK, 0); |
1746 | 1721 | ||
1747 | dev->trans_start = jiffies; /* prevent tx timeout */ | 1722 | dev->trans_start = jiffies; /* prevent tx timeout */ |
1748 | netif_stop_queue(dev); | 1723 | netif_stop_queue(dev); |
1749 | netif_poll_disable(hw->dev[0]); | 1724 | netif_poll_disable(hw->dev[0]); |
1750 | 1725 | ||
1726 | synchronize_irq(hw->pdev->irq); | ||
1727 | |||
1751 | ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); | 1728 | ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); |
1752 | gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); | 1729 | gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); |
1753 | sky2_rx_stop(sky2); | 1730 | sky2_rx_stop(sky2); |
@@ -1766,7 +1743,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
1766 | sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); | 1743 | sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); |
1767 | 1744 | ||
1768 | err = sky2_rx_start(sky2); | 1745 | err = sky2_rx_start(sky2); |
1769 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 1746 | sky2_write32(hw, B0_IMSK, imask); |
1770 | 1747 | ||
1771 | if (err) | 1748 | if (err) |
1772 | dev_close(dev); | 1749 | dev_close(dev); |
@@ -1843,8 +1820,7 @@ resubmit: | |||
1843 | sky2_rx_add(sky2, re->mapaddr); | 1820 | sky2_rx_add(sky2, re->mapaddr); |
1844 | 1821 | ||
1845 | /* Tell receiver about new buffers. */ | 1822 | /* Tell receiver about new buffers. */ |
1846 | sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put, | 1823 | sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put); |
1847 | &sky2->rx_last_put, RX_LE_SIZE); | ||
1848 | 1824 | ||
1849 | return skb; | 1825 | return skb; |
1850 | 1826 | ||
@@ -1871,76 +1847,51 @@ error: | |||
1871 | goto resubmit; | 1847 | goto resubmit; |
1872 | } | 1848 | } |
1873 | 1849 | ||
1874 | /* | 1850 | /* Transmit complete */ |
1875 | * Check for transmit complete | 1851 | static inline void sky2_tx_done(struct net_device *dev, u16 last) |
1876 | */ | ||
1877 | #define TX_NO_STATUS 0xffff | ||
1878 | |||
1879 | static void sky2_tx_check(struct sky2_hw *hw, int port, u16 last) | ||
1880 | { | 1852 | { |
1881 | if (last != TX_NO_STATUS) { | 1853 | struct sky2_port *sky2 = netdev_priv(dev); |
1882 | struct net_device *dev = hw->dev[port]; | ||
1883 | if (dev && netif_running(dev)) { | ||
1884 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1885 | 1854 | ||
1886 | spin_lock(&sky2->tx_lock); | 1855 | if (netif_running(dev)) { |
1887 | sky2_tx_complete(sky2, last); | 1856 | spin_lock(&sky2->tx_lock); |
1888 | spin_unlock(&sky2->tx_lock); | 1857 | sky2_tx_complete(sky2, last); |
1889 | } | 1858 | spin_unlock(&sky2->tx_lock); |
1890 | } | 1859 | } |
1891 | } | 1860 | } |
1892 | 1861 | ||
1893 | /* | 1862 | /* Process status response ring */ |
1894 | * Both ports share the same status interrupt, therefore there is only | 1863 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
1895 | * one poll routine. | ||
1896 | */ | ||
1897 | static int sky2_poll(struct net_device *dev0, int *budget) | ||
1898 | { | 1864 | { |
1899 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 1865 | int work_done = 0; |
1900 | unsigned int to_do = min(dev0->quota, *budget); | ||
1901 | unsigned int work_done = 0; | ||
1902 | u16 hwidx; | ||
1903 | u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; | ||
1904 | |||
1905 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
1906 | |||
1907 | /* | ||
1908 | * Kick the STAT_LEV_TIMER_CTRL timer. | ||
1909 | * This fixes my hangs on Yukon-EC (0xb6) rev 1. | ||
1910 | * The if clause is there to start the timer only if it has been | ||
1911 | * configured correctly and not been disabled via ethtool. | ||
1912 | */ | ||
1913 | if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_START) { | ||
1914 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP); | ||
1915 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); | ||
1916 | } | ||
1917 | 1866 | ||
1918 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | ||
1919 | BUG_ON(hwidx >= STATUS_RING_SIZE); | ||
1920 | rmb(); | 1867 | rmb(); |
1921 | 1868 | ||
1922 | while (hwidx != hw->st_idx) { | 1869 | for(;;) { |
1923 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | 1870 | struct sky2_status_le *le = hw->st_le + hw->st_idx; |
1924 | struct net_device *dev; | 1871 | struct net_device *dev; |
1925 | struct sky2_port *sky2; | 1872 | struct sky2_port *sky2; |
1926 | struct sk_buff *skb; | 1873 | struct sk_buff *skb; |
1927 | u32 status; | 1874 | u32 status; |
1928 | u16 length; | 1875 | u16 length; |
1876 | u8 link, opcode; | ||
1877 | |||
1878 | opcode = le->opcode; | ||
1879 | if (!opcode) | ||
1880 | break; | ||
1881 | opcode &= ~HW_OWNER; | ||
1929 | 1882 | ||
1930 | le = hw->st_le + hw->st_idx; | ||
1931 | hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; | 1883 | hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; |
1932 | prefetch(hw->st_le + hw->st_idx); | 1884 | le->opcode = 0; |
1933 | 1885 | ||
1934 | BUG_ON(le->link >= 2); | 1886 | link = le->link; |
1935 | dev = hw->dev[le->link]; | 1887 | BUG_ON(link >= 2); |
1936 | if (dev == NULL || !netif_running(dev)) | 1888 | dev = hw->dev[link]; |
1937 | continue; | ||
1938 | 1889 | ||
1939 | sky2 = netdev_priv(dev); | 1890 | sky2 = netdev_priv(dev); |
1940 | status = le32_to_cpu(le->status); | 1891 | length = le->length; |
1941 | length = le16_to_cpu(le->length); | 1892 | status = le->status; |
1942 | 1893 | ||
1943 | switch (le->opcode & ~HW_OWNER) { | 1894 | switch (opcode) { |
1944 | case OP_RXSTAT: | 1895 | case OP_RXSTAT: |
1945 | skb = sky2_receive(sky2, length, status); | 1896 | skb = sky2_receive(sky2, length, status); |
1946 | if (!skb) | 1897 | if (!skb) |
@@ -1980,42 +1931,23 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
1980 | 1931 | ||
1981 | case OP_TXINDEXLE: | 1932 | case OP_TXINDEXLE: |
1982 | /* TX index reports status for both ports */ | 1933 | /* TX index reports status for both ports */ |
1983 | tx_done[0] = status & 0xffff; | 1934 | sky2_tx_done(hw->dev[0], status & 0xffff); |
1984 | tx_done[1] = ((status >> 24) & 0xff) | 1935 | if (hw->dev[1]) |
1985 | | (u16)(length & 0xf) << 8; | 1936 | sky2_tx_done(hw->dev[1], |
1937 | ((status >> 24) & 0xff) | ||
1938 | | (u16)(length & 0xf) << 8); | ||
1986 | break; | 1939 | break; |
1987 | 1940 | ||
1988 | default: | 1941 | default: |
1989 | if (net_ratelimit()) | 1942 | if (net_ratelimit()) |
1990 | printk(KERN_WARNING PFX | 1943 | printk(KERN_WARNING PFX |
1991 | "unknown status opcode 0x%x\n", le->opcode); | 1944 | "unknown status opcode 0x%x\n", opcode); |
1992 | break; | 1945 | break; |
1993 | } | 1946 | } |
1994 | } | 1947 | } |
1995 | 1948 | ||
1996 | exit_loop: | 1949 | exit_loop: |
1997 | sky2_tx_check(hw, 0, tx_done[0]); | 1950 | return work_done; |
1998 | sky2_tx_check(hw, 1, tx_done[1]); | ||
1999 | |||
2000 | if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { | ||
2001 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | ||
2002 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
2003 | } | ||
2004 | |||
2005 | if (likely(work_done < to_do)) { | ||
2006 | spin_lock_irq(&hw->hw_lock); | ||
2007 | __netif_rx_complete(dev0); | ||
2008 | |||
2009 | hw->intr_mask |= Y2_IS_STAT_BMU; | ||
2010 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
2011 | spin_unlock_irq(&hw->hw_lock); | ||
2012 | |||
2013 | return 0; | ||
2014 | } else { | ||
2015 | *budget -= work_done; | ||
2016 | dev0->quota -= work_done; | ||
2017 | return 1; | ||
2018 | } | ||
2019 | } | 1951 | } |
2020 | 1952 | ||
2021 | static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) | 1953 | static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) |
@@ -2134,57 +2066,97 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) | |||
2134 | } | 2066 | } |
2135 | } | 2067 | } |
2136 | 2068 | ||
2137 | static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) | 2069 | /* This should never happen it is a fatal situation */ |
2070 | static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | ||
2071 | const char *rxtx, u32 mask) | ||
2138 | { | 2072 | { |
2139 | struct net_device *dev = hw->dev[port]; | 2073 | struct net_device *dev = hw->dev[port]; |
2140 | struct sky2_port *sky2 = netdev_priv(dev); | 2074 | struct sky2_port *sky2 = netdev_priv(dev); |
2075 | u32 imask; | ||
2076 | |||
2077 | printk(KERN_ERR PFX "%s: %s descriptor error (hardware problem)\n", | ||
2078 | dev ? dev->name : "<not registered>", rxtx); | ||
2141 | 2079 | ||
2142 | hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); | 2080 | imask = sky2_read32(hw, B0_IMSK); |
2143 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | 2081 | imask &= ~mask; |
2082 | sky2_write32(hw, B0_IMSK, imask); | ||
2144 | 2083 | ||
2145 | schedule_work(&sky2->phy_task); | 2084 | if (dev) { |
2085 | spin_lock(&sky2->phy_lock); | ||
2086 | sky2_link_down(sky2); | ||
2087 | spin_unlock(&sky2->phy_lock); | ||
2088 | } | ||
2146 | } | 2089 | } |
2147 | 2090 | ||
2148 | static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | 2091 | static int sky2_poll(struct net_device *dev0, int *budget) |
2149 | { | 2092 | { |
2150 | struct sky2_hw *hw = dev_id; | 2093 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
2151 | struct net_device *dev0 = hw->dev[0]; | 2094 | int work_limit = min(dev0->quota, *budget); |
2152 | u32 status; | 2095 | int work_done = 0; |
2096 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | ||
2153 | 2097 | ||
2154 | status = sky2_read32(hw, B0_Y2_SP_ISRC2); | 2098 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { |
2155 | if (status == 0 || status == ~0) | 2099 | if (status & Y2_IS_HW_ERR) |
2156 | return IRQ_NONE; | 2100 | sky2_hw_intr(hw); |
2157 | 2101 | ||
2158 | spin_lock(&hw->hw_lock); | 2102 | if (status & Y2_IS_IRQ_PHY1) |
2159 | if (status & Y2_IS_HW_ERR) | 2103 | sky2_phy_intr(hw, 0); |
2160 | sky2_hw_intr(hw); | ||
2161 | 2104 | ||
2162 | /* Do NAPI for Rx and Tx status */ | 2105 | if (status & Y2_IS_IRQ_PHY2) |
2163 | if (status & Y2_IS_STAT_BMU) { | 2106 | sky2_phy_intr(hw, 1); |
2164 | hw->intr_mask &= ~Y2_IS_STAT_BMU; | ||
2165 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
2166 | 2107 | ||
2167 | if (likely(__netif_rx_schedule_prep(dev0))) { | 2108 | if (status & Y2_IS_IRQ_MAC1) |
2168 | prefetch(&hw->st_le[hw->st_idx]); | 2109 | sky2_mac_intr(hw, 0); |
2169 | __netif_rx_schedule(dev0); | 2110 | |
2170 | } | 2111 | if (status & Y2_IS_IRQ_MAC2) |
2112 | sky2_mac_intr(hw, 1); | ||
2113 | |||
2114 | if (status & Y2_IS_CHK_RX1) | ||
2115 | sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); | ||
2116 | |||
2117 | if (status & Y2_IS_CHK_RX2) | ||
2118 | sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); | ||
2119 | |||
2120 | if (status & Y2_IS_CHK_TXA1) | ||
2121 | sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); | ||
2122 | |||
2123 | if (status & Y2_IS_CHK_TXA2) | ||
2124 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | ||
2171 | } | 2125 | } |
2172 | 2126 | ||
2173 | if (status & Y2_IS_IRQ_PHY1) | 2127 | if (status & Y2_IS_STAT_BMU) { |
2174 | sky2_phy_intr(hw, 0); | 2128 | work_done = sky2_status_intr(hw, work_limit); |
2129 | *budget -= work_done; | ||
2130 | dev0->quota -= work_done; | ||
2131 | |||
2132 | if (work_done >= work_limit) | ||
2133 | return 1; | ||
2175 | 2134 | ||
2176 | if (status & Y2_IS_IRQ_PHY2) | 2135 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2177 | sky2_phy_intr(hw, 1); | 2136 | } |
2178 | 2137 | ||
2179 | if (status & Y2_IS_IRQ_MAC1) | 2138 | netif_rx_complete(dev0); |
2180 | sky2_mac_intr(hw, 0); | ||
2181 | 2139 | ||
2182 | if (status & Y2_IS_IRQ_MAC2) | 2140 | status = sky2_read32(hw, B0_Y2_SP_LISR); |
2183 | sky2_mac_intr(hw, 1); | 2141 | return 0; |
2142 | } | ||
2184 | 2143 | ||
2185 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | 2144 | static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) |
2145 | { | ||
2146 | struct sky2_hw *hw = dev_id; | ||
2147 | struct net_device *dev0 = hw->dev[0]; | ||
2148 | u32 status; | ||
2186 | 2149 | ||
2187 | spin_unlock(&hw->hw_lock); | 2150 | /* Reading this mask interrupts as side effect */ |
2151 | status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
2152 | if (status == 0 || status == ~0) | ||
2153 | return IRQ_NONE; | ||
2154 | |||
2155 | prefetch(&hw->st_le[hw->st_idx]); | ||
2156 | if (likely(__netif_rx_schedule_prep(dev0))) | ||
2157 | __netif_rx_schedule(dev0); | ||
2158 | else | ||
2159 | printk(KERN_DEBUG PFX "irq race detected\n"); | ||
2188 | 2160 | ||
2189 | return IRQ_HANDLED; | 2161 | return IRQ_HANDLED; |
2190 | } | 2162 | } |
@@ -2238,6 +2210,23 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2238 | return -EOPNOTSUPP; | 2210 | return -EOPNOTSUPP; |
2239 | } | 2211 | } |
2240 | 2212 | ||
2213 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; | ||
2214 | |||
2215 | /* This rev is really old, and requires untested workarounds */ | ||
2216 | if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { | ||
2217 | printk(KERN_ERR PFX "%s: unsupported revision Yukon-%s (0x%x) rev %d\n", | ||
2218 | pci_name(hw->pdev), yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], | ||
2219 | hw->chip_id, hw->chip_rev); | ||
2220 | return -EOPNOTSUPP; | ||
2221 | } | ||
2222 | |||
2223 | /* This chip is new and not tested yet */ | ||
2224 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | ||
2225 | pr_info(PFX "%s: is a version of Yukon 2 chipset that has not been tested yet.\n", | ||
2226 | pci_name(hw->pdev)); | ||
2227 | pr_info("Please report success/failure to maintainer <shemminger@osdl.org>\n"); | ||
2228 | } | ||
2229 | |||
2241 | /* disable ASF */ | 2230 | /* disable ASF */ |
2242 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | 2231 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { |
2243 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | 2232 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); |
@@ -2258,7 +2247,7 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2258 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); | 2247 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); |
2259 | 2248 | ||
2260 | /* clear any PEX errors */ | 2249 | /* clear any PEX errors */ |
2261 | if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) | 2250 | if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) |
2262 | sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); | 2251 | sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); |
2263 | 2252 | ||
2264 | 2253 | ||
@@ -2271,7 +2260,6 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2271 | if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) | 2260 | if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) |
2272 | ++hw->ports; | 2261 | ++hw->ports; |
2273 | } | 2262 | } |
2274 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; | ||
2275 | 2263 | ||
2276 | sky2_set_power_state(hw, PCI_D0); | 2264 | sky2_set_power_state(hw, PCI_D0); |
2277 | 2265 | ||
@@ -2337,30 +2325,18 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2337 | /* Set the list last index */ | 2325 | /* Set the list last index */ |
2338 | sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1); | 2326 | sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1); |
2339 | 2327 | ||
2340 | /* These status setup values are copied from SysKonnect's driver */ | 2328 | sky2_write16(hw, STAT_TX_IDX_TH, 10); |
2341 | if (is_ec_a1(hw)) { | 2329 | sky2_write8(hw, STAT_FIFO_WM, 16); |
2342 | /* WA for dev. #4.3 */ | ||
2343 | sky2_write16(hw, STAT_TX_IDX_TH, 0xfff); /* Tx Threshold */ | ||
2344 | |||
2345 | /* set Status-FIFO watermark */ | ||
2346 | sky2_write8(hw, STAT_FIFO_WM, 0x21); /* WA for dev. #4.18 */ | ||
2347 | 2330 | ||
2348 | /* set Status-FIFO ISR watermark */ | 2331 | /* set Status-FIFO ISR watermark */ |
2349 | sky2_write8(hw, STAT_FIFO_ISR_WM, 0x07); /* WA for dev. #4.18 */ | 2332 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0) |
2350 | sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 10000)); | 2333 | sky2_write8(hw, STAT_FIFO_ISR_WM, 4); |
2351 | } else { | 2334 | else |
2352 | sky2_write16(hw, STAT_TX_IDX_TH, 10); | 2335 | sky2_write8(hw, STAT_FIFO_ISR_WM, 16); |
2353 | sky2_write8(hw, STAT_FIFO_WM, 16); | ||
2354 | |||
2355 | /* set Status-FIFO ISR watermark */ | ||
2356 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0) | ||
2357 | sky2_write8(hw, STAT_FIFO_ISR_WM, 4); | ||
2358 | else | ||
2359 | sky2_write8(hw, STAT_FIFO_ISR_WM, 16); | ||
2360 | 2336 | ||
2361 | sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); | 2337 | sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); |
2362 | sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 7)); | 2338 | sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20)); |
2363 | } | 2339 | sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100)); |
2364 | 2340 | ||
2365 | /* enable status unit */ | 2341 | /* enable status unit */ |
2366 | sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON); | 2342 | sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON); |
@@ -2743,7 +2719,7 @@ static int sky2_phys_id(struct net_device *dev, u32 data) | |||
2743 | ms = data * 1000; | 2719 | ms = data * 1000; |
2744 | 2720 | ||
2745 | /* save initial values */ | 2721 | /* save initial values */ |
2746 | down(&sky2->phy_sema); | 2722 | spin_lock_bh(&sky2->phy_lock); |
2747 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | 2723 | if (hw->chip_id == CHIP_ID_YUKON_XL) { |
2748 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | 2724 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
2749 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | 2725 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); |
@@ -2759,9 +2735,9 @@ static int sky2_phys_id(struct net_device *dev, u32 data) | |||
2759 | sky2_led(hw, port, onoff); | 2735 | sky2_led(hw, port, onoff); |
2760 | onoff = !onoff; | 2736 | onoff = !onoff; |
2761 | 2737 | ||
2762 | up(&sky2->phy_sema); | 2738 | spin_unlock_bh(&sky2->phy_lock); |
2763 | interrupted = msleep_interruptible(250); | 2739 | interrupted = msleep_interruptible(250); |
2764 | down(&sky2->phy_sema); | 2740 | spin_lock_bh(&sky2->phy_lock); |
2765 | 2741 | ||
2766 | ms -= 250; | 2742 | ms -= 250; |
2767 | } | 2743 | } |
@@ -2776,7 +2752,7 @@ static int sky2_phys_id(struct net_device *dev, u32 data) | |||
2776 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | 2752 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); |
2777 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); | 2753 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); |
2778 | } | 2754 | } |
2779 | up(&sky2->phy_sema); | 2755 | spin_unlock_bh(&sky2->phy_lock); |
2780 | 2756 | ||
2781 | return 0; | 2757 | return 0; |
2782 | } | 2758 | } |
@@ -2806,38 +2782,6 @@ static int sky2_set_pauseparam(struct net_device *dev, | |||
2806 | return err; | 2782 | return err; |
2807 | } | 2783 | } |
2808 | 2784 | ||
2809 | #ifdef CONFIG_PM | ||
2810 | static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2811 | { | ||
2812 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2813 | |||
2814 | wol->supported = WAKE_MAGIC; | ||
2815 | wol->wolopts = sky2->wol ? WAKE_MAGIC : 0; | ||
2816 | } | ||
2817 | |||
2818 | static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2819 | { | ||
2820 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2821 | struct sky2_hw *hw = sky2->hw; | ||
2822 | |||
2823 | if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) | ||
2824 | return -EOPNOTSUPP; | ||
2825 | |||
2826 | sky2->wol = wol->wolopts == WAKE_MAGIC; | ||
2827 | |||
2828 | if (sky2->wol) { | ||
2829 | memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN); | ||
2830 | |||
2831 | sky2_write16(hw, WOL_CTRL_STAT, | ||
2832 | WOL_CTL_ENA_PME_ON_MAGIC_PKT | | ||
2833 | WOL_CTL_ENA_MAGIC_PKT_UNIT); | ||
2834 | } else | ||
2835 | sky2_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT); | ||
2836 | |||
2837 | return 0; | ||
2838 | } | ||
2839 | #endif | ||
2840 | |||
2841 | static int sky2_get_coalesce(struct net_device *dev, | 2785 | static int sky2_get_coalesce(struct net_device *dev, |
2842 | struct ethtool_coalesce *ecmd) | 2786 | struct ethtool_coalesce *ecmd) |
2843 | { | 2787 | { |
@@ -2878,19 +2822,11 @@ static int sky2_set_coalesce(struct net_device *dev, | |||
2878 | { | 2822 | { |
2879 | struct sky2_port *sky2 = netdev_priv(dev); | 2823 | struct sky2_port *sky2 = netdev_priv(dev); |
2880 | struct sky2_hw *hw = sky2->hw; | 2824 | struct sky2_hw *hw = sky2->hw; |
2881 | const u32 tmin = sky2_clk2us(hw, 1); | 2825 | const u32 tmax = sky2_clk2us(hw, 0x0ffffff); |
2882 | const u32 tmax = 5000; | ||
2883 | |||
2884 | if (ecmd->tx_coalesce_usecs != 0 && | ||
2885 | (ecmd->tx_coalesce_usecs < tmin || ecmd->tx_coalesce_usecs > tmax)) | ||
2886 | return -EINVAL; | ||
2887 | |||
2888 | if (ecmd->rx_coalesce_usecs != 0 && | ||
2889 | (ecmd->rx_coalesce_usecs < tmin || ecmd->rx_coalesce_usecs > tmax)) | ||
2890 | return -EINVAL; | ||
2891 | 2826 | ||
2892 | if (ecmd->rx_coalesce_usecs_irq != 0 && | 2827 | if (ecmd->tx_coalesce_usecs > tmax || |
2893 | (ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax)) | 2828 | ecmd->rx_coalesce_usecs > tmax || |
2829 | ecmd->rx_coalesce_usecs_irq > tmax) | ||
2894 | return -EINVAL; | 2830 | return -EINVAL; |
2895 | 2831 | ||
2896 | if (ecmd->tx_max_coalesced_frames >= TX_RING_SIZE-1) | 2832 | if (ecmd->tx_max_coalesced_frames >= TX_RING_SIZE-1) |
@@ -3025,10 +2961,6 @@ static struct ethtool_ops sky2_ethtool_ops = { | |||
3025 | .set_ringparam = sky2_set_ringparam, | 2961 | .set_ringparam = sky2_set_ringparam, |
3026 | .get_pauseparam = sky2_get_pauseparam, | 2962 | .get_pauseparam = sky2_get_pauseparam, |
3027 | .set_pauseparam = sky2_set_pauseparam, | 2963 | .set_pauseparam = sky2_set_pauseparam, |
3028 | #ifdef CONFIG_PM | ||
3029 | .get_wol = sky2_get_wol, | ||
3030 | .set_wol = sky2_set_wol, | ||
3031 | #endif | ||
3032 | .phys_id = sky2_phys_id, | 2964 | .phys_id = sky2_phys_id, |
3033 | .get_stats_count = sky2_get_stats_count, | 2965 | .get_stats_count = sky2_get_stats_count, |
3034 | .get_ethtool_stats = sky2_get_ethtool_stats, | 2966 | .get_ethtool_stats = sky2_get_ethtool_stats, |
@@ -3082,16 +3014,15 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | |||
3082 | sky2->speed = -1; | 3014 | sky2->speed = -1; |
3083 | sky2->advertising = sky2_supported_modes(hw); | 3015 | sky2->advertising = sky2_supported_modes(hw); |
3084 | 3016 | ||
3085 | /* Receive checksum disabled for Yukon XL | 3017 | /* Receive checksum disabled for Yukon XL |
3086 | * because of observed problems with incorrect | 3018 | * because of observed problems with incorrect |
3087 | * values when multiple packets are received in one interrupt | 3019 | * values when multiple packets are received in one interrupt |
3088 | */ | 3020 | */ |
3089 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); | 3021 | sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); |
3090 | 3022 | ||
3091 | INIT_WORK(&sky2->phy_task, sky2_phy_task, sky2); | 3023 | spin_lock_init(&sky2->phy_lock); |
3092 | init_MUTEX(&sky2->phy_sema); | ||
3093 | sky2->tx_pending = TX_DEF_PENDING; | 3024 | sky2->tx_pending = TX_DEF_PENDING; |
3094 | sky2->rx_pending = is_ec_a1(hw) ? 8 : RX_DEF_PENDING; | 3025 | sky2->rx_pending = RX_DEF_PENDING; |
3095 | sky2->rx_bufsize = sky2_buf_size(ETH_DATA_LEN); | 3026 | sky2->rx_bufsize = sky2_buf_size(ETH_DATA_LEN); |
3096 | 3027 | ||
3097 | hw->dev[port] = dev; | 3028 | hw->dev[port] = dev; |
@@ -3133,6 +3064,66 @@ static void __devinit sky2_show_addr(struct net_device *dev) | |||
3133 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); | 3064 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); |
3134 | } | 3065 | } |
3135 | 3066 | ||
3067 | /* Handle software interrupt used during MSI test */ | ||
3068 | static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id, | ||
3069 | struct pt_regs *regs) | ||
3070 | { | ||
3071 | struct sky2_hw *hw = dev_id; | ||
3072 | u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
3073 | |||
3074 | if (status == 0) | ||
3075 | return IRQ_NONE; | ||
3076 | |||
3077 | if (status & Y2_IS_IRQ_SW) { | ||
3078 | hw->msi_detected = 1; | ||
3079 | wake_up(&hw->msi_wait); | ||
3080 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
3081 | } | ||
3082 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | ||
3083 | |||
3084 | return IRQ_HANDLED; | ||
3085 | } | ||
3086 | |||
3087 | /* Test interrupt path by forcing a a software IRQ */ | ||
3088 | static int __devinit sky2_test_msi(struct sky2_hw *hw) | ||
3089 | { | ||
3090 | struct pci_dev *pdev = hw->pdev; | ||
3091 | int err; | ||
3092 | |||
3093 | sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); | ||
3094 | |||
3095 | err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw); | ||
3096 | if (err) { | ||
3097 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | ||
3098 | pci_name(pdev), pdev->irq); | ||
3099 | return err; | ||
3100 | } | ||
3101 | |||
3102 | init_waitqueue_head (&hw->msi_wait); | ||
3103 | |||
3104 | sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); | ||
3105 | wmb(); | ||
3106 | |||
3107 | wait_event_timeout(hw->msi_wait, hw->msi_detected, HZ/10); | ||
3108 | |||
3109 | if (!hw->msi_detected) { | ||
3110 | /* MSI test failed, go back to INTx mode */ | ||
3111 | printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " | ||
3112 | "switching to INTx mode. Please report this failure to " | ||
3113 | "the PCI maintainer and include system chipset information.\n", | ||
3114 | pci_name(pdev)); | ||
3115 | |||
3116 | err = -EOPNOTSUPP; | ||
3117 | sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); | ||
3118 | } | ||
3119 | |||
3120 | sky2_write32(hw, B0_IMSK, 0); | ||
3121 | |||
3122 | free_irq(pdev->irq, hw); | ||
3123 | |||
3124 | return err; | ||
3125 | } | ||
3126 | |||
3136 | static int __devinit sky2_probe(struct pci_dev *pdev, | 3127 | static int __devinit sky2_probe(struct pci_dev *pdev, |
3137 | const struct pci_device_id *ent) | 3128 | const struct pci_device_id *ent) |
3138 | { | 3129 | { |
@@ -3201,7 +3192,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3201 | goto err_out_free_hw; | 3192 | goto err_out_free_hw; |
3202 | } | 3193 | } |
3203 | hw->pm_cap = pm_cap; | 3194 | hw->pm_cap = pm_cap; |
3204 | spin_lock_init(&hw->hw_lock); | ||
3205 | 3195 | ||
3206 | #ifdef __BIG_ENDIAN | 3196 | #ifdef __BIG_ENDIAN |
3207 | /* byte swap descriptors in hardware */ | 3197 | /* byte swap descriptors in hardware */ |
@@ -3254,21 +3244,29 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3254 | } | 3244 | } |
3255 | } | 3245 | } |
3256 | 3246 | ||
3257 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); | 3247 | if (!disable_msi && pci_enable_msi(pdev) == 0) { |
3248 | err = sky2_test_msi(hw); | ||
3249 | if (err == -EOPNOTSUPP) | ||
3250 | pci_disable_msi(pdev); | ||
3251 | else if (err) | ||
3252 | goto err_out_unregister; | ||
3253 | } | ||
3254 | |||
3255 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); | ||
3258 | if (err) { | 3256 | if (err) { |
3259 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | 3257 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", |
3260 | pci_name(pdev), pdev->irq); | 3258 | pci_name(pdev), pdev->irq); |
3261 | goto err_out_unregister; | 3259 | goto err_out_unregister; |
3262 | } | 3260 | } |
3263 | 3261 | ||
3264 | hw->intr_mask = Y2_IS_BASE; | 3262 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3265 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
3266 | 3263 | ||
3267 | pci_set_drvdata(pdev, hw); | 3264 | pci_set_drvdata(pdev, hw); |
3268 | 3265 | ||
3269 | return 0; | 3266 | return 0; |
3270 | 3267 | ||
3271 | err_out_unregister: | 3268 | err_out_unregister: |
3269 | pci_disable_msi(pdev); | ||
3272 | if (dev1) { | 3270 | if (dev1) { |
3273 | unregister_netdev(dev1); | 3271 | unregister_netdev(dev1); |
3274 | free_netdev(dev1); | 3272 | free_netdev(dev1); |
@@ -3311,6 +3309,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3311 | sky2_read8(hw, B0_CTST); | 3309 | sky2_read8(hw, B0_CTST); |
3312 | 3310 | ||
3313 | free_irq(pdev->irq, hw); | 3311 | free_irq(pdev->irq, hw); |
3312 | pci_disable_msi(pdev); | ||
3314 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | 3313 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); |
3315 | pci_release_regions(pdev); | 3314 | pci_release_regions(pdev); |
3316 | pci_disable_device(pdev); | 3315 | pci_disable_device(pdev); |