diff options
Diffstat (limited to 'drivers/net/enic')
-rw-r--r-- | drivers/net/enic/cq_desc.h | 5 | ||||
-rw-r--r-- | drivers/net/enic/enic.h | 2 | ||||
-rw-r--r-- | drivers/net/enic/enic_main.c | 86 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.c | 7 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.h | 4 | ||||
-rw-r--r-- | drivers/net/enic/vnic_dev.c | 70 | ||||
-rw-r--r-- | drivers/net/enic/vnic_devcmd.h | 19 | ||||
-rw-r--r-- | drivers/net/enic/vnic_intr.h | 2 | ||||
-rw-r--r-- | drivers/net/enic/vnic_resource.h | 2 | ||||
-rw-r--r-- | drivers/net/enic/vnic_rq.h | 9 | ||||
-rw-r--r-- | drivers/net/enic/vnic_rss.h | 13 | ||||
-rw-r--r-- | drivers/net/enic/vnic_wq.h | 9 |
12 files changed, 146 insertions, 82 deletions
diff --git a/drivers/net/enic/cq_desc.h b/drivers/net/enic/cq_desc.h index c036a8bfd043..1eb289f773bf 100644 --- a/drivers/net/enic/cq_desc.h +++ b/drivers/net/enic/cq_desc.h | |||
@@ -44,9 +44,10 @@ struct cq_desc { | |||
44 | u8 type_color; | 44 | u8 type_color; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | #define CQ_DESC_TYPE_BITS 7 | 47 | #define CQ_DESC_TYPE_BITS 4 |
48 | #define CQ_DESC_TYPE_MASK ((1 << CQ_DESC_TYPE_BITS) - 1) | 48 | #define CQ_DESC_TYPE_MASK ((1 << CQ_DESC_TYPE_BITS) - 1) |
49 | #define CQ_DESC_COLOR_MASK 1 | 49 | #define CQ_DESC_COLOR_MASK 1 |
50 | #define CQ_DESC_COLOR_SHIFT 7 | ||
50 | #define CQ_DESC_Q_NUM_BITS 10 | 51 | #define CQ_DESC_Q_NUM_BITS 10 |
51 | #define CQ_DESC_Q_NUM_MASK ((1 << CQ_DESC_Q_NUM_BITS) - 1) | 52 | #define CQ_DESC_Q_NUM_MASK ((1 << CQ_DESC_Q_NUM_BITS) - 1) |
52 | #define CQ_DESC_COMP_NDX_BITS 12 | 53 | #define CQ_DESC_COMP_NDX_BITS 12 |
@@ -58,7 +59,7 @@ static inline void cq_desc_dec(const struct cq_desc *desc_arg, | |||
58 | const struct cq_desc *desc = desc_arg; | 59 | const struct cq_desc *desc = desc_arg; |
59 | const u8 type_color = desc->type_color; | 60 | const u8 type_color = desc->type_color; |
60 | 61 | ||
61 | *color = (type_color >> CQ_DESC_TYPE_BITS) & CQ_DESC_COLOR_MASK; | 62 | *color = (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK; |
62 | 63 | ||
63 | /* | 64 | /* |
64 | * Make sure color bit is read from desc *before* other fields | 65 | * Make sure color bit is read from desc *before* other fields |
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 7f677e89a788..a832cc5d6a1e 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h | |||
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | #define DRV_NAME "enic" | 34 | #define DRV_NAME "enic" |
35 | #define DRV_DESCRIPTION "Cisco 10G Ethernet Driver" | 35 | #define DRV_DESCRIPTION "Cisco 10G Ethernet Driver" |
36 | #define DRV_VERSION "0.0.1-18163.472-k1" | 36 | #define DRV_VERSION "1.0.0.648" |
37 | #define DRV_COPYRIGHT "Copyright 2008 Cisco Systems, Inc" | 37 | #define DRV_COPYRIGHT "Copyright 2008 Cisco Systems, Inc" |
38 | #define PFX DRV_NAME ": " | 38 | #define PFX DRV_NAME ": " |
39 | 39 | ||
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 180e968dc54d..d039e16f2763 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -273,6 +273,8 @@ static struct ethtool_ops enic_ethtool_ops = { | |||
273 | .set_sg = ethtool_op_set_sg, | 273 | .set_sg = ethtool_op_set_sg, |
274 | .get_tso = ethtool_op_get_tso, | 274 | .get_tso = ethtool_op_get_tso, |
275 | .set_tso = enic_set_tso, | 275 | .set_tso = enic_set_tso, |
276 | .get_flags = ethtool_op_get_flags, | ||
277 | .set_flags = ethtool_op_set_flags, | ||
276 | }; | 278 | }; |
277 | 279 | ||
278 | static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf) | 280 | static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf) |
@@ -409,8 +411,8 @@ static irqreturn_t enic_isr_legacy(int irq, void *data) | |||
409 | } | 411 | } |
410 | 412 | ||
411 | if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) { | 413 | if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) { |
412 | if (netif_rx_schedule_prep(netdev, &enic->napi)) | 414 | if (netif_rx_schedule_prep(&enic->napi)) |
413 | __netif_rx_schedule(netdev, &enic->napi); | 415 | __netif_rx_schedule(&enic->napi); |
414 | } else { | 416 | } else { |
415 | vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); | 417 | vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); |
416 | } | 418 | } |
@@ -438,7 +440,7 @@ static irqreturn_t enic_isr_msi(int irq, void *data) | |||
438 | * writes). | 440 | * writes). |
439 | */ | 441 | */ |
440 | 442 | ||
441 | netif_rx_schedule(enic->netdev, &enic->napi); | 443 | netif_rx_schedule(&enic->napi); |
442 | 444 | ||
443 | return IRQ_HANDLED; | 445 | return IRQ_HANDLED; |
444 | } | 446 | } |
@@ -448,7 +450,7 @@ static irqreturn_t enic_isr_msix_rq(int irq, void *data) | |||
448 | struct enic *enic = data; | 450 | struct enic *enic = data; |
449 | 451 | ||
450 | /* schedule NAPI polling for RQ cleanup */ | 452 | /* schedule NAPI polling for RQ cleanup */ |
451 | netif_rx_schedule(enic->netdev, &enic->napi); | 453 | netif_rx_schedule(&enic->napi); |
452 | 454 | ||
453 | return IRQ_HANDLED; | 455 | return IRQ_HANDLED; |
454 | } | 456 | } |
@@ -895,6 +897,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, | |||
895 | int skipped, void *opaque) | 897 | int skipped, void *opaque) |
896 | { | 898 | { |
897 | struct enic *enic = vnic_dev_priv(rq->vdev); | 899 | struct enic *enic = vnic_dev_priv(rq->vdev); |
900 | struct net_device *netdev = enic->netdev; | ||
898 | struct sk_buff *skb; | 901 | struct sk_buff *skb; |
899 | 902 | ||
900 | u8 type, color, eop, sop, ingress_port, vlan_stripped; | 903 | u8 type, color, eop, sop, ingress_port, vlan_stripped; |
@@ -929,7 +932,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, | |||
929 | if (net_ratelimit()) | 932 | if (net_ratelimit()) |
930 | printk(KERN_ERR PFX | 933 | printk(KERN_ERR PFX |
931 | "%s: packet error: bad FCS\n", | 934 | "%s: packet error: bad FCS\n", |
932 | enic->netdev->name); | 935 | netdev->name); |
933 | } | 936 | } |
934 | 937 | ||
935 | dev_kfree_skb_any(skb); | 938 | dev_kfree_skb_any(skb); |
@@ -943,19 +946,18 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, | |||
943 | */ | 946 | */ |
944 | 947 | ||
945 | skb_put(skb, bytes_written); | 948 | skb_put(skb, bytes_written); |
946 | skb->protocol = eth_type_trans(skb, enic->netdev); | 949 | skb->protocol = eth_type_trans(skb, netdev); |
947 | 950 | ||
948 | if (enic->csum_rx_enabled && !csum_not_calc) { | 951 | if (enic->csum_rx_enabled && !csum_not_calc) { |
949 | skb->csum = htons(checksum); | 952 | skb->csum = htons(checksum); |
950 | skb->ip_summed = CHECKSUM_COMPLETE; | 953 | skb->ip_summed = CHECKSUM_COMPLETE; |
951 | } | 954 | } |
952 | 955 | ||
953 | skb->dev = enic->netdev; | 956 | skb->dev = netdev; |
954 | enic->netdev->last_rx = jiffies; | ||
955 | 957 | ||
956 | if (enic->vlan_group && vlan_stripped) { | 958 | if (enic->vlan_group && vlan_stripped) { |
957 | 959 | ||
958 | if (ENIC_SETTING(enic, LRO) && ipv4) | 960 | if ((netdev->features & NETIF_F_LRO) && ipv4) |
959 | lro_vlan_hwaccel_receive_skb(&enic->lro_mgr, | 961 | lro_vlan_hwaccel_receive_skb(&enic->lro_mgr, |
960 | skb, enic->vlan_group, | 962 | skb, enic->vlan_group, |
961 | vlan, cq_desc); | 963 | vlan, cq_desc); |
@@ -965,7 +967,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, | |||
965 | 967 | ||
966 | } else { | 968 | } else { |
967 | 969 | ||
968 | if (ENIC_SETTING(enic, LRO) && ipv4) | 970 | if ((netdev->features & NETIF_F_LRO) && ipv4) |
969 | lro_receive_skb(&enic->lro_mgr, skb, cq_desc); | 971 | lro_receive_skb(&enic->lro_mgr, skb, cq_desc); |
970 | else | 972 | else |
971 | netif_receive_skb(skb); | 973 | netif_receive_skb(skb); |
@@ -1063,10 +1065,10 @@ static int enic_poll(struct napi_struct *napi, int budget) | |||
1063 | /* If no work done, flush all LROs and exit polling | 1065 | /* If no work done, flush all LROs and exit polling |
1064 | */ | 1066 | */ |
1065 | 1067 | ||
1066 | if (ENIC_SETTING(enic, LRO)) | 1068 | if (netdev->features & NETIF_F_LRO) |
1067 | lro_flush_all(&enic->lro_mgr); | 1069 | lro_flush_all(&enic->lro_mgr); |
1068 | 1070 | ||
1069 | netif_rx_complete(netdev, napi); | 1071 | netif_rx_complete(napi); |
1070 | vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); | 1072 | vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); |
1071 | } | 1073 | } |
1072 | 1074 | ||
@@ -1107,10 +1109,10 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) | |||
1107 | /* If no work done, flush all LROs and exit polling | 1109 | /* If no work done, flush all LROs and exit polling |
1108 | */ | 1110 | */ |
1109 | 1111 | ||
1110 | if (ENIC_SETTING(enic, LRO)) | 1112 | if (netdev->features & NETIF_F_LRO) |
1111 | lro_flush_all(&enic->lro_mgr); | 1113 | lro_flush_all(&enic->lro_mgr); |
1112 | 1114 | ||
1113 | netif_rx_complete(netdev, napi); | 1115 | netif_rx_complete(napi); |
1114 | vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); | 1116 | vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); |
1115 | } | 1117 | } |
1116 | 1118 | ||
@@ -1591,6 +1593,23 @@ static void enic_iounmap(struct enic *enic) | |||
1591 | iounmap(enic->bar0.vaddr); | 1593 | iounmap(enic->bar0.vaddr); |
1592 | } | 1594 | } |
1593 | 1595 | ||
1596 | static const struct net_device_ops enic_netdev_ops = { | ||
1597 | .ndo_open = enic_open, | ||
1598 | .ndo_stop = enic_stop, | ||
1599 | .ndo_start_xmit = enic_hard_start_xmit, | ||
1600 | .ndo_get_stats = enic_get_stats, | ||
1601 | .ndo_validate_addr = eth_validate_addr, | ||
1602 | .ndo_set_multicast_list = enic_set_multicast_list, | ||
1603 | .ndo_change_mtu = enic_change_mtu, | ||
1604 | .ndo_vlan_rx_register = enic_vlan_rx_register, | ||
1605 | .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid, | ||
1606 | .ndo_vlan_rx_kill_vid = enic_vlan_rx_kill_vid, | ||
1607 | .ndo_tx_timeout = enic_tx_timeout, | ||
1608 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1609 | .ndo_poll_controller = enic_poll_controller, | ||
1610 | #endif | ||
1611 | }; | ||
1612 | |||
1594 | static int __devinit enic_probe(struct pci_dev *pdev, | 1613 | static int __devinit enic_probe(struct pci_dev *pdev, |
1595 | const struct pci_device_id *ent) | 1614 | const struct pci_device_id *ent) |
1596 | { | 1615 | { |
@@ -1746,13 +1765,13 @@ static int __devinit enic_probe(struct pci_dev *pdev, | |||
1746 | } | 1765 | } |
1747 | 1766 | ||
1748 | /* Get available resource counts | 1767 | /* Get available resource counts |
1749 | */ | 1768 | */ |
1750 | 1769 | ||
1751 | enic_get_res_counts(enic); | 1770 | enic_get_res_counts(enic); |
1752 | 1771 | ||
1753 | /* Set interrupt mode based on resource counts and system | 1772 | /* Set interrupt mode based on resource counts and system |
1754 | * capabilities | 1773 | * capabilities |
1755 | */ | 1774 | */ |
1756 | 1775 | ||
1757 | err = enic_set_intr_mode(enic); | 1776 | err = enic_set_intr_mode(enic); |
1758 | if (err) { | 1777 | if (err) { |
@@ -1814,21 +1833,9 @@ static int __devinit enic_probe(struct pci_dev *pdev, | |||
1814 | goto err_out_free_vnic_resources; | 1833 | goto err_out_free_vnic_resources; |
1815 | } | 1834 | } |
1816 | 1835 | ||
1817 | netdev->open = enic_open; | 1836 | netdev->netdev_ops = &enic_netdev_ops; |
1818 | netdev->stop = enic_stop; | ||
1819 | netdev->hard_start_xmit = enic_hard_start_xmit; | ||
1820 | netdev->get_stats = enic_get_stats; | ||
1821 | netdev->set_multicast_list = enic_set_multicast_list; | ||
1822 | netdev->change_mtu = enic_change_mtu; | ||
1823 | netdev->vlan_rx_register = enic_vlan_rx_register; | ||
1824 | netdev->vlan_rx_add_vid = enic_vlan_rx_add_vid; | ||
1825 | netdev->vlan_rx_kill_vid = enic_vlan_rx_kill_vid; | ||
1826 | netdev->tx_timeout = enic_tx_timeout; | ||
1827 | netdev->watchdog_timeo = 2 * HZ; | 1837 | netdev->watchdog_timeo = 2 * HZ; |
1828 | netdev->ethtool_ops = &enic_ethtool_ops; | 1838 | netdev->ethtool_ops = &enic_ethtool_ops; |
1829 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1830 | netdev->poll_controller = enic_poll_controller; | ||
1831 | #endif | ||
1832 | 1839 | ||
1833 | switch (vnic_dev_get_intr_mode(enic->vdev)) { | 1840 | switch (vnic_dev_get_intr_mode(enic->vdev)) { |
1834 | default: | 1841 | default: |
@@ -1845,22 +1852,23 @@ static int __devinit enic_probe(struct pci_dev *pdev, | |||
1845 | if (ENIC_SETTING(enic, TSO)) | 1852 | if (ENIC_SETTING(enic, TSO)) |
1846 | netdev->features |= NETIF_F_TSO | | 1853 | netdev->features |= NETIF_F_TSO | |
1847 | NETIF_F_TSO6 | NETIF_F_TSO_ECN; | 1854 | NETIF_F_TSO6 | NETIF_F_TSO_ECN; |
1855 | if (ENIC_SETTING(enic, LRO)) | ||
1856 | netdev->features |= NETIF_F_LRO; | ||
1848 | if (using_dac) | 1857 | if (using_dac) |
1849 | netdev->features |= NETIF_F_HIGHDMA; | 1858 | netdev->features |= NETIF_F_HIGHDMA; |
1850 | 1859 | ||
1851 | 1860 | ||
1852 | enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM); | 1861 | enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM); |
1853 | 1862 | ||
1854 | if (ENIC_SETTING(enic, LRO)) { | 1863 | enic->lro_mgr.max_aggr = ENIC_LRO_MAX_AGGR; |
1855 | enic->lro_mgr.max_aggr = ENIC_LRO_MAX_AGGR; | 1864 | enic->lro_mgr.max_desc = ENIC_LRO_MAX_DESC; |
1856 | enic->lro_mgr.max_desc = ENIC_LRO_MAX_DESC; | 1865 | enic->lro_mgr.lro_arr = enic->lro_desc; |
1857 | enic->lro_mgr.lro_arr = enic->lro_desc; | 1866 | enic->lro_mgr.get_skb_header = enic_get_skb_header; |
1858 | enic->lro_mgr.get_skb_header = enic_get_skb_header; | 1867 | enic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; |
1859 | enic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; | 1868 | enic->lro_mgr.dev = netdev; |
1860 | enic->lro_mgr.dev = netdev; | 1869 | enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE; |
1861 | enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE; | 1870 | enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; |
1862 | enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; | 1871 | |
1863 | } | ||
1864 | 1872 | ||
1865 | err = register_netdev(netdev); | 1873 | err = register_netdev(netdev); |
1866 | if (err) { | 1874 | if (err) { |
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index 95184b9108ef..e5fc9384f8f5 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net/enic/enic_res.c | |||
@@ -90,11 +90,8 @@ int enic_get_vnic_config(struct enic *enic) | |||
90 | 90 | ||
91 | c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer); | 91 | c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer); |
92 | 92 | ||
93 | printk(KERN_INFO PFX "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x " | 93 | printk(KERN_INFO PFX "vNIC MAC addr %pM wq/rq %d/%d\n", |
94 | "wq/rq %d/%d\n", | 94 | enic->mac_addr, c->wq_desc_count, c->rq_desc_count); |
95 | enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2], | ||
96 | enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5], | ||
97 | c->wq_desc_count, c->rq_desc_count); | ||
98 | printk(KERN_INFO PFX "vNIC mtu %d csum tx/rx %d/%d tso/lro %d/%d " | 95 | printk(KERN_INFO PFX "vNIC mtu %d csum tx/rx %d/%d tso/lro %d/%d " |
99 | "intr timer %d\n", | 96 | "intr timer %d\n", |
100 | c->mtu, ENIC_SETTING(enic, TXCSUM), | 97 | c->mtu, ENIC_SETTING(enic, TXCSUM), |
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h index 68534a29b7ac..7bf272fa859b 100644 --- a/drivers/net/enic/enic_res.h +++ b/drivers/net/enic/enic_res.h | |||
@@ -58,8 +58,6 @@ static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq, | |||
58 | (u16)vlan_tag, | 58 | (u16)vlan_tag, |
59 | 0 /* loopback */); | 59 | 0 /* loopback */); |
60 | 60 | ||
61 | wmb(); | ||
62 | |||
63 | vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop); | 61 | vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop); |
64 | } | 62 | } |
65 | 63 | ||
@@ -127,8 +125,6 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq, | |||
127 | (u64)dma_addr | VNIC_PADDR_TARGET, | 125 | (u64)dma_addr | VNIC_PADDR_TARGET, |
128 | type, (u16)len); | 126 | type, (u16)len); |
129 | 127 | ||
130 | wmb(); | ||
131 | |||
132 | vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len); | 128 | vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len); |
133 | } | 129 | } |
134 | 130 | ||
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 4d104f5c30f9..11708579b6ce 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c | |||
@@ -43,6 +43,7 @@ struct vnic_dev { | |||
43 | struct vnic_devcmd_notify *notify; | 43 | struct vnic_devcmd_notify *notify; |
44 | struct vnic_devcmd_notify notify_copy; | 44 | struct vnic_devcmd_notify notify_copy; |
45 | dma_addr_t notify_pa; | 45 | dma_addr_t notify_pa; |
46 | u32 notify_sz; | ||
46 | u32 *linkstatus; | 47 | u32 *linkstatus; |
47 | dma_addr_t linkstatus_pa; | 48 | dma_addr_t linkstatus_pa; |
48 | struct vnic_stats *stats; | 49 | struct vnic_stats *stats; |
@@ -235,14 +236,6 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, | |||
235 | struct vnic_devcmd __iomem *devcmd = vdev->devcmd; | 236 | struct vnic_devcmd __iomem *devcmd = vdev->devcmd; |
236 | int delay; | 237 | int delay; |
237 | u32 status; | 238 | u32 status; |
238 | int dev_cmd_err[] = { | ||
239 | /* convert from fw's version of error.h to host's version */ | ||
240 | 0, /* ERR_SUCCESS */ | ||
241 | EINVAL, /* ERR_EINVAL */ | ||
242 | EFAULT, /* ERR_EFAULT */ | ||
243 | EPERM, /* ERR_EPERM */ | ||
244 | EBUSY, /* ERR_EBUSY */ | ||
245 | }; | ||
246 | int err; | 239 | int err; |
247 | 240 | ||
248 | status = ioread32(&devcmd->status); | 241 | status = ioread32(&devcmd->status); |
@@ -270,10 +263,12 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, | |||
270 | if (!(status & STAT_BUSY)) { | 263 | if (!(status & STAT_BUSY)) { |
271 | 264 | ||
272 | if (status & STAT_ERROR) { | 265 | if (status & STAT_ERROR) { |
273 | err = dev_cmd_err[(int)readq(&devcmd->args[0])]; | 266 | err = (int)readq(&devcmd->args[0]); |
274 | printk(KERN_ERR "Error %d devcmd %d\n", | 267 | if (err != ERR_ECMDUNKNOWN || |
275 | err, _CMD_N(cmd)); | 268 | cmd != CMD_CAPABILITY) |
276 | return -err; | 269 | printk(KERN_ERR "Error %d devcmd %d\n", |
270 | err, _CMD_N(cmd)); | ||
271 | return err; | ||
277 | } | 272 | } |
278 | 273 | ||
279 | if (_CMD_DIR(cmd) & _CMD_DIR_READ) { | 274 | if (_CMD_DIR(cmd) & _CMD_DIR_READ) { |
@@ -290,6 +285,17 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, | |||
290 | return -ETIMEDOUT; | 285 | return -ETIMEDOUT; |
291 | } | 286 | } |
292 | 287 | ||
288 | static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd) | ||
289 | { | ||
290 | u64 a0 = (u32)cmd, a1 = 0; | ||
291 | int wait = 1000; | ||
292 | int err; | ||
293 | |||
294 | err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait); | ||
295 | |||
296 | return !(err || a0); | ||
297 | } | ||
298 | |||
293 | int vnic_dev_fw_info(struct vnic_dev *vdev, | 299 | int vnic_dev_fw_info(struct vnic_dev *vdev, |
294 | struct vnic_devcmd_fw_info **fw_info) | 300 | struct vnic_devcmd_fw_info **fw_info) |
295 | { | 301 | { |
@@ -489,10 +495,7 @@ void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) | |||
489 | 495 | ||
490 | err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); | 496 | err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); |
491 | if (err) | 497 | if (err) |
492 | printk(KERN_ERR | 498 | printk(KERN_ERR "Can't add addr [%pM], %d\n", addr, err); |
493 | "Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", | ||
494 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], | ||
495 | err); | ||
496 | } | 499 | } |
497 | 500 | ||
498 | void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) | 501 | void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) |
@@ -507,16 +510,14 @@ void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) | |||
507 | 510 | ||
508 | err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); | 511 | err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); |
509 | if (err) | 512 | if (err) |
510 | printk(KERN_ERR | 513 | printk(KERN_ERR "Can't del addr [%pM], %d\n", addr, err); |
511 | "Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", | ||
512 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], | ||
513 | err); | ||
514 | } | 514 | } |
515 | 515 | ||
516 | int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) | 516 | int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) |
517 | { | 517 | { |
518 | u64 a0, a1; | 518 | u64 a0, a1; |
519 | int wait = 1000; | 519 | int wait = 1000; |
520 | int r; | ||
520 | 521 | ||
521 | if (!vdev->notify) { | 522 | if (!vdev->notify) { |
522 | vdev->notify = pci_alloc_consistent(vdev->pdev, | 523 | vdev->notify = pci_alloc_consistent(vdev->pdev, |
@@ -524,13 +525,16 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) | |||
524 | &vdev->notify_pa); | 525 | &vdev->notify_pa); |
525 | if (!vdev->notify) | 526 | if (!vdev->notify) |
526 | return -ENOMEM; | 527 | return -ENOMEM; |
528 | memset(vdev->notify, 0, sizeof(struct vnic_devcmd_notify)); | ||
527 | } | 529 | } |
528 | 530 | ||
529 | a0 = vdev->notify_pa; | 531 | a0 = vdev->notify_pa; |
530 | a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; | 532 | a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; |
531 | a1 += sizeof(struct vnic_devcmd_notify); | 533 | a1 += sizeof(struct vnic_devcmd_notify); |
532 | 534 | ||
533 | return vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); | 535 | r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); |
536 | vdev->notify_sz = (r == 0) ? (u32)a1 : 0; | ||
537 | return r; | ||
534 | } | 538 | } |
535 | 539 | ||
536 | void vnic_dev_notify_unset(struct vnic_dev *vdev) | 540 | void vnic_dev_notify_unset(struct vnic_dev *vdev) |
@@ -543,22 +547,22 @@ void vnic_dev_notify_unset(struct vnic_dev *vdev) | |||
543 | a1 += sizeof(struct vnic_devcmd_notify); | 547 | a1 += sizeof(struct vnic_devcmd_notify); |
544 | 548 | ||
545 | vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); | 549 | vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); |
550 | vdev->notify_sz = 0; | ||
546 | } | 551 | } |
547 | 552 | ||
548 | static int vnic_dev_notify_ready(struct vnic_dev *vdev) | 553 | static int vnic_dev_notify_ready(struct vnic_dev *vdev) |
549 | { | 554 | { |
550 | u32 *words; | 555 | u32 *words; |
551 | unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4; | 556 | unsigned int nwords = vdev->notify_sz / 4; |
552 | unsigned int i; | 557 | unsigned int i; |
553 | u32 csum; | 558 | u32 csum; |
554 | 559 | ||
555 | if (!vdev->notify) | 560 | if (!vdev->notify || !vdev->notify_sz) |
556 | return 0; | 561 | return 0; |
557 | 562 | ||
558 | do { | 563 | do { |
559 | csum = 0; | 564 | csum = 0; |
560 | memcpy(&vdev->notify_copy, vdev->notify, | 565 | memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz); |
561 | sizeof(struct vnic_devcmd_notify)); | ||
562 | words = (u32 *)&vdev->notify_copy; | 566 | words = (u32 *)&vdev->notify_copy; |
563 | for (i = 1; i < nwords; i++) | 567 | for (i = 1; i < nwords; i++) |
564 | csum += words[i]; | 568 | csum += words[i]; |
@@ -571,7 +575,20 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) | |||
571 | { | 575 | { |
572 | u64 a0 = (u32)arg, a1 = 0; | 576 | u64 a0 = (u32)arg, a1 = 0; |
573 | int wait = 1000; | 577 | int wait = 1000; |
574 | return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); | 578 | int r = 0; |
579 | |||
580 | if (vnic_dev_capable(vdev, CMD_INIT)) | ||
581 | r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); | ||
582 | else { | ||
583 | vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); | ||
584 | if (a0 & CMD_INITF_DEFAULT_MAC) { | ||
585 | // Emulate these for old CMD_INIT_v1 which | ||
586 | // didn't pass a0 so no CMD_INITF_*. | ||
587 | vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); | ||
588 | vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); | ||
589 | } | ||
590 | } | ||
591 | return r; | ||
575 | } | 592 | } |
576 | 593 | ||
577 | int vnic_dev_link_status(struct vnic_dev *vdev) | 594 | int vnic_dev_link_status(struct vnic_dev *vdev) |
@@ -672,3 +689,4 @@ err_out: | |||
672 | return NULL; | 689 | return NULL; |
673 | } | 690 | } |
674 | 691 | ||
692 | |||
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h index d8617a3373b1..8062c75154e6 100644 --- a/drivers/net/enic/vnic_devcmd.h +++ b/drivers/net/enic/vnic_devcmd.h | |||
@@ -168,7 +168,8 @@ enum vnic_devcmd_cmd { | |||
168 | CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25), | 168 | CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25), |
169 | 169 | ||
170 | /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */ | 170 | /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */ |
171 | CMD_INIT = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26), | 171 | /***** Replaced by CMD_INIT *****/ |
172 | CMD_INIT_v1 = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26), | ||
172 | 173 | ||
173 | /* variant of CMD_INIT, with provisioning info | 174 | /* variant of CMD_INIT, with provisioning info |
174 | * (u64)a0=paddr of vnic_devcmd_provinfo | 175 | * (u64)a0=paddr of vnic_devcmd_provinfo |
@@ -198,6 +199,14 @@ enum vnic_devcmd_cmd { | |||
198 | 199 | ||
199 | /* undo initialize of virtual link */ | 200 | /* undo initialize of virtual link */ |
200 | CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34), | 201 | CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34), |
202 | |||
203 | /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */ | ||
204 | CMD_INIT = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 35), | ||
205 | |||
206 | /* check fw capability of a cmd: | ||
207 | * in: (u32)a0=cmd | ||
208 | * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */ | ||
209 | CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36), | ||
201 | }; | 210 | }; |
202 | 211 | ||
203 | /* flags for CMD_OPEN */ | 212 | /* flags for CMD_OPEN */ |
@@ -249,8 +258,16 @@ struct vnic_devcmd_notify { | |||
249 | u32 uif; /* uplink interface */ | 258 | u32 uif; /* uplink interface */ |
250 | u32 status; /* status bits (see VNIC_STF_*) */ | 259 | u32 status; /* status bits (see VNIC_STF_*) */ |
251 | u32 error; /* error code (see ERR_*) for first ERR */ | 260 | u32 error; /* error code (see ERR_*) for first ERR */ |
261 | u32 link_down_cnt; /* running count of link down transitions */ | ||
252 | }; | 262 | }; |
253 | #define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */ | 263 | #define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */ |
264 | #define VNIC_STF_STD_PAUSE 0x0002 /* standard link-level pause on */ | ||
265 | #define VNIC_STF_PFC_PAUSE 0x0004 /* priority flow control pause on */ | ||
266 | /* all supported status flags */ | ||
267 | #define VNIC_STF_ALL (VNIC_STF_FATAL_ERR |\ | ||
268 | VNIC_STF_STD_PAUSE |\ | ||
269 | VNIC_STF_PFC_PAUSE |\ | ||
270 | 0) | ||
254 | 271 | ||
255 | struct vnic_devcmd_provinfo { | 272 | struct vnic_devcmd_provinfo { |
256 | u8 oui[3]; | 273 | u8 oui[3]; |
diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h index ccc408116af8..ce633a5a7e3c 100644 --- a/drivers/net/enic/vnic_intr.h +++ b/drivers/net/enic/vnic_intr.h | |||
@@ -78,7 +78,7 @@ static inline void vnic_intr_return_credits(struct vnic_intr *intr, | |||
78 | 78 | ||
79 | static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba) | 79 | static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba) |
80 | { | 80 | { |
81 | /* get and ack interrupt in one read (clear-and-ack-on-read) */ | 81 | /* read PBA without clearing */ |
82 | return ioread32(legacy_pba); | 82 | return ioread32(legacy_pba); |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/enic/vnic_resource.h index 144d2812f081..b61c22aec41a 100644 --- a/drivers/net/enic/vnic_resource.h +++ b/drivers/net/enic/vnic_resource.h | |||
@@ -38,7 +38,7 @@ enum vnic_res_type { | |||
38 | RES_TYPE_INTR_CTRL, /* Interrupt ctrl table */ | 38 | RES_TYPE_INTR_CTRL, /* Interrupt ctrl table */ |
39 | RES_TYPE_INTR_TABLE, /* MSI/MSI-X Interrupt table */ | 39 | RES_TYPE_INTR_TABLE, /* MSI/MSI-X Interrupt table */ |
40 | RES_TYPE_INTR_PBA, /* MSI/MSI-X PBA table */ | 40 | RES_TYPE_INTR_PBA, /* MSI/MSI-X PBA table */ |
41 | RES_TYPE_INTR_PBA_LEGACY, /* Legacy intr status, r2c */ | 41 | RES_TYPE_INTR_PBA_LEGACY, /* Legacy intr status */ |
42 | RES_TYPE_RSVD6, | 42 | RES_TYPE_RSVD6, |
43 | RES_TYPE_RSVD7, | 43 | RES_TYPE_RSVD7, |
44 | RES_TYPE_DEVCMD, /* Device command region */ | 44 | RES_TYPE_DEVCMD, /* Device command region */ |
diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h index 82bfca67cc4d..fd0ef66d2e9f 100644 --- a/drivers/net/enic/vnic_rq.h +++ b/drivers/net/enic/vnic_rq.h | |||
@@ -132,8 +132,15 @@ static inline void vnic_rq_post(struct vnic_rq *rq, | |||
132 | #define VNIC_RQ_RETURN_RATE 0xf /* keep 2^n - 1 */ | 132 | #define VNIC_RQ_RETURN_RATE 0xf /* keep 2^n - 1 */ |
133 | #endif | 133 | #endif |
134 | 134 | ||
135 | if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) | 135 | if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) { |
136 | /* Adding write memory barrier prevents compiler and/or CPU | ||
137 | * reordering, thus avoiding descriptor posting before | ||
138 | * descriptor is initialized. Otherwise, hardware can read | ||
139 | * stale descriptor fields. | ||
140 | */ | ||
141 | wmb(); | ||
136 | iowrite32(buf->index, &rq->ctrl->posted_index); | 142 | iowrite32(buf->index, &rq->ctrl->posted_index); |
143 | } | ||
137 | } | 144 | } |
138 | 145 | ||
139 | static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count) | 146 | static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count) |
diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/enic/vnic_rss.h index e325d65d7c34..5fbb3c923bcd 100644 --- a/drivers/net/enic/vnic_rss.h +++ b/drivers/net/enic/vnic_rss.h | |||
@@ -1,6 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2008 Cisco Systems, Inc. All rights reserved. | 2 | * Copyright 2008 Cisco Systems, Inc. All rights reserved. |
3 | * Copyright 2007 Nuova Systems, Inc. All rights reserved. | 3 | * Copyright 2007 Nuova Systems, Inc. All rights reserved. |
4 | * | ||
5 | * This program is free software; you may redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; version 2 of the License. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
10 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
11 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
12 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
13 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
15 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
16 | * SOFTWARE. | ||
4 | */ | 17 | */ |
5 | 18 | ||
6 | #ifndef _VNIC_RSS_H_ | 19 | #ifndef _VNIC_RSS_H_ |
diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/enic/vnic_wq.h index 7081828d8a42..c826137dc651 100644 --- a/drivers/net/enic/vnic_wq.h +++ b/drivers/net/enic/vnic_wq.h | |||
@@ -108,8 +108,15 @@ static inline void vnic_wq_post(struct vnic_wq *wq, | |||
108 | buf->len = len; | 108 | buf->len = len; |
109 | 109 | ||
110 | buf = buf->next; | 110 | buf = buf->next; |
111 | if (eop) | 111 | if (eop) { |
112 | /* Adding write memory barrier prevents compiler and/or CPU | ||
113 | * reordering, thus avoiding descriptor posting before | ||
114 | * descriptor is initialized. Otherwise, hardware can read | ||
115 | * stale descriptor fields. | ||
116 | */ | ||
117 | wmb(); | ||
112 | iowrite32(buf->index, &wq->ctrl->posted_index); | 118 | iowrite32(buf->index, &wq->ctrl->posted_index); |
119 | } | ||
113 | wq->to_use = buf; | 120 | wq->to_use = buf; |
114 | 121 | ||
115 | wq->ring.desc_avail--; | 122 | wq->ring.desc_avail--; |