aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSunil Goutham <sgoutham@cavium.com>2016-11-15 07:08:29 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-16 13:28:33 -0500
commitc94acf805d93e7beb5898ac97ff327ae0b6f04dd (patch)
tree163999dc96988c0b9b03c7227df37c79c9ed6ac6 /drivers/net
parent964cb69bdc9db255f7c3a80f6e1bed8a25e4c60e (diff)
net: thunderx: Fix memory leak and other issues upon interface toggle
This patch fixes the following 1. When interface is being teardown and queues are being cleaned up, free pending SKBs that are in SQ which are either not transmitted or freed as NAPI is disabled by that time. 2. While interface initialization, delay CFG_DONE notification till the end to avoid corner cases where TXQs are enabled but CQ interrupts are not which results blocking transmission and kicking off watchdog. 3. Check for IFF_UP while re-enabling RBDR interrupts from tasklet. Signed-off-by: Sunil Goutham <sgoutham@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c11
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.c14
2 files changed, 18 insertions, 7 deletions
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 9dc79c0578d8..8a37012c9c89 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -473,9 +473,6 @@ int nicvf_set_real_num_queues(struct net_device *netdev,
473static int nicvf_init_resources(struct nicvf *nic) 473static int nicvf_init_resources(struct nicvf *nic)
474{ 474{
475 int err; 475 int err;
476 union nic_mbx mbx = {};
477
478 mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
479 476
480 /* Enable Qset */ 477 /* Enable Qset */
481 nicvf_qset_config(nic, true); 478 nicvf_qset_config(nic, true);
@@ -488,9 +485,6 @@ static int nicvf_init_resources(struct nicvf *nic)
488 return err; 485 return err;
489 } 486 }
490 487
491 /* Send VF config done msg to PF */
492 nicvf_write_to_mbx(nic, &mbx);
493
494 return 0; 488 return 0;
495} 489}
496 490
@@ -1184,6 +1178,7 @@ int nicvf_open(struct net_device *netdev)
1184 struct nicvf *nic = netdev_priv(netdev); 1178 struct nicvf *nic = netdev_priv(netdev);
1185 struct queue_set *qs = nic->qs; 1179 struct queue_set *qs = nic->qs;
1186 struct nicvf_cq_poll *cq_poll = NULL; 1180 struct nicvf_cq_poll *cq_poll = NULL;
1181 union nic_mbx mbx = {};
1187 1182
1188 netif_carrier_off(netdev); 1183 netif_carrier_off(netdev);
1189 1184
@@ -1271,6 +1266,10 @@ int nicvf_open(struct net_device *netdev)
1271 for (qidx = 0; qidx < qs->rbdr_cnt; qidx++) 1266 for (qidx = 0; qidx < qs->rbdr_cnt; qidx++)
1272 nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx); 1267 nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
1273 1268
1269 /* Send VF config done msg to PF */
1270 mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
1271 nicvf_write_to_mbx(nic, &mbx);
1272
1274 return 0; 1273 return 0;
1275cleanup: 1274cleanup:
1276 nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0); 1275 nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index bdce5915baae..747ef0882976 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -271,7 +271,8 @@ refill:
271 rbdr_idx, new_rb); 271 rbdr_idx, new_rb);
272next_rbdr: 272next_rbdr:
273 /* Re-enable RBDR interrupts only if buffer allocation is success */ 273 /* Re-enable RBDR interrupts only if buffer allocation is success */
274 if (!nic->rb_alloc_fail && rbdr->enable) 274 if (!nic->rb_alloc_fail && rbdr->enable &&
275 netif_running(nic->pnicvf->netdev))
275 nicvf_enable_intr(nic, NICVF_INTR_RBDR, rbdr_idx); 276 nicvf_enable_intr(nic, NICVF_INTR_RBDR, rbdr_idx);
276 277
277 if (rbdr_idx) 278 if (rbdr_idx)
@@ -362,6 +363,8 @@ static int nicvf_init_snd_queue(struct nicvf *nic,
362 363
363static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq) 364static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)
364{ 365{
366 struct sk_buff *skb;
367
365 if (!sq) 368 if (!sq)
366 return; 369 return;
367 if (!sq->dmem.base) 370 if (!sq->dmem.base)
@@ -372,6 +375,15 @@ static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)
372 sq->dmem.q_len * TSO_HEADER_SIZE, 375 sq->dmem.q_len * TSO_HEADER_SIZE,
373 sq->tso_hdrs, sq->tso_hdrs_phys); 376 sq->tso_hdrs, sq->tso_hdrs_phys);
374 377
378 /* Free pending skbs in the queue */
379 smp_rmb();
380 while (sq->head != sq->tail) {
381 skb = (struct sk_buff *)sq->skbuff[sq->head];
382 if (skb)
383 dev_kfree_skb_any(skb);
384 sq->head++;
385 sq->head &= (sq->dmem.q_len - 1);
386 }
375 kfree(sq->skbuff); 387 kfree(sq->skbuff);
376 nicvf_free_q_desc_mem(nic, &sq->dmem); 388 nicvf_free_q_desc_mem(nic, &sq->dmem);
377} 389}