diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 11:47:02 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-23 11:47:02 -0700 |
commit | 5f05647dd81c11a6a165ccc8f0c1370b16f3bcb0 (patch) | |
tree | 7851ef1c93aa1aba7ef327ca4b75fd35e6d10f29 /drivers/net/enic | |
parent | 02f36038c568111ad4fc433f6fa760ff5e38fab4 (diff) | |
parent | ec37a48d1d16c30b655ac5280209edf52a6775d4 (diff) | |
download | blackbird-op-linux-5f05647dd81c11a6a165ccc8f0c1370b16f3bcb0.tar.gz blackbird-op-linux-5f05647dd81c11a6a165ccc8f0c1370b16f3bcb0.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1699 commits)
bnx2/bnx2x: Unsupported Ethtool operations should return -EINVAL.
vlan: Calling vlan_hwaccel_do_receive() is always valid.
tproxy: use the interface primary IP address as a default value for --on-ip
tproxy: added IPv6 support to the socket match
cxgb3: function namespace cleanup
tproxy: added IPv6 support to the TPROXY target
tproxy: added IPv6 socket lookup function to nf_tproxy_core
be2net: Changes to use only priority codes allowed by f/w
tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled
tproxy: added tproxy sockopt interface in the IPV6 layer
tproxy: added udp6_lib_lookup function
tproxy: added const specifiers to udp lookup functions
tproxy: split off ipv6 defragmentation to a separate module
l2tp: small cleanup
nf_nat: restrict ICMP translation for embedded header
can: mcp251x: fix generation of error frames
can: mcp251x: fix endless loop in interrupt handler if CANINTF_MERRF is set
can-raw: add msg_flags to distinguish local traffic
9p: client code cleanup
rds: make local functions/variables static
...
Fix up conflicts in net/core/dev.c, drivers/net/pcmcia/smc91c92_cs.c and
drivers/net/wireless/ath/ath9k/debug.c as per David
Diffstat (limited to 'drivers/net/enic')
-rw-r--r-- | drivers/net/enic/enic.h | 27 | ||||
-rw-r--r-- | drivers/net/enic/enic_main.c | 415 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.c | 32 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.h | 2 | ||||
-rw-r--r-- | drivers/net/enic/vnic_dev.c | 133 | ||||
-rw-r--r-- | drivers/net/enic/vnic_dev.h | 19 | ||||
-rw-r--r-- | drivers/net/enic/vnic_devcmd.h | 12 | ||||
-rw-r--r-- | drivers/net/enic/vnic_enet.h | 2 | ||||
-rw-r--r-- | drivers/net/enic/vnic_intr.c | 5 | ||||
-rw-r--r-- | drivers/net/enic/vnic_resource.h | 13 | ||||
-rw-r--r-- | drivers/net/enic/vnic_rq.c | 8 | ||||
-rw-r--r-- | drivers/net/enic/vnic_rq.h | 6 | ||||
-rw-r--r-- | drivers/net/enic/vnic_rss.h | 5 | ||||
-rw-r--r-- | drivers/net/enic/vnic_vic.c | 7 | ||||
-rw-r--r-- | drivers/net/enic/vnic_wq.c | 8 | ||||
-rw-r--r-- | drivers/net/enic/vnic_wq.h | 4 |
16 files changed, 393 insertions, 305 deletions
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index f239aa8c6f4c..c91d364c5527 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -32,7 +32,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" -#define DRV_VERSION "1.4.1.1" +#define DRV_VERSION "1.4.1.6" #define DRV_COPYRIGHT "Copyright 2008-2010 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 @@ -42,25 +42,6 @@ #define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) #define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) -enum enic_cq_index { - ENIC_CQ_RQ, - ENIC_CQ_WQ, -}; - -enum enic_intx_intr_index { - ENIC_INTX_WQ_RQ, - ENIC_INTX_ERR, - ENIC_INTX_NOTIFY, -}; - -enum enic_msix_intr_index { - ENIC_MSIX_RQ, - ENIC_MSIX_WQ, - ENIC_MSIX_ERR, - ENIC_MSIX_NOTIFY, - ENIC_MSIX_MAX, -}; - struct enic_msix_entry { int requested; char devname[IFNAMSIZ]; @@ -91,8 +72,8 @@ struct enic { struct vnic_dev *vdev; struct timer_list notify_timer; struct work_struct reset; - struct msix_entry msix_entry[ENIC_MSIX_MAX]; - struct enic_msix_entry msix[ENIC_MSIX_MAX]; + struct msix_entry msix_entry[ENIC_INTR_MAX]; + struct enic_msix_entry msix[ENIC_INTR_MAX]; u32 msg_enable; spinlock_t devcmd_lock; u8 mac_addr[ETH_ALEN]; @@ -119,7 +100,7 @@ struct enic { int (*rq_alloc_buf)(struct vnic_rq *rq); u64 rq_truncated_pkts; u64 rq_bad_fcs; - struct napi_struct napi; + struct napi_struct napi[ENIC_RQ_MAX]; /* interrupt resource cache line section */ ____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX]; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 9aab85366d21..a466ef91dd43 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -122,6 +122,51 @@ static int enic_is_dynamic(struct enic *enic) return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; } +static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq) +{ + return rq; +} + +static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) +{ + return enic->rq_count + wq; +} + +static inline unsigned int enic_legacy_io_intr(void) +{ + return 0; +} + +static inline unsigned int enic_legacy_err_intr(void) +{ + return 1; +} + +static inline unsigned int enic_legacy_notify_intr(void) +{ + return 2; +} + +static inline unsigned int enic_msix_rq_intr(struct enic *enic, unsigned int rq) +{ + return rq; +} + +static inline unsigned int enic_msix_wq_intr(struct enic *enic, unsigned int wq) +{ + return enic->rq_count + wq; +} + +static inline unsigned int enic_msix_err_intr(struct enic *enic) +{ + return enic->rq_count + enic->wq_count; +} + +static inline unsigned int enic_msix_notify_intr(struct enic *enic) +{ + return enic->rq_count + enic->wq_count + 1; +} + static int enic_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { @@ -306,6 +351,7 @@ static int enic_set_coalesce(struct net_device *netdev, struct enic *enic = netdev_priv(netdev); u32 tx_coalesce_usecs; u32 rx_coalesce_usecs; + unsigned int i, intr; tx_coalesce_usecs = min_t(u32, INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), @@ -319,7 +365,8 @@ static int enic_set_coalesce(struct net_device *netdev, if (tx_coalesce_usecs != rx_coalesce_usecs) return -EINVAL; - vnic_intr_coalescing_timer_set(&enic->intr[ENIC_INTX_WQ_RQ], + intr = enic_legacy_io_intr(); + vnic_intr_coalescing_timer_set(&enic->intr[intr], INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); break; case VNIC_DEV_INTR_MODE_MSI: @@ -330,10 +377,18 @@ static int enic_set_coalesce(struct net_device *netdev, INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); break; case VNIC_DEV_INTR_MODE_MSIX: - vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_WQ], - INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); - vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_RQ], - INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs)); + for (i = 0; i < enic->wq_count; i++) { + intr = enic_msix_wq_intr(enic, i); + vnic_intr_coalescing_timer_set(&enic->intr[intr], + INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); + } + + for (i = 0; i < enic->rq_count; i++) { + intr = enic_msix_rq_intr(enic, i); + vnic_intr_coalescing_timer_set(&enic->intr[intr], + INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs)); + } + break; default: break; @@ -482,34 +537,37 @@ static irqreturn_t enic_isr_legacy(int irq, void *data) { struct net_device *netdev = data; struct enic *enic = netdev_priv(netdev); + unsigned int io_intr = enic_legacy_io_intr(); + unsigned int err_intr = enic_legacy_err_intr(); + unsigned int notify_intr = enic_legacy_notify_intr(); u32 pba; - vnic_intr_mask(&enic->intr[ENIC_INTX_WQ_RQ]); + vnic_intr_mask(&enic->intr[io_intr]); pba = vnic_intr_legacy_pba(enic->legacy_pba); if (!pba) { - vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); + vnic_intr_unmask(&enic->intr[io_intr]); return IRQ_NONE; /* not our interrupt */ } - if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) { - vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_NOTIFY]); + if (ENIC_TEST_INTR(pba, notify_intr)) { + vnic_intr_return_all_credits(&enic->intr[notify_intr]); enic_notify_check(enic); } - if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) { - vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_ERR]); + if (ENIC_TEST_INTR(pba, err_intr)) { + vnic_intr_return_all_credits(&enic->intr[err_intr]); enic_log_q_error(enic); /* schedule recovery from WQ/RQ error */ schedule_work(&enic->reset); return IRQ_HANDLED; } - if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) { - if (napi_schedule_prep(&enic->napi)) - __napi_schedule(&enic->napi); + if (ENIC_TEST_INTR(pba, io_intr)) { + if (napi_schedule_prep(&enic->napi[0])) + __napi_schedule(&enic->napi[0]); } else { - vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); + vnic_intr_unmask(&enic->intr[io_intr]); } return IRQ_HANDLED; @@ -535,17 +593,17 @@ static irqreturn_t enic_isr_msi(int irq, void *data) * writes). */ - napi_schedule(&enic->napi); + napi_schedule(&enic->napi[0]); return IRQ_HANDLED; } static irqreturn_t enic_isr_msix_rq(int irq, void *data) { - struct enic *enic = data; + struct napi_struct *napi = data; /* schedule NAPI polling for RQ cleanup */ - napi_schedule(&enic->napi); + napi_schedule(napi); return IRQ_HANDLED; } @@ -553,13 +611,15 @@ static irqreturn_t enic_isr_msix_rq(int irq, void *data) static irqreturn_t enic_isr_msix_wq(int irq, void *data) { struct enic *enic = data; + unsigned int cq = enic_cq_wq(enic, 0); + unsigned int intr = enic_msix_wq_intr(enic, 0); unsigned int wq_work_to_do = -1; /* no limit */ unsigned int wq_work_done; - wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], + wq_work_done = vnic_cq_service(&enic->cq[cq], wq_work_to_do, enic_wq_service, NULL); - vnic_intr_return_credits(&enic->intr[ENIC_MSIX_WQ], + vnic_intr_return_credits(&enic->intr[intr], wq_work_done, 1 /* unmask intr */, 1 /* reset intr timer */); @@ -570,8 +630,9 @@ static irqreturn_t enic_isr_msix_wq(int irq, void *data) static irqreturn_t enic_isr_msix_err(int irq, void *data) { struct enic *enic = data; + unsigned int intr = enic_msix_err_intr(enic); - vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_ERR]); + vnic_intr_return_all_credits(&enic->intr[intr]); enic_log_q_error(enic); @@ -584,8 +645,9 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data) static irqreturn_t enic_isr_msix_notify(int irq, void *data) { struct enic *enic = data; + unsigned int intr = enic_msix_notify_intr(enic); - vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_NOTIFY]); + vnic_intr_return_all_credits(&enic->intr[intr]); enic_notify_check(enic); return IRQ_HANDLED; @@ -743,7 +805,7 @@ static inline void enic_queue_wq_skb(struct enic *enic, int vlan_tag_insert = 0; int loopback = 0; - if (enic->vlan_group && vlan_tx_tag_present(skb)) { + if (vlan_tx_tag_present(skb)) { /* VLAN tag from trunking driver */ vlan_tag_insert = 1; vlan_tag = vlan_tx_tag_get(skb); @@ -911,7 +973,20 @@ static int enic_set_mac_address_dynamic(struct net_device *netdev, void *p) static int enic_set_mac_address(struct net_device *netdev, void *p) { - return -EOPNOTSUPP; + struct sockaddr *saddr = p; + char *addr = saddr->sa_data; + struct enic *enic = netdev_priv(netdev); + int err; + + err = enic_dev_del_station_addr(enic); + if (err) + return err; + + err = enic_set_mac_addr(netdev, addr); + if (err) + return err; + + return enic_dev_add_station_addr(enic); } static int enic_dev_packet_filter(struct enic *enic, int directed, @@ -1407,8 +1482,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, (vlan_tci & CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK)) { if (netdev->features & NETIF_F_GRO) - vlan_gro_receive(&enic->napi, enic->vlan_group, - vlan_tci, skb); + vlan_gro_receive(&enic->napi[q_number], + enic->vlan_group, vlan_tci, skb); else vlan_hwaccel_receive_skb(skb, enic->vlan_group, vlan_tci); @@ -1416,12 +1491,11 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, } else { if (netdev->features & NETIF_F_GRO) - napi_gro_receive(&enic->napi, skb); + napi_gro_receive(&enic->napi[q_number], skb); else netif_receive_skb(skb); } - } else { /* Buffer overflow @@ -1445,7 +1519,11 @@ static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, static int enic_poll(struct napi_struct *napi, int budget) { - struct enic *enic = container_of(napi, struct enic, napi); + struct net_device *netdev = napi->dev; + struct enic *enic = netdev_priv(netdev); + unsigned int cq_rq = enic_cq_rq(enic, 0); + unsigned int cq_wq = enic_cq_wq(enic, 0); + unsigned int intr = enic_legacy_io_intr(); unsigned int rq_work_to_do = budget; unsigned int wq_work_to_do = -1; /* no limit */ unsigned int work_done, rq_work_done, wq_work_done; @@ -1454,10 +1532,10 @@ static int enic_poll(struct napi_struct *napi, int budget) /* Service RQ (first) and WQ */ - rq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], + rq_work_done = vnic_cq_service(&enic->cq[cq_rq], rq_work_to_do, enic_rq_service, NULL); - wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], + wq_work_done = vnic_cq_service(&enic->cq[cq_wq], wq_work_to_do, enic_wq_service, NULL); /* Accumulate intr event credits for this polling @@ -1468,7 +1546,7 @@ static int enic_poll(struct napi_struct *napi, int budget) work_done = rq_work_done + wq_work_done; if (work_done > 0) - vnic_intr_return_credits(&enic->intr[ENIC_INTX_WQ_RQ], + vnic_intr_return_credits(&enic->intr[intr], work_done, 0 /* don't unmask intr */, 0 /* don't reset intr timer */); @@ -1489,7 +1567,7 @@ static int enic_poll(struct napi_struct *napi, int budget) */ napi_complete(napi); - vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); + vnic_intr_unmask(&enic->intr[intr]); } return rq_work_done; @@ -1497,7 +1575,11 @@ static int enic_poll(struct napi_struct *napi, int budget) static int enic_poll_msix(struct napi_struct *napi, int budget) { - struct enic *enic = container_of(napi, struct enic, napi); + struct net_device *netdev = napi->dev; + struct enic *enic = netdev_priv(netdev); + unsigned int rq = (napi - &enic->napi[0]); + unsigned int cq = enic_cq_rq(enic, rq); + unsigned int intr = enic_msix_rq_intr(enic, rq); unsigned int work_to_do = budget; unsigned int work_done; int err; @@ -1505,7 +1587,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) /* Service RQ */ - work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], + work_done = vnic_cq_service(&enic->cq[cq], work_to_do, enic_rq_service, NULL); /* Return intr event credits for this polling @@ -1514,12 +1596,12 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) */ if (work_done > 0) - vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], + vnic_intr_return_credits(&enic->intr[intr], work_done, 0 /* don't unmask intr */, 0 /* don't reset intr timer */); - err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); + err = vnic_rq_fill(&enic->rq[rq], enic->rq_alloc_buf); /* Buffer allocation failed. Stay in polling mode * so we can try to fill the ring again. @@ -1535,7 +1617,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) */ napi_complete(napi); - vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); + vnic_intr_unmask(&enic->intr[intr]); } return work_done; @@ -1577,7 +1659,7 @@ static void enic_free_intr(struct enic *enic) static int enic_request_intr(struct enic *enic) { struct net_device *netdev = enic->netdev; - unsigned int i; + unsigned int i, intr; int err = 0; switch (vnic_dev_get_intr_mode(enic->vdev)) { @@ -1596,27 +1678,38 @@ static int enic_request_intr(struct enic *enic) case VNIC_DEV_INTR_MODE_MSIX: - sprintf(enic->msix[ENIC_MSIX_RQ].devname, - "%.11s-rx-0", netdev->name); - enic->msix[ENIC_MSIX_RQ].isr = enic_isr_msix_rq; - enic->msix[ENIC_MSIX_RQ].devid = enic; + for (i = 0; i < enic->rq_count; i++) { + intr = enic_msix_rq_intr(enic, i); + sprintf(enic->msix[intr].devname, + "%.11s-rx-%d", netdev->name, i); + enic->msix[intr].isr = enic_isr_msix_rq; + enic->msix[intr].devid = &enic->napi[i]; + } - sprintf(enic->msix[ENIC_MSIX_WQ].devname, - "%.11s-tx-0", netdev->name); - enic->msix[ENIC_MSIX_WQ].isr = enic_isr_msix_wq; - enic->msix[ENIC_MSIX_WQ].devid = enic; + for (i = 0; i < enic->wq_count; i++) { + intr = enic_msix_wq_intr(enic, i); + sprintf(enic->msix[intr].devname, + "%.11s-tx-%d", netdev->name, i); + enic->msix[intr].isr = enic_isr_msix_wq; + enic->msix[intr].devid = enic; + } - sprintf(enic->msix[ENIC_MSIX_ERR].devname, + intr = enic_msix_err_intr(enic); + sprintf(enic->msix[intr].devname, "%.11s-err", netdev->name); - enic->msix[ENIC_MSIX_ERR].isr = enic_isr_msix_err; - enic->msix[ENIC_MSIX_ERR].devid = enic; + enic->msix[intr].isr = enic_isr_msix_err; + enic->msix[intr].devid = enic; - sprintf(enic->msix[ENIC_MSIX_NOTIFY].devname, + intr = enic_msix_notify_intr(enic); + sprintf(enic->msix[intr].devname, "%.11s-notify", netdev->name); - enic->msix[ENIC_MSIX_NOTIFY].isr = enic_isr_msix_notify; - enic->msix[ENIC_MSIX_NOTIFY].devid = enic; + enic->msix[intr].isr = enic_isr_msix_notify; + enic->msix[intr].devid = enic; + + for (i = 0; i < ARRAY_SIZE(enic->msix); i++) + enic->msix[i].requested = 0; - for (i = 0; i < ARRAY_SIZE(enic->msix); i++) { + for (i = 0; i < enic->intr_count; i++) { err = request_irq(enic->msix_entry[i].vector, enic->msix[i].isr, 0, enic->msix[i].devname, @@ -1662,10 +1755,12 @@ static int enic_dev_notify_set(struct enic *enic) spin_lock(&enic->devcmd_lock); switch (vnic_dev_get_intr_mode(enic->vdev)) { case VNIC_DEV_INTR_MODE_INTX: - err = vnic_dev_notify_set(enic->vdev, ENIC_INTX_NOTIFY); + err = vnic_dev_notify_set(enic->vdev, + enic_legacy_notify_intr()); break; case VNIC_DEV_INTR_MODE_MSIX: - err = vnic_dev_notify_set(enic->vdev, ENIC_MSIX_NOTIFY); + err = vnic_dev_notify_set(enic->vdev, + enic_msix_notify_intr(enic)); break; default: err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */); @@ -1692,7 +1787,7 @@ static int enic_dev_enable(struct enic *enic) int err; spin_lock(&enic->devcmd_lock); - err = vnic_dev_enable(enic->vdev); + err = vnic_dev_enable_wait(enic->vdev); spin_unlock(&enic->devcmd_lock); return err; @@ -1760,7 +1855,10 @@ static int enic_open(struct net_device *netdev) enic_set_multicast_list(netdev); netif_wake_queue(netdev); - napi_enable(&enic->napi); + + for (i = 0; i < enic->rq_count; i++) + napi_enable(&enic->napi[i]); + enic_dev_enable(enic); for (i = 0; i < enic->intr_count; i++) @@ -1795,7 +1893,10 @@ static int enic_stop(struct net_device *netdev) del_timer_sync(&enic->notify_timer); enic_dev_disable(enic); - napi_disable(&enic->napi); + + for (i = 0; i < enic->rq_count; i++) + napi_disable(&enic->napi[i]); + netif_carrier_off(netdev); netif_tx_disable(netdev); enic_dev_del_station_addr(enic); @@ -1855,11 +1956,16 @@ static void enic_poll_controller(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); struct vnic_dev *vdev = enic->vdev; + unsigned int i, intr; switch (vnic_dev_get_intr_mode(vdev)) { case VNIC_DEV_INTR_MODE_MSIX: - enic_isr_msix_rq(enic->pdev->irq, enic); - enic_isr_msix_wq(enic->pdev->irq, enic); + for (i = 0; i < enic->rq_count; i++) { + intr = enic_msix_rq_intr(enic, i); + enic_isr_msix_rq(enic->msix_entry[intr].vector, enic); + } + intr = enic_msix_wq_intr(enic, i); + enic_isr_msix_wq(enic->msix_entry[intr].vector, enic); break; case VNIC_DEV_INTR_MODE_MSI: enic_isr_msi(enic->pdev->irq, enic); @@ -1934,19 +2040,73 @@ static int enic_dev_hang_reset(struct enic *enic) return err; } -static int enic_set_niccfg(struct enic *enic) +static int enic_set_rsskey(struct enic *enic) +{ + u64 rss_key_buf_pa; + union vnic_rss_key *rss_key_buf_va = NULL; + union vnic_rss_key rss_key = { + .key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101}, + .key[1].b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101}, + .key[2].b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115}, + .key[3].b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108}, + }; + int err; + + rss_key_buf_va = pci_alloc_consistent(enic->pdev, + sizeof(union vnic_rss_key), &rss_key_buf_pa); + if (!rss_key_buf_va) + return -ENOMEM; + + memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key)); + + spin_lock(&enic->devcmd_lock); + err = enic_set_rss_key(enic, + rss_key_buf_pa, + sizeof(union vnic_rss_key)); + spin_unlock(&enic->devcmd_lock); + + pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key), + rss_key_buf_va, rss_key_buf_pa); + + return err; +} + +static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits) +{ + u64 rss_cpu_buf_pa; + union vnic_rss_cpu *rss_cpu_buf_va = NULL; + unsigned int i; + int err; + + rss_cpu_buf_va = pci_alloc_consistent(enic->pdev, + sizeof(union vnic_rss_cpu), &rss_cpu_buf_pa); + if (!rss_cpu_buf_va) + return -ENOMEM; + + for (i = 0; i < (1 << rss_hash_bits); i++) + (*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count; + + spin_lock(&enic->devcmd_lock); + err = enic_set_rss_cpu(enic, + rss_cpu_buf_pa, + sizeof(union vnic_rss_cpu)); + spin_unlock(&enic->devcmd_lock); + + pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu), + rss_cpu_buf_va, rss_cpu_buf_pa); + + return err; +} + +static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu, + u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable) { - const u8 rss_default_cpu = 0; - const u8 rss_hash_type = 0; - const u8 rss_hash_bits = 0; - const u8 rss_base_cpu = 0; - const u8 rss_enable = 0; const u8 tso_ipid_split_en = 0; const u8 ig_vlan_strip_en = 1; int err; - /* Enable VLAN tag stripping. RSS not enabled (yet). - */ + /* Enable VLAN tag stripping. + */ spin_lock(&enic->devcmd_lock); err = enic_set_nic_cfg(enic, @@ -1959,6 +2119,35 @@ static int enic_set_niccfg(struct enic *enic) return err; } +static int enic_set_rss_nic_cfg(struct enic *enic) +{ + struct device *dev = enic_get_dev(enic); + const u8 rss_default_cpu = 0; + const u8 rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 | + NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 | + NIC_CFG_RSS_HASH_TYPE_IPV6 | + NIC_CFG_RSS_HASH_TYPE_TCP_IPV6; + const u8 rss_hash_bits = 7; + const u8 rss_base_cpu = 0; + u8 rss_enable = ENIC_SETTING(enic, RSS) && (enic->rq_count > 1); + + if (rss_enable) { + if (!enic_set_rsskey(enic)) { + if (enic_set_rsscpu(enic, rss_hash_bits)) { + rss_enable = 0; + dev_warn(dev, "RSS disabled, " + "Failed to set RSS cpu indirection table."); + } + } else { + rss_enable = 0; + dev_warn(dev, "RSS disabled, Failed to set RSS key.\n"); + } + } + + return enic_set_niccfg(enic, rss_default_cpu, rss_hash_type, + rss_hash_bits, rss_base_cpu, rss_enable); +} + static int enic_dev_hang_notify(struct enic *enic) { int err; @@ -1970,7 +2159,7 @@ static int enic_dev_hang_notify(struct enic *enic) return err; } -int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic) +static int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic) { int err; @@ -1996,7 +2185,7 @@ static void enic_reset(struct work_struct *work) enic_dev_hang_reset(enic); enic_reset_multicast_list(enic); enic_init_vnic_resources(enic); - enic_set_niccfg(enic); + enic_set_rss_nic_cfg(enic); enic_dev_set_ig_vlan_rewrite_mode(enic); enic_open(enic->netdev); @@ -2005,12 +2194,12 @@ static void enic_reset(struct work_struct *work) static int enic_set_intr_mode(struct enic *enic) { - unsigned int n = 1; + unsigned int n = min_t(unsigned int, enic->rq_count, ENIC_RQ_MAX); unsigned int m = 1; unsigned int i; /* Set interrupt mode (INTx, MSI, MSI-X) depending - * system capabilities. + * on system capabilities. * * Try MSI-X first * @@ -2023,21 +2212,47 @@ static int enic_set_intr_mode(struct enic *enic) for (i = 0; i < n + m + 2; i++) enic->msix_entry[i].entry = i; - if (enic->config.intr_mode < 1 && + /* Use multiple RQs if RSS is enabled + */ + + if (ENIC_SETTING(enic, RSS) && + enic->config.intr_mode < 1 && enic->rq_count >= n && enic->wq_count >= m && enic->cq_count >= n + m && - enic->intr_count >= n + m + 2 && - !pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) { + enic->intr_count >= n + m + 2) { - enic->rq_count = n; - enic->wq_count = m; - enic->cq_count = n + m; - enic->intr_count = n + m + 2; + if (!pci_enable_msix(enic->pdev, enic->msix_entry, n + m + 2)) { - vnic_dev_set_intr_mode(enic->vdev, VNIC_DEV_INTR_MODE_MSIX); + enic->rq_count = n; + enic->wq_count = m; + enic->cq_count = n + m; + enic->intr_count = n + m + 2; - return 0; + vnic_dev_set_intr_mode(enic->vdev, + VNIC_DEV_INTR_MODE_MSIX); + + return 0; + } + } + + if (enic->config.intr_mode < 1 && + enic->rq_count >= 1 && + enic->wq_count >= m && + enic->cq_count >= 1 + m && + enic->intr_count >= 1 + m + 2) { + if (!pci_enable_msix(enic->pdev, enic->msix_entry, 1 + m + 2)) { + + enic->rq_count = 1; + enic->wq_count = m; + enic->cq_count = 1 + m; + enic->intr_count = 1 + m + 2; + + vnic_dev_set_intr_mode(enic->vdev, + VNIC_DEV_INTR_MODE_MSIX); + + return 0; + } } /* Next try MSI @@ -2145,28 +2360,22 @@ static const struct net_device_ops enic_netdev_ops = { #endif }; -void enic_dev_deinit(struct enic *enic) +static void enic_dev_deinit(struct enic *enic) { - netif_napi_del(&enic->napi); - enic_free_vnic_resources(enic); - enic_clear_intr_mode(enic); -} - -static int enic_dev_stats_clear(struct enic *enic) -{ - int err; + unsigned int i; - spin_lock(&enic->devcmd_lock); - err = vnic_dev_stats_clear(enic->vdev); - spin_unlock(&enic->devcmd_lock); + for (i = 0; i < enic->rq_count; i++) + netif_napi_del(&enic->napi[i]); - return err; + enic_free_vnic_resources(enic); + enic_clear_intr_mode(enic); } -int enic_dev_init(struct enic *enic) +static int enic_dev_init(struct enic *enic) { struct device *dev = enic_get_dev(enic); struct net_device *netdev = enic->netdev; + unsigned int i; int err; /* Get vNIC configuration @@ -2205,17 +2414,13 @@ int enic_dev_init(struct enic *enic) enic_init_vnic_resources(enic); - /* Clear LIF stats - */ - enic_dev_stats_clear(enic); - err = enic_set_rq_alloc_buf(enic); if (err) { dev_err(dev, "Failed to set RQ buffer allocator, aborting\n"); goto err_out_free_vnic_resources; } - err = enic_set_niccfg(enic); + err = enic_set_rss_nic_cfg(enic); if (err) { dev_err(dev, "Failed to config nic, aborting\n"); goto err_out_free_vnic_resources; @@ -2223,17 +2428,19 @@ int enic_dev_init(struct enic *enic) err = enic_dev_set_ig_vlan_rewrite_mode(enic); if (err) { - netdev_err(netdev, + dev_err(dev, "Failed to set ingress vlan rewrite mode, aborting.\n"); goto err_out_free_vnic_resources; } switch (vnic_dev_get_intr_mode(enic->vdev)) { default: - netif_napi_add(netdev, &enic->napi, enic_poll, 64); + netif_napi_add(netdev, &enic->napi[0], enic_poll, 64); break; case VNIC_DEV_INTR_MODE_MSIX: - netif_napi_add(netdev, &enic->napi, enic_poll_msix, 64); + for (i = 0; i < enic->rq_count; i++) + netif_napi_add(netdev, &enic->napi[i], + enic_poll_msix, 64); break; } diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index 29ede8a17a2c..f111a37419ce 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net/enic/enic_res.c @@ -94,13 +94,14 @@ int enic_get_vnic_config(struct enic *enic) INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), c->intr_timer_usec); - dev_info(enic_get_dev(enic), "vNIC MAC addr %pM wq/rq %d/%d\n", - enic->mac_addr, c->wq_desc_count, c->rq_desc_count); - dev_info(enic_get_dev(enic), "vNIC mtu %d csum tx/rx %d/%d " - "tso/lro %d/%d intr timer %d usec\n", - c->mtu, ENIC_SETTING(enic, TXCSUM), - ENIC_SETTING(enic, RXCSUM), ENIC_SETTING(enic, TSO), - ENIC_SETTING(enic, LRO), c->intr_timer_usec); + dev_info(enic_get_dev(enic), + "vNIC MAC addr %pM wq/rq %d/%d mtu %d\n", + enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu); + dev_info(enic_get_dev(enic), "vNIC csum tx/rx %d/%d " + "tso/lro %d/%d intr timer %d usec rss %d\n", + ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM), + ENIC_SETTING(enic, TSO), ENIC_SETTING(enic, LRO), + c->intr_timer_usec, ENIC_SETTING(enic, RSS)); return 0; } @@ -181,18 +182,11 @@ void enic_free_vnic_resources(struct enic *enic) void enic_get_res_counts(struct enic *enic) { - enic->wq_count = min_t(int, - vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ), - ENIC_WQ_MAX); - enic->rq_count = min_t(int, - vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ), - ENIC_RQ_MAX); - enic->cq_count = min_t(int, - vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ), - ENIC_CQ_MAX); - enic->intr_count = min_t(int, - vnic_dev_get_res_count(enic->vdev, RES_TYPE_INTR_CTRL), - ENIC_INTR_MAX); + enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ); + enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ); + enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ); + enic->intr_count = vnic_dev_get_res_count(enic->vdev, + RES_TYPE_INTR_CTRL); dev_info(enic_get_dev(enic), "vNIC resources avail: wq %d rq %d cq %d intr %d\n", diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h index 83bd172c356c..9a103d9ef9e2 100644 --- a/drivers/net/enic/enic_res.h +++ b/drivers/net/enic/enic_res.h @@ -30,7 +30,7 @@ #define ENIC_MIN_RQ_DESCS 64 #define ENIC_MAX_RQ_DESCS 4096 -#define ENIC_MIN_MTU 576 /* minimum for IPv4 */ +#define ENIC_MIN_MTU 68 #define ENIC_MAX_MTU 9000 #define ENIC_MULTICAST_PERFECT_FILTERS 32 diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 6a5b578a69e1..fb35d8b17668 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -74,6 +74,7 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev, struct vnic_dev_bar *bar, unsigned int num_bars) { struct vnic_resource_header __iomem *rh; + struct mgmt_barmap_hdr __iomem *mrh; struct vnic_resource __iomem *r; u8 type; @@ -85,22 +86,32 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev, return -EINVAL; } - rh = bar->vaddr; + rh = bar->vaddr; + mrh = bar->vaddr; if (!rh) { pr_err("vNIC BAR0 res hdr not mem-mapped\n"); return -EINVAL; } - if (ioread32(&rh->magic) != VNIC_RES_MAGIC || - ioread32(&rh->version) != VNIC_RES_VERSION) { - pr_err("vNIC BAR0 res magic/version error " - "exp (%lx/%lx) curr (%x/%x)\n", + /* Check for mgmt vnic in addition to normal vnic */ + if ((ioread32(&rh->magic) != VNIC_RES_MAGIC) || + (ioread32(&rh->version) != VNIC_RES_VERSION)) { + if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) || + (ioread32(&mrh->version) != MGMTVNIC_VERSION)) { + pr_err("vNIC BAR0 res magic/version error " + "exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n", VNIC_RES_MAGIC, VNIC_RES_VERSION, + MGMTVNIC_MAGIC, MGMTVNIC_VERSION, ioread32(&rh->magic), ioread32(&rh->version)); - return -EINVAL; + return -EINVAL; + } } - r = (struct vnic_resource __iomem *)(rh + 1); + if (ioread32(&mrh->magic) == MGMTVNIC_MAGIC) + r = (struct vnic_resource __iomem *)(mrh + 1); + else + r = (struct vnic_resource __iomem *)(rh + 1); + while ((type = ioread8(&r->type)) != RES_TYPE_EOL) { @@ -175,22 +186,7 @@ void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, } } -dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev, - enum vnic_res_type type, unsigned int index) -{ - switch (type) { - case RES_TYPE_WQ: - case RES_TYPE_RQ: - case RES_TYPE_CQ: - case RES_TYPE_INTR_CTRL: - return vdev->res[type].bus_addr + - index * VNIC_RES_STRIDE; - default: - return vdev->res[type].bus_addr; - } -} - -unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring, +static unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring, unsigned int desc_count, unsigned int desc_size) { /* The base address of the desc rings must be 512 byte aligned. @@ -373,18 +369,6 @@ static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev, return err; } -void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf) -{ - vdev->proxy = PROXY_BY_BDF; - vdev->proxy_index = bdf; -} - -void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev) -{ - vdev->proxy = PROXY_NONE; - vdev->proxy_index = 0; -} - int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait) { @@ -477,13 +461,6 @@ int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size, return err; } -int vnic_dev_stats_clear(struct vnic_dev *vdev) -{ - u64 a0 = 0, a1 = 0; - int wait = 1000; - return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait); -} - int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats) { u64 a0, a1; @@ -510,13 +487,6 @@ int vnic_dev_close(struct vnic_dev *vdev) return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait); } -int vnic_dev_enable(struct vnic_dev *vdev) -{ - u64 a0 = 0, a1 = 0; - int wait = 1000; - return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait); -} - int vnic_dev_enable_wait(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; @@ -561,14 +531,14 @@ int vnic_dev_open_done(struct vnic_dev *vdev, int *done) return 0; } -int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg) +static int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait); } -int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) +static int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) { u64 a0 = 0, a1 = 0; int wait = 1000; @@ -669,26 +639,6 @@ int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, return err; } -int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed, - int multicast, int broadcast, int promisc, int allmulti) -{ - u64 a0, a1 = 0; - int wait = 1000; - int err; - - a0 = (directed ? CMD_PFILTER_DIRECTED : 0) | - (multicast ? CMD_PFILTER_MULTICAST : 0) | - (broadcast ? CMD_PFILTER_BROADCAST : 0) | - (promisc ? CMD_PFILTER_PROMISCUOUS : 0) | - (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0); - - err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER_ALL, &a0, &a1, wait); - if (err) - pr_err("Can't set packet filter\n"); - - return err; -} - int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) { u64 a0 = 0, a1 = 0; @@ -737,20 +687,7 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, return err; } -int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr) -{ - u64 a0 = intr, a1 = 0; - int wait = 1000; - int err; - - err = vnic_dev_cmd(vdev, CMD_IAR, &a0, &a1, wait); - if (err) - pr_err("Failed to raise INTR[%d], err %d\n", intr, err); - - return err; -} - -int vnic_dev_notify_setcmd(struct vnic_dev *vdev, +static int vnic_dev_notify_setcmd(struct vnic_dev *vdev, void *notify_addr, dma_addr_t notify_pa, u16 intr) { u64 a0, a1; @@ -789,7 +726,7 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr); } -int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev) +static int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev) { u64 a0, a1; int wait = 1000; @@ -943,30 +880,6 @@ u32 vnic_dev_mtu(struct vnic_dev *vdev) return vdev->notify_copy.mtu; } -u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev) -{ - if (!vnic_dev_notify_ready(vdev)) - return 0; - - return vdev->notify_copy.link_down_cnt; -} - -u32 vnic_dev_notify_status(struct vnic_dev *vdev) -{ - if (!vnic_dev_notify_ready(vdev)) - return 0; - - return vdev->notify_copy.status; -} - -u32 vnic_dev_uif(struct vnic_dev *vdev) -{ - if (!vnic_dev_notify_ready(vdev)) - return 0; - - return vdev->notify_copy.uif; -} - void vnic_dev_set_intr_mode(struct vnic_dev *vdev, enum vnic_dev_intr_mode intr_mode) { diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h index 3a61873138b6..05f9a24cd459 100644 --- a/drivers/net/enic/vnic_dev.h +++ b/drivers/net/enic/vnic_dev.h @@ -84,10 +84,6 @@ unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev, enum vnic_res_type type); void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, unsigned int index); -dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev, - enum vnic_res_type type, unsigned int index); -unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring, - unsigned int desc_count, unsigned int desc_size); void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring); int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring, unsigned int desc_count, unsigned int desc_size); @@ -95,39 +91,26 @@ void vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring); int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait); -void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf); -void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev); int vnic_dev_fw_info(struct vnic_dev *vdev, struct vnic_devcmd_fw_info **fw_info); int vnic_dev_hw_version(struct vnic_dev *vdev, enum vnic_dev_hw_version *hw_ver); int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size, void *value); -int vnic_dev_stats_clear(struct vnic_dev *vdev); int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats); int vnic_dev_hang_notify(struct vnic_dev *vdev); int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, int broadcast, int promisc, int allmulti); -int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed, - int multicast, int broadcast, int promisc, int allmulti); int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr); int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr); int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); -int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr); -int vnic_dev_notify_setcmd(struct vnic_dev *vdev, - void *notify_addr, dma_addr_t notify_pa, u16 intr); int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr); -int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev); int vnic_dev_notify_unset(struct vnic_dev *vdev); int vnic_dev_link_status(struct vnic_dev *vdev); u32 vnic_dev_port_speed(struct vnic_dev *vdev); u32 vnic_dev_msg_lvl(struct vnic_dev *vdev); u32 vnic_dev_mtu(struct vnic_dev *vdev); -u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev); -u32 vnic_dev_notify_status(struct vnic_dev *vdev); -u32 vnic_dev_uif(struct vnic_dev *vdev); int vnic_dev_close(struct vnic_dev *vdev); -int vnic_dev_enable(struct vnic_dev *vdev); int vnic_dev_enable_wait(struct vnic_dev *vdev); int vnic_dev_disable(struct vnic_dev *vdev); int vnic_dev_open(struct vnic_dev *vdev, int arg); @@ -136,8 +119,6 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg); int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err); int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len); int vnic_dev_deinit(struct vnic_dev *vdev); -int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); -int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg); int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done); void vnic_dev_set_intr_mode(struct vnic_dev *vdev, diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h index 20661755df6b..9abb3d51dea1 100644 --- a/drivers/net/enic/vnic_devcmd.h +++ b/drivers/net/enic/vnic_devcmd.h @@ -238,6 +238,18 @@ enum vnic_devcmd_cmd { * out: (u32)a0=status of proxied cmd * a1-a15=out args of proxied cmd */ CMD_PROXY_BY_BDF = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42), + + /* + * As for BY_BDF except a0 is index of hvnlink subordinate vnic + * or SR-IOV virtual vnic */ + CMD_PROXY_BY_INDEX = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43), + + /* + * in: (u64)a0=paddr of buffer to put latest VIC VIF-CONFIG-INFO TLV in + * (u32)a1=length of buffer in a0 + * out: (u64)a0=paddr of buffer with latest VIC VIF-CONFIG-INFO TLV + * (u32)a1=actual length of latest VIC VIF-CONFIG-INFO TLV */ + CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44), }; /* flags for CMD_OPEN */ diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h index 3b3291248956..e8740e3704e4 100644 --- a/drivers/net/enic/vnic_enet.h +++ b/drivers/net/enic/vnic_enet.h @@ -30,7 +30,7 @@ struct vnic_enet_config { u32 wq_desc_count; u32 rq_desc_count; u16 mtu; - u16 intr_timer; + u16 intr_timer_deprecated; u8 intr_timer_type; u8 intr_mode; char devname[16]; diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c index 52ab61af2750..3873771d75cc 100644 --- a/drivers/net/enic/vnic_intr.c +++ b/drivers/net/enic/vnic_intr.c @@ -65,8 +65,3 @@ void vnic_intr_clean(struct vnic_intr *intr) { iowrite32(0, &intr->ctrl->int_credits); } - -void vnic_intr_raise(struct vnic_intr *intr) -{ - vnic_dev_raise_intr(intr->vdev, (u16)intr->index); -} diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/enic/vnic_resource.h index 810287beff14..e0a73f1ca6f4 100644 --- a/drivers/net/enic/vnic_resource.h +++ b/drivers/net/enic/vnic_resource.h @@ -22,6 +22,11 @@ #define VNIC_RES_MAGIC 0x766E6963L /* 'vnic' */ #define VNIC_RES_VERSION 0x00000000L +#define MGMTVNIC_MAGIC 0x544d474dL /* 'MGMT' */ +#define MGMTVNIC_VERSION 0x00000000L + +/* The MAC address assigned to the CFG vNIC is fixed. */ +#define MGMTVNIC_MAC { 0x02, 0x00, 0x54, 0x4d, 0x47, 0x4d } /* vNIC resource types */ enum vnic_res_type { @@ -52,6 +57,14 @@ struct vnic_resource_header { u32 version; }; +struct mgmt_barmap_hdr { + u32 magic; /* magic number */ + u32 version; /* header format version */ + u16 lif; /* loopback lif for mgmt frames */ + u16 pci_slot; /* installed pci slot */ + char serial[16]; /* card serial number */ +}; + struct vnic_resource { u8 type; u8 bar; diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c index dbb2aca258b9..34105e0951a5 100644 --- a/drivers/net/enic/vnic_rq.c +++ b/drivers/net/enic/vnic_rq.c @@ -77,8 +77,10 @@ void vnic_rq_free(struct vnic_rq *rq) vnic_dev_free_desc_ring(vdev, &rq->ring); for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) { - kfree(rq->bufs[i]); - rq->bufs[i] = NULL; + if (rq->bufs[i]) { + kfree(rq->bufs[i]); + rq->bufs[i] = NULL; + } } rq->ctrl = NULL; @@ -113,7 +115,7 @@ int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index, return 0; } -void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index, +static void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index, unsigned int fetch_index, unsigned int posted_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset) diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h index 2dc48f91abf7..37f08de2454a 100644 --- a/drivers/net/enic/vnic_rq.h +++ b/drivers/net/enic/vnic_rq.h @@ -143,7 +143,7 @@ static inline void vnic_rq_post(struct vnic_rq *rq, static inline int vnic_rq_posting_soon(struct vnic_rq *rq) { - return ((rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0); + return (rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0; } static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count) @@ -202,10 +202,6 @@ static inline int vnic_rq_fill(struct vnic_rq *rq, void vnic_rq_free(struct vnic_rq *rq); int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index, unsigned int desc_count, unsigned int desc_size); -void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index, - unsigned int fetch_index, unsigned int posted_index, - unsigned int error_interrupt_enable, - unsigned int error_interrupt_offset); void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset); diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/enic/vnic_rss.h index f62d18719629..fa421baf45b8 100644 --- a/drivers/net/enic/vnic_rss.h +++ b/drivers/net/enic/vnic_rss.h @@ -37,9 +37,4 @@ union vnic_rss_cpu { u64 raw[32]; }; -void vnic_set_rss_key(union vnic_rss_key *rss_key, u8 *key); -void vnic_set_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu); -void vnic_get_rss_key(union vnic_rss_key *rss_key, u8 *key); -void vnic_get_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu); - #endif /* _VNIC_RSS_H_ */ diff --git a/drivers/net/enic/vnic_vic.c b/drivers/net/enic/vnic_vic.c index 197c9d24af82..4725b79de0ef 100644 --- a/drivers/net/enic/vnic_vic.c +++ b/drivers/net/enic/vnic_vic.c @@ -54,8 +54,8 @@ int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, if (!vp || !value) return -EINVAL; - if (ntohl(vp->length) + sizeof(*tlv) + length > - VIC_PROVINFO_MAX_TLV_DATA) + if (ntohl(vp->length) + offsetof(struct vic_provinfo_tlv, value) + + length > VIC_PROVINFO_MAX_TLV_DATA) return -ENOMEM; tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv + @@ -66,7 +66,8 @@ int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, memcpy(tlv->value, value, length); vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1); - vp->length = htonl(ntohl(vp->length) + sizeof(*tlv) + length); + vp->length = htonl(ntohl(vp->length) + + offsetof(struct vic_provinfo_tlv, value) + length); return 0; } diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c index 122e33bcc578..df61bd932ea6 100644 --- a/drivers/net/enic/vnic_wq.c +++ b/drivers/net/enic/vnic_wq.c @@ -77,8 +77,10 @@ void vnic_wq_free(struct vnic_wq *wq) vnic_dev_free_desc_ring(vdev, &wq->ring); for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) { - kfree(wq->bufs[i]); - wq->bufs[i] = NULL; + if (wq->bufs[i]) { + kfree(wq->bufs[i]); + wq->bufs[i] = NULL; + } } wq->ctrl = NULL; @@ -113,7 +115,7 @@ int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, return 0; } -void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, +static void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, unsigned int fetch_index, unsigned int posted_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset) diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/enic/vnic_wq.h index 94ac4621acc5..7dd937ac11c2 100644 --- a/drivers/net/enic/vnic_wq.h +++ b/drivers/net/enic/vnic_wq.h @@ -153,10 +153,6 @@ static inline void vnic_wq_service(struct vnic_wq *wq, void vnic_wq_free(struct vnic_wq *wq); int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, unsigned int desc_count, unsigned int desc_size); -void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, - unsigned int fetch_index, unsigned int posted_index, - unsigned int error_interrupt_enable, - unsigned int error_interrupt_offset); void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset); |