Skip to content

Commit f68b123

Browse files
committed
Merge branch 'thunderx-fixes'
Aleksey Makarov says: ==================== net: thunderx: Misc fixes Miscellaneous fixes for the ThunderX VNIC driver All the patches can be applied individually. It's ok to drop some if the maintainer feels uncomfortable with applying for 4.2. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents c8507fb + 60f83c8 commit f68b123

File tree

6 files changed

+92
-37
lines changed

6 files changed

+92
-37
lines changed

drivers/net/ethernet/cavium/thunder/nic.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,15 @@
125125
*/
126126
#define NICPF_CLK_PER_INT_TICK 2
127127

128+
/* Time to wait before we decide that a SQ is stuck.
129+
*
130+
* Since both pkt rx and tx notifications are done with same CQ,
131+
* when packets are being received at very high rate (eg: L2 forwarding)
132+
* then freeing transmitted skbs will be delayed and watchdog
133+
* will kick in, resetting interface. Hence keeping this value high.
134+
*/
135+
#define NICVF_TX_TIMEOUT (50 * HZ)
136+
128137
struct nicvf_cq_poll {
129138
u8 cq_idx; /* Completion queue index */
130139
struct napi_struct napi;
@@ -216,8 +225,9 @@ struct nicvf_drv_stats {
216225
/* Tx */
217226
u64 tx_frames_ok;
218227
u64 tx_drops;
219-
u64 tx_busy;
220228
u64 tx_tso;
229+
u64 txq_stop;
230+
u64 txq_wake;
221231
};
222232

223233
struct nicvf {

drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ static const struct nicvf_stat nicvf_drv_stats[] = {
6666
NICVF_DRV_STAT(rx_frames_jumbo),
6767
NICVF_DRV_STAT(rx_drops),
6868
NICVF_DRV_STAT(tx_frames_ok),
69-
NICVF_DRV_STAT(tx_busy),
7069
NICVF_DRV_STAT(tx_tso),
7170
NICVF_DRV_STAT(tx_drops),
71+
NICVF_DRV_STAT(txq_stop),
72+
NICVF_DRV_STAT(txq_wake),
7273
};
7374

7475
static const struct nicvf_stat nicvf_queue_stats[] = {
@@ -126,6 +127,7 @@ static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl)
126127

127128
static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
128129
{
130+
struct nicvf *nic = netdev_priv(netdev);
129131
int stats, qidx;
130132

131133
if (sset != ETH_SS_STATS)
@@ -141,15 +143,15 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
141143
data += ETH_GSTRING_LEN;
142144
}
143145

144-
for (qidx = 0; qidx < MAX_RCV_QUEUES_PER_QS; qidx++) {
146+
for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
145147
for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
146148
sprintf(data, "rxq%d: %s", qidx,
147149
nicvf_queue_stats[stats].name);
148150
data += ETH_GSTRING_LEN;
149151
}
150152
}
151153

152-
for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) {
154+
for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
153155
for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
154156
sprintf(data, "txq%d: %s", qidx,
155157
nicvf_queue_stats[stats].name);
@@ -170,12 +172,14 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
170172

171173
static int nicvf_get_sset_count(struct net_device *netdev, int sset)
172174
{
175+
struct nicvf *nic = netdev_priv(netdev);
176+
173177
if (sset != ETH_SS_STATS)
174178
return -EINVAL;
175179

176180
return nicvf_n_hw_stats + nicvf_n_drv_stats +
177181
(nicvf_n_queue_stats *
178-
(MAX_RCV_QUEUES_PER_QS + MAX_SND_QUEUES_PER_QS)) +
182+
(nic->qs->rq_cnt + nic->qs->sq_cnt)) +
179183
BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT;
180184
}
181185

