diff options
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 368 |
1 files changed, 198 insertions, 170 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 93ff8ef3935..9a18e7930b3 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -86,6 +86,7 @@ static const char * const ue_status_low_desc[] = { "JTAG ", "MPU_INTPEND " }; + /* UE Status High CSR */ static const char * const ue_status_hi_desc[] = { "LPCMEMHOST", @@ -122,10 +123,10 @@ static const char * const ue_status_hi_desc[] = { "Unknown" }; - static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) { struct be_dma_mem *mem = &q->dma_mem; + if (mem->va) { dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va, mem->dma); @@ -187,6 +188,7 @@ static void be_intr_set(struct be_adapter *adapter, bool enable) static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted) { u32 val = 0; + val |= qid & DB_RQ_RING_ID_MASK; val |= posted << DB_RQ_NUM_POSTED_SHIFT; @@ -198,6 +200,7 @@ static void be_txq_notify(struct be_adapter *adapter, struct be_tx_obj *txo, u16 posted) { u32 val = 0; + val |= txo->q.id & DB_TXULP_RING_ID_MASK; val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT; @@ -209,6 +212,7 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, bool arm, bool clear_int, u16 num_popped) { u32 val = 0; + val |= qid & DB_EQ_RING_ID_MASK; val |= ((qid & DB_EQ_RING_ID_EXT_MASK) << DB_EQ_RING_ID_EXT_MASK_SHIFT); @@ -227,6 +231,7 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) { u32 val = 0; + val |= qid & DB_CQ_RING_ID_MASK; val |= ((qid & DB_CQ_RING_ID_EXT_MASK) << DB_CQ_RING_ID_EXT_MASK_SHIFT); @@ -488,7 +493,6 @@ static void populate_be_v2_stats(struct be_adapter *adapter) static void populate_lancer_stats(struct be_adapter *adapter) { - struct be_drv_stats *drvs = &adapter->drv_stats; struct lancer_pport_stats *pport_stats = pport_stats_from_cmd(adapter); @@ -588,6 +592,7 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, for_all_rx_queues(adapter, rxo, i) { const struct be_rx_stats *rx_stats = rx_stats(rxo); + do { start = u64_stats_fetch_begin_irq(&rx_stats->sync); pkts = rx_stats(rxo)->rx_pkts; @@ -602,6 +607,7 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, for_all_tx_queues(adapter, txo, i) { const struct be_tx_stats *tx_stats = tx_stats(txo); + do { start = u64_stats_fetch_begin_irq(&tx_stats->sync); pkts = tx_stats(txo)->tx_pkts; @@ -738,38 +744,37 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, memset(hdr, 0, sizeof(*hdr)); - AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1); + SET_TX_WRB_HDR_BITS(crc, hdr, 1); if (skb_is_gso(skb)) { - AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1); - AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss, - hdr, skb_shinfo(skb)->gso_size); + SET_TX_WRB_HDR_BITS(lso, hdr, 1); + SET_TX_WRB_HDR_BITS(lso_mss, hdr, skb_shinfo(skb)->gso_size); if (skb_is_gso_v6(skb) && !lancer_chip(adapter)) - AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1); + SET_TX_WRB_HDR_BITS(lso6, hdr, 1); } else if (skb->ip_summed == CHECKSUM_PARTIAL) { if (skb->encapsulation) { - AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1); + SET_TX_WRB_HDR_BITS(ipcs, hdr, 1); proto = skb_inner_ip_proto(skb); } else { proto = skb_ip_proto(skb); } if (proto == IPPROTO_TCP) - AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); + SET_TX_WRB_HDR_BITS(tcpcs, hdr, 1); else if (proto == IPPROTO_UDP) - AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1); + SET_TX_WRB_HDR_BITS(udpcs, hdr, 1); } if (vlan_tx_tag_present(skb)) { - AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); + SET_TX_WRB_HDR_BITS(vlan, hdr, 1); vlan_tag = be_get_tx_vlan_tag(adapter, skb); - AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag); + SET_TX_WRB_HDR_BITS(vlan_tag, hdr, vlan_tag); } /* To skip HW VLAN tagging: evt = 1, compl = 0 */ - AMAP_SET_BITS(struct amap_eth_hdr_wrb, complete, hdr, !skip_hw_vlan); - AMAP_SET_BITS(struct amap_eth_hdr_wrb, event, hdr, 1); - AMAP_SET_BITS(struct amap_eth_hdr_wrb, num_wrb, hdr, wrb_cnt); - AMAP_SET_BITS(struct amap_eth_hdr_wrb, len, hdr, len); + SET_TX_WRB_HDR_BITS(complete, hdr, !skip_hw_vlan); + SET_TX_WRB_HDR_BITS(event, hdr, 1); + SET_TX_WRB_HDR_BITS(num_wrb, hdr, wrb_cnt); + SET_TX_WRB_HDR_BITS(len, hdr, len); } static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb, @@ -808,6 +813,7 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, if (skb->len > skb->data_len) { int len = skb_headlen(skb); + busaddr = dma_map_single(dev, skb->data, len, DMA_TO_DEVICE); if (dma_mapping_error(dev, busaddr)) goto dma_err; @@ -821,6 +827,7 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + busaddr = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); if (dma_mapping_error(dev, busaddr)) @@ -850,6 +857,7 @@ dma_err: unmap_tx_frag(dev, wrb, map_single); map_single = false; copied -= wrb->frag_len; + adapter->drv_stats.dma_map_errors++; queue_head_inc(txq); } return 0; @@ -910,7 +918,7 @@ static bool be_ipv6_exthdr_check(struct sk_buff *skb) if (ip6h->nexthdr != NEXTHDR_TCP && ip6h->nexthdr != NEXTHDR_UDP) { struct ipv6_opt_hdr *ehdr = - (struct ipv6_opt_hdr *) (skb->data + offset); + (struct ipv6_opt_hdr *)(skb->data + offset); /* offending pkt: 2nd byte following IPv6 hdr is 0xff */ if (ehdr->hdrlen == 0xff) @@ -974,8 +982,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter, * skip HW tagging is not enabled by FW. */ if (unlikely(be_ipv6_tx_stall_chk(adapter, skb) && - (adapter->pvid || adapter->qnq_vid) && - !qnq_async_evt_rcvd(adapter))) + (adapter->pvid || adapter->qnq_vid) && + !qnq_async_evt_rcvd(adapter))) goto tx_drop; /* Manual VLAN tag insertion to prevent: @@ -1073,15 +1081,15 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) static int be_change_mtu(struct net_device *netdev, int new_mtu) { struct be_adapter *adapter = netdev_priv(netdev); - if (new_mtu < BE_MIN_MTU || - new_mtu > (BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN))) { - dev_info(&adapter->pdev->dev, - "MTU must be between %d and %d bytes\n", - BE_MIN_MTU, - (BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN))); + struct device *dev = &adapter->pdev->dev; + + if (new_mtu < BE_MIN_MTU || new_mtu > BE_MAX_MTU) { + dev_info(dev, "MTU must be between %d and %d bytes\n", + BE_MIN_MTU, BE_MAX_MTU); return -EINVAL; } - dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", + + dev_info(dev, "MTU changed from %d to %d bytes\n", netdev->mtu, new_mtu); netdev->mtu = new_mtu; return 0; @@ -1093,6 +1101,7 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) */ static int be_vid_config(struct be_adapter *adapter) { + struct device *dev = &adapter->pdev->dev; u16 vids[BE_NUM_VLANS_SUPPORTED]; u16 num = 0, i = 0; int status = 0; @@ -1114,16 +1123,15 @@ static int be_vid_config(struct be_adapter *adapter) if (addl_status(status) == MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES) goto set_vlan_promisc; - dev_err(&adapter->pdev->dev, - "Setting HW VLAN filtering failed.\n"); + dev_err(dev, "Setting HW VLAN filtering failed\n"); } else { if (adapter->flags & BE_FLAGS_VLAN_PROMISC) { /* hw VLAN filtering re-enabled. */ status = be_cmd_rx_filter(adapter, BE_FLAGS_VLAN_PROMISC, OFF); if (!status) { - dev_info(&adapter->pdev->dev, - "Disabling VLAN Promiscuous mode.\n"); + dev_info(dev, + "Disabling VLAN Promiscuous mode\n"); adapter->flags &= ~BE_FLAGS_VLAN_PROMISC; } } @@ -1137,11 +1145,10 @@ set_vlan_promisc: status = be_cmd_rx_filter(adapter, BE_FLAGS_VLAN_PROMISC, ON); if (!status) { - dev_info(&adapter->pdev->dev, "Enable VLAN Promiscuous mode\n"); + dev_info(dev, "Enable VLAN Promiscuous mode\n"); adapter->flags |= BE_FLAGS_VLAN_PROMISC; } else - dev_err(&adapter->pdev->dev, - "Failed to enable VLAN Promiscuous mode.\n"); + dev_err(dev, "Failed to enable VLAN Promiscuous mode\n"); return status; } @@ -1417,6 +1424,7 @@ err: max_tx_rate, vf); return be_cmd_status(status); } + static int be_set_vf_link_state(struct net_device *netdev, int vf, int link_state) { @@ -1482,7 +1490,6 @@ static void be_eqd_update(struct be_adapter *adapter) tx_pkts = txo->stats.tx_reqs; } while (u64_stats_fetch_retry_irq(&txo->stats.sync, start)); - /* Skip, if wrapped around or first calculation */ now = jiffies; if (!aic->jiffies || time_before(now, aic->jiffies) || @@ -1683,7 +1690,7 @@ static void be_rx_compl_process(struct be_rx_obj *rxo, struct napi_struct *napi, if (netdev->features & NETIF_F_RXHASH) skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3); - skb->encapsulation = rxcp->tunneled; + skb->csum_level = rxcp->tunneled; skb_mark_napi_id(skb, napi); if (rxcp->vlanf) @@ -1741,7 +1748,7 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo, if (adapter->netdev->features & NETIF_F_RXHASH) skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3); - skb->encapsulation = rxcp->tunneled; + skb->csum_level = rxcp->tunneled; skb_mark_napi_id(skb, napi); if (rxcp->vlanf) @@ -1753,65 +1760,46 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo, static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl, struct be_rx_compl_info *rxcp) { - rxcp->pkt_size = - AMAP_GET_BITS(struct amap_eth_rx_compl_v1, pktsize, compl); - rxcp->vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtp, compl); - rxcp->err = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, err, compl); - rxcp->tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, tcpf, compl); - rxcp->udpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, udpf, compl); - rxcp->ip_csum = - AMAP_GET_BITS(struct amap_eth_rx_compl_v1, ipcksm, compl); - rxcp->l4_csum = - AMAP_GET_BITS(struct amap_eth_rx_compl_v1, l4_cksm, compl); - rxcp->ipv6 = - AMAP_GET_BITS(struct amap_eth_rx_compl_v1, ip_version, compl); - rxcp->num_rcvd = - AMAP_GET_BITS(struct amap_eth_rx_compl_v1, numfrags, compl); - rxcp->pkt_type = - AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl); - rxcp->rss_hash = - AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, compl); + rxcp->pkt_size = GET_RX_COMPL_V1_BITS(pktsize, compl); + rxcp->vlanf = GET_RX_COMPL_V1_BITS(vtp, compl); + rxcp->err = GET_RX_COMPL_V1_BITS(err, compl); + rxcp->tcpf = GET_RX_COMPL_V1_BITS(tcpf, compl); + rxcp->udpf = GET_RX_COMPL_V1_BITS(udpf, compl); + rxcp->ip_csum = GET_RX_COMPL_V1_BITS(ipcksm, compl); + rxcp->l4_csum = GET_RX_COMPL_V1_BITS(l4_cksm, compl); + rxcp->ipv6 = GET_RX_COMPL_V1_BITS(ip_version, compl); + rxcp->num_rcvd = GET_RX_COMPL_V1_BITS(numfrags, compl); + rxcp->pkt_type = GET_RX_COMPL_V1_BITS(cast_enc, compl); + rxcp->rss_hash = GET_RX_COMPL_V1_BITS(rsshash, compl); if (rxcp->vlanf) { - rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, qnq, - compl); - rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, - vlan_tag, compl); + rxcp->qnq = GET_RX_COMPL_V1_BITS(qnq, compl); + rxcp->vlan_tag = GET_RX_COMPL_V1_BITS(vlan_tag, compl); } - rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, port, compl); + rxcp->port = GET_RX_COMPL_V1_BITS(port, compl); rxcp->tunneled = - AMAP_GET_BITS(struct amap_eth_rx_compl_v1, tunneled, compl); + GET_RX_COMPL_V1_BITS(tunneled, compl); } static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl, struct be_rx_compl_info *rxcp) { - rxcp->pkt_size = - AMAP_GET_BITS(struct amap_eth_rx_compl_v0, pktsize, compl); - rxcp->vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtp, compl); - rxcp->err = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, err, compl); - rxcp->tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, tcpf, compl); - rxcp->udpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, udpf, compl); - rxcp->ip_csum = - AMAP_GET_BITS(struct amap_eth_rx_compl_v0, ipcksm, compl); - rxcp->l4_csum = - AMAP_GET_BITS(struct amap_eth_rx_compl_v0, l4_cksm, compl); - rxcp->ipv6 = - AMAP_GET_BITS(struct amap_eth_rx_compl_v0, ip_version, compl); - rxcp->num_rcvd = - AMAP_GET_BITS(struct amap_eth_rx_compl_v0, numfrags, compl); - rxcp->pkt_type = - AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl); - rxcp->rss_hash = - AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, compl); + rxcp->pkt_size = GET_RX_COMPL_V0_BITS(pktsize, compl); + rxcp->vlanf = GET_RX_COMPL_V0_BITS(vtp, compl); + rxcp->err = GET_RX_COMPL_V0_BITS(err, compl); + rxcp->tcpf = GET_RX_COMPL_V0_BITS(tcpf, compl); + rxcp->udpf = GET_RX_COMPL_V0_BITS(udpf, compl); + rxcp->ip_csum = GET_RX_COMPL_V0_BITS(ipcksm, compl); + rxcp->l4_csum = GET_RX_COMPL_V0_BITS(l4_cksm, compl); + rxcp->ipv6 = GET_RX_COMPL_V0_BITS(ip_version, compl); + rxcp->num_rcvd = GET_RX_COMPL_V0_BITS(numfrags, compl); + rxcp->pkt_type = GET_RX_COMPL_V0_BITS(cast_enc, compl); + rxcp->rss_hash = GET_RX_COMPL_V0_BITS(rsshash, compl); if (rxcp->vlanf) { - rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, qnq, - compl); - rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, - vlan_tag, compl); + rxcp->qnq = GET_RX_COMPL_V0_BITS(qnq, compl); + rxcp->vlan_tag = GET_RX_COMPL_V0_BITS(vlan_tag, compl); } - rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, port, compl); - rxcp->ip_frag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, - ip_frag, compl); + rxcp->port = GET_RX_COMPL_V0_BITS(port, compl); + rxcp->ip_frag = GET_RX_COMPL_V0_BITS(ip_frag, compl); } static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo) @@ -1872,7 +1860,7 @@ static inline struct page *be_alloc_pages(u32 size, gfp_t gfp) * Allocate a page, split it to fragments of size rx_frag_size and post as * receive buffers to BE */ -static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) +static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp, u32 frags_needed) { struct be_adapter *adapter = rxo->adapter; struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; @@ -1881,10 +1869,10 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) struct device *dev = &adapter->pdev->dev; struct be_eth_rx_d *rxd; u64 page_dmaaddr = 0, frag_dmaaddr; - u32 posted, page_offset = 0; + u32 posted, page_offset = 0, notify = 0; page_info = &rxo->page_info_tbl[rxq->head]; - for (posted = 0; posted < MAX_RX_POST && !page_info->page; posted++) { + for (posted = 0; posted < frags_needed && !page_info->page; posted++) { if (!pagep) { pagep = be_alloc_pages(adapter->big_page_size, gfp); if (unlikely(!pagep)) { @@ -1897,7 +1885,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) if (dma_mapping_error(dev, page_dmaaddr)) { put_page(pagep); pagep = NULL; - rx_stats(rxo)->rx_post_fail++; + adapter->drv_stats.dma_map_errors++; break; } page_offset = 0; @@ -1940,7 +1928,11 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp) atomic_add(posted, &rxq->used); if (rxo->rx_post_starved) rxo->rx_post_starved = false; - be_rxq_notify(adapter, rxq->id, posted); + do { + notify = min(256u, posted); + be_rxq_notify(adapter, rxq->id, notify); + posted -= notify; + } while (posted); } else if (atomic_read(&rxq->used) == 0) { /* Let be_worker replenish when memory is available */ rxo->rx_post_starved = true; @@ -1991,7 +1983,7 @@ static u16 be_tx_compl_process(struct be_adapter *adapter, queue_tail_inc(txq); } while (cur_index != last_index); - dev_kfree_skb_any(sent_skb); + dev_consume_skb_any(sent_skb); return num_wrbs; } @@ -2069,7 +2061,8 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) memset(page_info, 0, sizeof(*page_info)); } BUG_ON(atomic_read(&rxq->used)); - rxq->tail = rxq->head = 0; + rxq->tail = 0; + rxq->head = 0; } static void be_tx_compl_clean(struct be_adapter *adapter) @@ -2091,9 +2084,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter) num_wrbs = 0; txq = &txo->q; while ((txcp = be_tx_compl_get(&txo->cq))) { - end_idx = - AMAP_GET_BITS(struct amap_eth_tx_compl, - wrb_index, txcp); + end_idx = GET_TX_COMPL_BITS(wrb_index, txcp); num_wrbs += be_tx_compl_process(adapter, txo, end_idx); cmpl++; @@ -2164,7 +2155,6 @@ static int be_evt_queues_create(struct be_adapter *adapter) napi_hash_add(&eqo->napi); aic = &adapter->aic_obj[i]; eqo->adapter = adapter; - eqo->tx_budget = BE_TX_BUDGET; eqo->idx = i; aic->max_eqd = BE_MAX_EQD; aic->enable = true; @@ -2394,6 +2384,7 @@ static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi, struct be_queue_info *rx_cq = &rxo->cq; struct be_rx_compl_info *rxcp; u32 work_done; + u32 frags_consumed = 0; for (work_done = 0; work_done < budget; work_done++) { rxcp = be_rx_compl_get(rxo); @@ -2426,6 +2417,7 @@ static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi, be_rx_compl_process(rxo, napi, rxcp); loop_continue: + frags_consumed += rxcp->num_rcvd; be_rx_stats_update(rxo, rxcp); } @@ -2437,26 +2429,71 @@ loop_continue: */ if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM && !rxo->rx_post_starved) - be_post_rx_frags(rxo, GFP_ATOMIC); + be_post_rx_frags(rxo, GFP_ATOMIC, + max_t(u32, MAX_RX_POST, + frags_consumed)); } return work_done; } -static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, - int budget, int idx) +static inline void be_update_tx_err(struct be_tx_obj *txo, u32 status) +{ + switch (status) { + case BE_TX_COMP_HDR_PARSE_ERR: + tx_stats(txo)->tx_hdr_parse_err++; + break; + case BE_TX_COMP_NDMA_ERR: + tx_stats(txo)->tx_dma_err++; + break; + case BE_TX_COMP_ACL_ERR: + tx_stats(txo)->tx_spoof_check_err++; + break; + } +} + +static inline void lancer_update_tx_err(struct be_tx_obj *txo, u32 status) +{ + switch (status) { + case LANCER_TX_COMP_LSO_ERR: + tx_stats(txo)->tx_tso_err++; + break; + case LANCER_TX_COMP_HSW_DROP_MAC_ERR: + case LANCER_TX_COMP_HSW_DROP_VLAN_ERR: + tx_stats(txo)->tx_spoof_check_err++; + break; + case LANCER_TX_COMP_QINQ_ERR: + tx_stats(txo)->tx_qinq_err++; + break; + case LANCER_TX_COMP_PARITY_ERR: + tx_stats(txo)->tx_internal_parity_err++; + break; + case LANCER_TX_COMP_DMA_ERR: + tx_stats(txo)->tx_dma_err++; + break; + } +} + +static void be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, + int idx) { struct be_eth_tx_compl *txcp; - int num_wrbs = 0, work_done; + int num_wrbs = 0, work_done = 0; + u32 compl_status; + u16 last_idx; - for (work_done = 0; work_done < budget; work_done++) { - txcp = be_tx_compl_get(&txo->cq); - if (!txcp) - break; - num_wrbs += be_tx_compl_process(adapter, txo, - AMAP_GET_BITS(struct - amap_eth_tx_compl, - wrb_index, txcp)); + while ((txcp = be_tx_compl_get(&txo->cq))) { + last_idx = GET_TX_COMPL_BITS(wrb_index, txcp); + num_wrbs += be_tx_compl_process(adapter, txo, last_idx); + work_done++; + + compl_status = GET_TX_COMPL_BITS(status, txcp); + if (compl_status) { + if (lancer_chip(adapter)) + lancer_update_tx_err(txo, compl_status); + else + be_update_tx_err(txo, compl_status); + } } if (work_done) { @@ -2474,7 +2511,6 @@ static bool be_process_tx(struct be_adapter *adapter, struct be_tx_obj *txo, tx_stats(txo)->tx_compl += work_done; u64_stats_update_end(&tx_stats(txo)->sync_compl); } - return (work_done < budget); /* Done */ } int be_poll(struct napi_struct *napi, int budget) @@ -2483,17 +2519,12 @@ int be_poll(struct napi_struct *napi, int budget) struct be_adapter *adapter = eqo->adapter; int max_work = 0, work, i, num_evts; struct be_rx_obj *rxo; - bool tx_done; + struct be_tx_obj *txo; num_evts = events_get(eqo); - /* Process all TXQs serviced by this EQ */ - for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) { - tx_done = be_process_tx(adapter, &adapter->tx_obj[i], - eqo->tx_budget, i); - if (!tx_done) - max_work = budget; - } + for_all_tx_queues_on_eq(adapter, eqo, txo, i) + be_process_tx(adapter, txo, i); if (be_lock_napi(eqo)) { /* This loop will iterate twice for EQ0 in which @@ -2882,7 +2913,7 @@ static int be_rx_qs_create(struct be_adapter *adapter) /* First time posting */ for_all_rx_queues(adapter, rxo, i) - be_post_rx_frags(rxo, GFP_KERNEL); + be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST); return 0; } @@ -3309,10 +3340,20 @@ static void BEx_get_resources(struct be_adapter *adapter, */ if (BE2_chip(adapter) || use_sriov || (adapter->port_num > 1) || !be_physfn(adapter) || (be_is_mc(adapter) && - !(adapter->function_caps & BE_FUNCTION_CAPS_RSS))) + !(adapter->function_caps & BE_FUNCTION_CAPS_RSS))) { res->max_tx_qs = 1; - else + } else if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) { + struct be_resources super_nic_res = {0}; + + /* On a SuperNIC profile, the driver needs to use the + * GET_PROFILE_CONFIG cmd to query the per-function TXQ limits + */ + be_cmd_get_profile_config(adapter, &super_nic_res, 0); + /* Some old versions of BE3 FW don't report max_tx_qs value */ + res->max_tx_qs = super_nic_res.max_tx_qs ? : BE3_MAX_TX_QS; + } else { res->max_tx_qs = BE3_MAX_TX_QS; + } if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && !use_sriov && be_physfn(adapter)) @@ -3362,7 +3403,7 @@ static int be_get_sriov_config(struct be_adapter *adapter) if (!be_max_vfs(adapter)) { if (num_vfs) - dev_warn(dev, "device doesn't support SRIOV\n"); + dev_warn(dev, "SRIOV is disabled. Ignoring num_vfs\n"); adapter->num_vfs = 0; return 0; } @@ -3413,16 +3454,16 @@ static int be_get_resources(struct be_adapter *adapter) if (be_roce_supported(adapter)) res.max_evt_qs /= 2; adapter->res = res; - - dev_info(dev, "Max: txqs %d, rxqs %d, rss %d, eqs %d, vfs %d\n", - be_max_txqs(adapter), be_max_rxqs(adapter), - be_max_rss(adapter), be_max_eqs(adapter), - be_max_vfs(adapter)); - dev_info(dev, "Max: uc-macs %d, mc-macs %d, vlans %d\n", - be_max_uc(adapter), be_max_mc(adapter), - be_max_vlans(adapter)); } + dev_info(dev, "Max: txqs %d, rxqs %d, rss %d, eqs %d, vfs %d\n", + be_max_txqs(adapter), be_max_rxqs(adapter), + be_max_rss(adapter), be_max_eqs(adapter), + be_max_vfs(adapter)); + dev_info(dev, "Max: uc-macs %d, mc-macs %d, vlans %d\n", + be_max_uc(adapter), be_max_mc(adapter), + be_max_vlans(adapter)); + return 0; } @@ -3633,9 +3674,10 @@ static int be_setup(struct be_adapter *adapter) goto err; be_cmd_get_fw_ver(adapter); + dev_info(dev, "FW version is %s\n", adapter->fw_ver); if (BE2_chip(adapter) && fw_major_num(adapter->fw_ver) < 4) { - dev_err(dev, "Firmware on card is old(%s), IRQs may not work.", + dev_err(dev, "Firmware on card is old(%s), IRQs may not work", adapter->fw_ver); dev_err(dev, "Please upgrade firmware to version >= 4.0\n"); } @@ -3683,8 +3725,6 @@ static void be_netpoll(struct net_device *netdev) be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); napi_schedule(&eqo->napi); } - - return; } #endif @@ -4052,6 +4092,7 @@ static int lancer_fw_download(struct be_adapter *adapter, { #define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024) #define LANCER_FW_DOWNLOAD_LOCATION "/prg" + struct device *dev = &adapter->pdev->dev; struct be_dma_mem flash_cmd; const u8 *data_ptr = NULL; u8 *dest_image_ptr = NULL; @@ -4064,21 +4105,16 @@ static int lancer_fw_download(struct be_adapter *adapter, u8 change_status; if (!IS_ALIGNED(fw->size, sizeof(u32))) { - dev_err(&adapter->pdev->dev, - "FW Image not properly aligned. " - "Length must be 4 byte aligned.\n"); - status = -EINVAL; - goto lancer_fw_exit; + dev_err(dev, "FW image size should be multiple of 4\n"); + return -EINVAL; } flash_cmd.size = sizeof(struct lancer_cmd_req_write_object) + LANCER_FW_DOWNLOAD_CHUNK; - flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, + flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma, GFP_KERNEL); - if (!flash_cmd.va) { - status = -ENOMEM; - goto lancer_fw_exit; - } + if (!flash_cmd.va) + return -ENOMEM; dest_image_ptr = flash_cmd.va + sizeof(struct lancer_cmd_req_write_object); @@ -4113,35 +4149,27 @@ static int lancer_fw_download(struct be_adapter *adapter, &add_status); } - dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, - flash_cmd.dma); + dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); if (status) { - dev_err(&adapter->pdev->dev, - "Firmware load error. " - "Status code: 0x%x Additional Status: 0x%x\n", - status, add_status); - goto lancer_fw_exit; + dev_err(dev, "Firmware load error\n"); + return be_cmd_status(status); } + dev_info(dev, "Firmware flashed successfully\n"); + if (change_status == LANCER_FW_RESET_NEEDED) { - dev_info(&adapter->pdev->dev, - "Resetting adapter to activate new FW\n"); + dev_info(dev, "Resetting adapter to activate new FW\n"); status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK); if (status) { - dev_err(&adapter->pdev->dev, - "Adapter busy for FW reset.\n" - "New FW will not be active.\n"); - goto lancer_fw_exit; + dev_err(dev, "Adapter busy, could not reset FW\n"); + dev_err(dev, "Reboot server to activate new FW\n"); } } else if (change_status != LANCER_NO_RESET_NEEDED) { - dev_err(&adapter->pdev->dev, - "System reboot required for new FW to be active\n"); + dev_info(dev, "Reboot server to activate new FW\n"); } - dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); -lancer_fw_exit: - return status; + return 0; } #define UFI_TYPE2 2 @@ -4374,7 +4402,6 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family, return; err: be_disable_vxlan_offloads(adapter); - return; } static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family, @@ -4506,6 +4533,7 @@ static int be_map_pci_bars(struct be_adapter *adapter) return 0; pci_map_err: + dev_err(&adapter->pdev->dev, "Error in mapping PCI BARs\n"); be_unmap_pci_bars(adapter); return -ENOMEM; } @@ -4713,7 +4741,6 @@ static void be_func_recovery_task(struct work_struct *work) be_detect_error(adapter); if (adapter->hw_error && lancer_chip(adapter)) { - rtnl_lock(); netif_device_detach(adapter->netdev); rtnl_unlock(); @@ -4750,7 +4777,7 @@ static void be_worker(struct work_struct *work) if (!adapter->stats_cmd_sent) { if (lancer_chip(adapter)) lancer_cmd_get_pport_stats(adapter, - &adapter->stats_cmd); + &adapter->stats_cmd); else be_cmd_get_stats(adapter, &adapter->stats_cmd); } @@ -4764,7 +4791,7 @@ static void be_worker(struct work_struct *work) * allocation failures. */ if (rxo->rx_post_starved) - be_post_rx_frags(rxo, GFP_KERNEL); + be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST); } be_eqd_update(adapter); @@ -4822,6 +4849,8 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) struct net_device *netdev; char port_name; + dev_info(&pdev->dev, "%s version is %s\n", DRV_NAME, DRV_VER); + status = pci_enable_device(pdev); if (status) goto do_none; @@ -4853,11 +4882,9 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) } } - if (be_physfn(adapter)) { - status = pci_enable_pcie_error_reporting(pdev); - if (!status) - dev_info(&pdev->dev, "PCIe error reporting enabled\n"); - } + status = pci_enable_pcie_error_reporting(pdev); + if (!status) + dev_info(&pdev->dev, "PCIe error reporting enabled\n"); status = be_ctrl_init(adapter); if (status) @@ -4897,7 +4924,8 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) INIT_DELAYED_WORK(&adapter->work, be_worker); INIT_DELAYED_WORK(&adapter->func_recovery_work, be_func_recovery_task); - adapter->rx_fc = adapter->tx_fc = true; + adapter->rx_fc = true; + adapter->tx_fc = true; status = be_setup(adapter); if (status) |