aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/emulex/benet/be_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/emulex/benet/be_main.c')
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c368
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 93ff8ef39352..9a18e7930b31 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)