@@ -197,13 +201,13 @@ static void nicvf_get_ethtool_stats(struct net_device *netdev,
197201
*(data++) = ((u64 *)&nic->drv_stats)
198202
[nicvf_drv_stats[stat].index];
199203

200-
for (qidx = 0; qidx < MAX_RCV_QUEUES_PER_QS; qidx++) {
204+
for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
201205
for (stat = 0; stat < nicvf_n_queue_stats; stat++)
202206
*(data++) = ((u64 *)&nic->qs->rq[qidx].stats)
203207
[nicvf_queue_stats[stat].index];
204208
}
205209

206-
for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) {
210+
for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
207211
for (stat = 0; stat < nicvf_n_queue_stats; stat++)
208212
*(data++) = ((u64 *)&nic->qs->sq[qidx].stats)
209213
[nicvf_queue_stats[stat].index];
@@ -543,6 +547,7 @@ static int nicvf_set_channels(struct net_device *dev,
543547
{
544548
struct nicvf *nic = netdev_priv(dev);
545549
int err = 0;
550+
bool if_up = netif_running(dev);
546551

547552
if (!channel->rx_count || !channel->tx_count)
548553
return -EINVAL;
@@ -551,6 +556,9 @@ static int nicvf_set_channels(struct net_device *dev,
551556
if (channel->tx_count > MAX_SND_QUEUES_PER_QS)
552557
return -EINVAL;
553558

559+
if (if_up)
560+
nicvf_stop(dev);
561+
554562
nic->qs->rq_cnt = channel->rx_count;
555563
nic->qs->sq_cnt = channel->tx_count;
556564
nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
@@ -559,11 +567,9 @@ static int nicvf_set_channels(struct net_device *dev,
559567
if (err)
560568
return err;
561569

562-
if (!netif_running(dev))
563-
return err;
570+
if (if_up)
571+
nicvf_open(dev);
564572

565-
nicvf_stop(dev);
566-
nicvf_open(dev);
567573
netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
568574
nic->qs->sq_cnt, nic->qs->rq_cnt);
569575

drivers/net/ethernet/cavium/thunder/nicvf_main.c

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic)
234234
nic->duplex == DUPLEX_FULL ?
235235
"Full duplex" : "Half duplex");
236236
netif_carrier_on(nic->netdev);
237-
netif_tx_wake_all_queues(nic->netdev);
237+
netif_tx_start_all_queues(nic->netdev);
238238
} else {
239239
netdev_info(nic->netdev, "%s: Link is Down\n",
240240
nic->netdev->name);
@@ -425,6 +425,7 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
425425
if (skb) {
426426
prefetch(skb);
427427
dev_consume_skb_any(skb);
428+
sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
428429
}
429430
}
430431

@@ -476,12 +477,13 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
476477
static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
477478
struct napi_struct *napi, int budget)
478479
{
479-
int processed_cqe, work_done = 0;
480+
int processed_cqe, work_done = 0, tx_done = 0;
480481
int cqe_count, cqe_head;
481482
struct nicvf *nic = netdev_priv(netdev);
482483
struct queue_set *qs = nic->qs;
483484
struct cmp_queue *cq = &qs->cq[cq_idx];
484485
struct cqe_rx_t *cq_desc;
486+
struct netdev_queue *txq;
485487

486488
spin_lock_bh(&cq->lock);
487489
loop:
@@ -496,8 +498,8 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
496498
cqe_head = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, cq_idx) >> 9;
497499
cqe_head &= 0xFFFF;
498500

499-
netdev_dbg(nic->netdev, "%s cqe_count %d cqe_head %d\n",
500-
__func__, cqe_count, cqe_head);
501+
netdev_dbg(nic->netdev, "%s CQ%d cqe_count %d cqe_head %d\n",
502+
__func__, cq_idx, cqe_count, cqe_head);
501503
while (processed_cqe < cqe_count) {
502504
/* Get the CQ descriptor */
503505
cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head);
@@ -511,8 +513,8 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
511513
break;
512514
}
513515

