|
16 | 16 |
|
17 | 17 | #include "ionic.h"
|
18 | 18 | #include "ionic_bus.h"
|
| 19 | +#include "ionic_dev.h" |
19 | 20 | #include "ionic_lif.h"
|
20 | 21 | #include "ionic_txrx.h"
|
21 | 22 | #include "ionic_ethtool.h"
|
@@ -200,6 +201,13 @@ void ionic_link_status_check_request(struct ionic_lif *lif, bool can_sleep)
|
200 | 201 | }
|
201 | 202 | }
|
202 | 203 |
|
| 204 | +static void ionic_napi_deadline(struct timer_list *timer) |
| 205 | +{ |
| 206 | + struct ionic_qcq *qcq = container_of(timer, struct ionic_qcq, napi_deadline); |
| 207 | + |
| 208 | + napi_schedule(&qcq->napi); |
| 209 | +} |
| 210 | + |
203 | 211 | static irqreturn_t ionic_isr(int irq, void *data)
|
204 | 212 | {
|
205 | 213 | struct napi_struct *napi = data;
|
@@ -269,23 +277,32 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq)
|
269 | 277 | .oper = IONIC_Q_ENABLE,
|
270 | 278 | },
|
271 | 279 | };
|
| 280 | + int ret; |
272 | 281 |
|
273 | 282 | idev = &lif->ionic->idev;
|
274 | 283 | dev = lif->ionic->dev;
|
275 | 284 |
|
276 | 285 | dev_dbg(dev, "q_enable.index %d q_enable.qtype %d\n",
|
277 | 286 | ctx.cmd.q_control.index, ctx.cmd.q_control.type);
|
278 | 287 |
|
| 288 | + if (qcq->flags & IONIC_QCQ_F_INTR) |
| 289 | + ionic_intr_clean(idev->intr_ctrl, qcq->intr.index); |
| 290 | + |
| 291 | + ret = ionic_adminq_post_wait(lif, &ctx); |
| 292 | + if (ret) |
| 293 | + return ret; |
| 294 | + |
| 295 | + if (qcq->napi.poll) |
| 296 | + napi_enable(&qcq->napi); |
| 297 | + |
279 | 298 | if (qcq->flags & IONIC_QCQ_F_INTR) {
|
280 | 299 | irq_set_affinity_hint(qcq->intr.vector,
|
281 | 300 | &qcq->intr.affinity_mask);
|
282 |
| - napi_enable(&qcq->napi); |
283 |
| - ionic_intr_clean(idev->intr_ctrl, qcq->intr.index); |
284 | 301 | ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
|
285 | 302 | IONIC_INTR_MASK_CLEAR);
|
286 | 303 | }
|
287 | 304 |
|
288 |
| - return ionic_adminq_post_wait(lif, &ctx); |
| 305 | + return 0; |
289 | 306 | }
|
290 | 307 |
|
291 | 308 | static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int fw_err)
|
@@ -316,6 +333,7 @@ static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int f
|
316 | 333 | synchronize_irq(qcq->intr.vector);
|
317 | 334 | irq_set_affinity_hint(qcq->intr.vector, NULL);
|
318 | 335 | napi_disable(&qcq->napi);
|
| 336 | + del_timer_sync(&qcq->napi_deadline); |
319 | 337 | }
|
320 | 338 |
|
321 | 339 | /* If there was a previous fw communcation error, don't bother with
|
@@ -451,6 +469,7 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
|
451 | 469 |
|
452 | 470 | n_qcq->intr.vector = src_qcq->intr.vector;
|
453 | 471 | n_qcq->intr.index = src_qcq->intr.index;
|
| 472 | + n_qcq->napi_qcq = src_qcq->napi_qcq; |
454 | 473 | }
|
455 | 474 |
|
456 | 475 | static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
@@ -564,13 +583,15 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
|
564 | 583 | }
|
565 | 584 |
|
566 | 585 | if (flags & IONIC_QCQ_F_NOTIFYQ) {
|
567 |
| - int q_size, cq_size; |
| 586 | + int q_size; |
568 | 587 |
|
569 |
| - /* q & cq need to be contiguous in case of notifyq */ |
| 588 | + /* q & cq need to be contiguous in NotifyQ, so alloc it all in q |
| 589 | + * and don't alloc qc. We leave new->qc_size and new->qc_base |
| 590 | + * as 0 to be sure we don't try to free it later. |
| 591 | + */ |
570 | 592 | q_size = ALIGN(num_descs * desc_size, PAGE_SIZE);
|
571 |
| - cq_size = ALIGN(num_descs * cq_desc_size, PAGE_SIZE); |
572 |
| - |
573 |
| - new->q_size = PAGE_SIZE + q_size + cq_size; |
| 593 | + new->q_size = PAGE_SIZE + q_size + |
| 594 | + ALIGN(num_descs * cq_desc_size, PAGE_SIZE); |
574 | 595 | new->q_base = dma_alloc_coherent(dev, new->q_size,
|
575 | 596 | &new->q_base_pa, GFP_KERNEL);
|
576 | 597 | if (!new->q_base) {
|
@@ -773,8 +794,14 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
773 | 794 | dev_dbg(dev, "txq->hw_type %d\n", q->hw_type);
|
774 | 795 | dev_dbg(dev, "txq->hw_index %d\n", q->hw_index);
|
775 | 796 |
|
776 |
| - if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) |
| 797 | + q->dbell_deadline = IONIC_TX_DOORBELL_DEADLINE; |
| 798 | + q->dbell_jiffies = jiffies; |
| 799 | + |
| 800 | + if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) { |
777 | 801 | netif_napi_add(lif->netdev, &qcq->napi, ionic_tx_napi);
|
| 802 | + qcq->napi_qcq = qcq; |
| 803 | + timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); |
| 804 | + } |
778 | 805 |
|
779 | 806 | qcq->flags |= IONIC_QCQ_F_INITED;
|
780 | 807 |
|
@@ -828,11 +855,17 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
828 | 855 | dev_dbg(dev, "rxq->hw_type %d\n", q->hw_type);
|
829 | 856 | dev_dbg(dev, "rxq->hw_index %d\n", q->hw_index);
|
830 | 857 |
|
| 858 | + q->dbell_deadline = IONIC_RX_MIN_DOORBELL_DEADLINE; |
| 859 | + q->dbell_jiffies = jiffies; |
| 860 | + |
831 | 861 | if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
|
832 | 862 | netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi);
|
833 | 863 | else
|
834 | 864 | netif_napi_add(lif->netdev, &qcq->napi, ionic_txrx_napi);
|
835 | 865 |
|
| 866 | + qcq->napi_qcq = qcq; |
| 867 | + timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); |
| 868 | + |
836 | 869 | qcq->flags |= IONIC_QCQ_F_INITED;
|
837 | 870 |
|
838 | 871 | return 0;
|
@@ -1150,6 +1183,7 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
|
1150 | 1183 | struct ionic_dev *idev = &lif->ionic->idev;
|
1151 | 1184 | unsigned long irqflags;
|
1152 | 1185 | unsigned int flags = 0;
|
| 1186 | + bool resched = false; |
1153 | 1187 | int rx_work = 0;
|
1154 | 1188 | int tx_work = 0;
|
1155 | 1189 | int n_work = 0;
|
@@ -1187,6 +1221,16 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
|
1187 | 1221 | ionic_intr_credits(idev->intr_ctrl, intr->index, credits, flags);
|
1188 | 1222 | }
|
1189 | 1223 |
|
| 1224 | + if (!a_work && ionic_adminq_poke_doorbell(&lif->adminqcq->q)) |
| 1225 | + resched = true; |
| 1226 | + if (lif->hwstamp_rxq && !rx_work && ionic_rxq_poke_doorbell(&lif->hwstamp_rxq->q)) |
| 1227 | + resched = true; |
| 1228 | + if (lif->hwstamp_txq && !tx_work && ionic_txq_poke_doorbell(&lif->hwstamp_txq->q)) |
| 1229 | + resched = true; |
| 1230 | + if (resched) |
| 1231 | + mod_timer(&lif->adminqcq->napi_deadline, |
| 1232 | + jiffies + IONIC_NAPI_DEADLINE); |
| 1233 | + |
1190 | 1234 | return work_done;
|
1191 | 1235 | }
|
1192 | 1236 |
|
@@ -3245,8 +3289,14 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif)
|
3245 | 3289 | dev_dbg(dev, "adminq->hw_type %d\n", q->hw_type);
|
3246 | 3290 | dev_dbg(dev, "adminq->hw_index %d\n", q->hw_index);
|
3247 | 3291 |
|
| 3292 | + q->dbell_deadline = IONIC_ADMIN_DOORBELL_DEADLINE; |
| 3293 | + q->dbell_jiffies = jiffies; |
| 3294 | + |
3248 | 3295 | netif_napi_add(lif->netdev, &qcq->napi, ionic_adminq_napi);
|
3249 | 3296 |
|
| 3297 | + qcq->napi_qcq = qcq; |
| 3298 | + timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); |
| 3299 | + |
3250 | 3300 | napi_enable(&qcq->napi);
|
3251 | 3301 |
|
3252 | 3302 | if (qcq->flags & IONIC_QCQ_F_INTR)
|
|
0 commit comments