514-
netdev_dbg(nic->netdev, "cq_desc->cqe_type %d\n",
515-
cq_desc->cqe_type);
516+
netdev_dbg(nic->netdev, "CQ%d cq_desc->cqe_type %d\n",
517+
cq_idx, cq_desc->cqe_type);
516518
switch (cq_desc->cqe_type) {
517519
case CQE_TYPE_RX:
518520
nicvf_rcv_pkt_handler(netdev, napi, cq,
@@ -522,6 +524,7 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
522524
case CQE_TYPE_SEND:
523525
nicvf_snd_pkt_handler(netdev, cq,
524526
(void *)cq_desc, CQE_TYPE_SEND);
527+
tx_done++;
525528
break;
526529
case CQE_TYPE_INVALID:
527530
case CQE_TYPE_RX_SPLIT:
@@ -532,8 +535,9 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
532535
}
533536
processed_cqe++;
534537
}
535-
netdev_dbg(nic->netdev, "%s processed_cqe %d work_done %d budget %d\n",
536-
__func__, processed_cqe, work_done, budget);
538+
netdev_dbg(nic->netdev,
539+
"%s CQ%d processed_cqe %d work_done %d budget %d\n",
540+
__func__, cq_idx, processed_cqe, work_done, budget);
537541

538542
/* Ring doorbell to inform H/W to reuse processed CQEs */
539543
nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_DOOR,
@@ -543,6 +547,19 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
543547
goto loop;
544548

545549
done:
550+
/* Wakeup TXQ if its stopped earlier due to SQ full */
551+
if (tx_done) {
552+
txq = netdev_get_tx_queue(netdev, cq_idx);
553+
if (netif_tx_queue_stopped(txq)) {
554+
netif_tx_start_queue(txq);
555+
nic->drv_stats.txq_wake++;
556+
if (netif_msg_tx_err(nic))
557+
netdev_warn(netdev,
558+
"%s: Transmit queue wakeup SQ%d\n",
559+
netdev->name, cq_idx);
560+
}
561+
}
562+
546563
spin_unlock_bh(&cq->lock);
547564
return work_done;
548565
}
@@ -554,15 +571,10 @@ static int nicvf_poll(struct napi_struct *napi, int budget)
554571
struct net_device *netdev = napi->dev;
555572
struct nicvf *nic = netdev_priv(netdev);
556573
struct nicvf_cq_poll *cq;
557-
struct netdev_queue *txq;
558574

559575
cq = container_of(napi, struct nicvf_cq_poll, napi);
560576
work_done = nicvf_cq_intr_handler(netdev, cq->cq_idx, napi, budget);
561577

562-
txq = netdev_get_tx_queue(netdev, cq->cq_idx);
563-
if (netif_tx_queue_stopped(txq))
564-
netif_tx_wake_queue(txq);
565-
566578
if (work_done < budget) {
567579
/* Slow packet rate, exit polling */
568580
napi_complete(napi);
@@ -833,9 +845,9 @@ static netdev_tx_t nicvf_xmit(struct sk_buff *skb, struct net_device *netdev)
833845
return NETDEV_TX_OK;
834846
}
835847

836-
if (!nicvf_sq_append_skb(nic, skb) && !netif_tx_queue_stopped(txq)) {
848+
if (!netif_tx_queue_stopped(txq) && !nicvf_sq_append_skb(nic, skb)) {
837849
netif_tx_stop_queue(txq);
838-
nic->drv_stats.tx_busy++;
850+
nic->drv_stats.txq_stop++;
839851
if (netif_msg_tx_err(nic))
840852
netdev_warn(netdev,
841853
"%s: Transmit ring full, stopping SQ%d\n",
@@ -859,7 +871,6 @@ int nicvf_stop(struct net_device *netdev)
859871
nicvf_send_msg_to_pf(nic, &mbx);
860872

861873
netif_carrier_off(netdev);
862-
netif_tx_disable(netdev);
863874

864875
/* Disable RBDR & QS error interrupts */
865876
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++) {
@@ -894,6 +905,8 @@ int nicvf_stop(struct net_device *netdev)
894905
kfree(cq_poll);
895906
}
896907

908+
netif_tx_disable(netdev);
909+
897910
/* Free resources */
898911
nicvf_config_data_transfer(nic, false);
899912

@@ -988,6 +1001,9 @@ int nicvf_open(struct net_device *netdev)
9881001
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++)
9891002
nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
9901003

1004+
nic->drv_stats.txq_stop = 0;
1005+
nic->drv_stats.txq_wake = 0;
1006+
9911007
netif_carrier_on(netdev);
9921008
netif_tx_start_all_queues(netdev);
9931009

@@ -1278,6 +1294,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
12781294
netdev->hw_features = netdev->features;
12791295

12801296
netdev->netdev_ops = &nicvf_netdev_ops;
1297+
netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
12811298

12821299
INIT_WORK(&nic->reset_task, nicvf_reset_task);
12831300

@@ -1318,11 +1335,17 @@ static void nicvf_remove(struct pci_dev *pdev)
13181335
pci_disable_device(pdev);
13191336
}
13201337

1338+
static void nicvf_shutdown(struct pci_dev *pdev)
1339+
{
1340+
nicvf_remove(pdev);
1341+
}
1342+
13211343
static struct pci_driver nicvf_driver = {
13221344
.name = DRV_NAME,
13231345
.id_table = nicvf_id_table,
13241346
.probe = nicvf_probe,
13251347
.remove = nicvf_remove,
1348+
.shutdown = nicvf_shutdown,
13261349
};
13271350

13281351
static int __init nicvf_init_module(void)

drivers/net/ethernet/cavium/thunder/nicvf_queues.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,11 @@ static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, gfp_t gfp,
103103

104104
/* Allocate a new page */
105105
if (!nic->rb_page) {
106-
nic->rb_page = alloc_pages(gfp | __GFP_COMP, order);
106+
nic->rb_page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN,
107+
order);
107108
if (!nic->rb_page) {
108-
netdev_err(nic->netdev, "Failed to allocate new rcv buffer\n");
109+
netdev_err(nic->netdev,
110+
"Failed to allocate new rcv buffer\n");
109111
return -ENOMEM;
110112
}
111113
nic->rb_page_offset = 0;
@@ -382,7 +384,8 @@ static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)
382384
return;
383385

384386
if (sq->tso_hdrs)
385-
dma_free_coherent(&nic->pdev->dev, sq->dmem.q_len,
387+
dma_free_coherent(&nic->pdev->dev,
388+
sq->dmem.q_len * TSO_HEADER_SIZE,
386389
sq->tso_hdrs, sq->tso_hdrs_phys);
387390

388391
kfree(sq->skbuff);
@@ -863,10 +866,11 @@ void nicvf_sq_free_used_descs(struct net_device *netdev, struct snd_queue *sq,
863866
continue;
864867
}
865868
skb = (struct sk_buff *)sq->skbuff[sq->head];
869+
if (skb)
870+
dev_kfree_skb_any(skb);
866871
atomic64_add(1, (atomic64_t *)&netdev->stats.tx_packets);
867872
atomic64_add(hdr->tot_len,
868873
(atomic64_t *)&netdev->stats.tx_bytes);
869-
dev_kfree_skb_any(skb);
870874
nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1);
871875
}
872876
}
@@ -992,7 +996,7 @@ static inline void nicvf_sq_add_gather_subdesc(struct snd_queue *sq, int qentry,
992996

993997
memset(gather, 0, SND_QUEUE_DESC_SIZE);
994998
gather->subdesc_type = SQ_DESC_TYPE_GATHER;
995-
gather->ld_type = NIC_SEND_LD_TYPE_E_LDWB;
999+
gather->ld_type = NIC_SEND_LD_TYPE_E_LDD;
9961000
gather->size = size;
9971001
gather->addr = data;
9981002
}
@@ -1048,7 +1052,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq,
10481052
}
10491053
nicvf_sq_add_hdr_subdesc(sq, hdr_qentry,
10501054
seg_subdescs - 1, skb, seg_len);
1051-
sq->skbuff[hdr_qentry] = 0;
1055+
sq->skbuff[hdr_qentry] = (u64)NULL;
10521056
qentry = nicvf_get_nxt_sqentry(sq, qentry);
10531057

10541058
desc_cnt += seg_subdescs;
@@ -1062,6 +1066,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq,
10621066
/* Inform HW to xmit all TSO segments */
10631067
nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_DOOR,
10641068
skb_get_queue_mapping(skb), desc_cnt);
1069+
nic->drv_stats.tx_tso++;
10651070
return 1;
10661071
}
10671072

0 commit comments

Comments
 (0)