diff --git a/README.md b/README.md index 9c37191..f964393 100644 --- a/README.md +++ b/README.md @@ -195,12 +195,15 @@ As usual, if the Linux headers are elsewhere, add the appropriate -C magic: - fix 16bit math issue when PAGE_SIZE >= 64KB - restrict page-cache allocation to Rx queues -23-12-14 - driver update for 23.12.2-001 +2023-12-14 - driver update for 23.12.2-001 - updates from upstream kernel fixes - updates to FLR handling - added AER error handling -24-03-19 - driver update for 24.03.1-002 +2024-03-19 - driver update for 24.03.1-002 - Add XDP support - Refactor Tx and Rx fast paths for performance - Refactor struct sizes, layout, and usage for memory savings and performance + +2024-04-03 - driver update for 24.03.4-002 + - Fix to reduce impact of missed doorbell workaround diff --git a/drivers/linux/Makefile b/drivers/linux/Makefile index a255f86..d98fd56 100644 --- a/drivers/linux/Makefile +++ b/drivers/linux/Makefile @@ -69,7 +69,7 @@ ALL = eth endif ifeq ($(DVER),) - DVER = "24.03.1-002" + DVER = "24.03.4-002" endif KCFLAGS += -Ddrv_ver=\\\"$(DVER)\\\" diff --git a/drivers/linux/eth/ionic/ionic.h b/drivers/linux/eth/ionic/ionic.h index 06db8be..708efd2 100644 --- a/drivers/linux/eth/ionic/ionic.h +++ b/drivers/linux/eth/ionic/ionic.h @@ -80,6 +80,7 @@ struct ionic { struct rw_semaphore vf_op_lock; /* lock for VF operations */ struct ionic_vf *vfs; int num_vfs; + struct timer_list doorbell_timer; struct timer_list watchdog_timer; int watchdog_period; }; diff --git a/drivers/linux/eth/ionic/ionic_bus_pci.c b/drivers/linux/eth/ionic/ionic_bus_pci.c index 50b49c7..75e1262 100644 --- a/drivers/linux/eth/ionic/ionic_bus_pci.c +++ b/drivers/linux/eth/ionic/ionic_bus_pci.c @@ -438,6 +438,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_deregister_devlink; } + mod_timer(&ionic->doorbell_timer, jiffies + IONIC_NAPI_DEADLINE); mod_timer(&ionic->watchdog_timer, round_jiffies(jiffies + ionic->watchdog_period)); @@ -470,6 +471,7 @@ static void ionic_remove(struct pci_dev *pdev) if (ionic->lif) set_bit(IONIC_LIF_F_IN_SHUTDOWN, ionic->lif->state); + del_timer_sync(&ionic->doorbell_timer); del_timer_sync(&ionic->watchdog_timer); if (ionic->lif) { @@ -509,6 +511,7 @@ void ionic_reset_prepare(struct pci_dev *pdev) * scheduled and render these del/cancel calls useless (i.e. don't mix * device triggered resets with userspace triggered resets). */ + del_timer_sync(&ionic->doorbell_timer); del_timer_sync(&ionic->watchdog_timer); mutex_lock(&lif->queue_lock); @@ -542,6 +545,7 @@ void ionic_reset_done(struct pci_dev *pdev) if (err) goto err_out; + mod_timer(&ionic->doorbell_timer, jiffies + IONIC_NAPI_DEADLINE); mod_timer(&ionic->watchdog_timer, jiffies + 1); err_out: diff --git a/drivers/linux/eth/ionic/ionic_bus_platform.c b/drivers/linux/eth/ionic/ionic_bus_platform.c index c057a75..7c61fd2 100644 --- a/drivers/linux/eth/ionic/ionic_bus_platform.c +++ b/drivers/linux/eth/ionic/ionic_bus_platform.c @@ -222,6 +222,8 @@ static int ionic_mnic_dev_setup(struct ionic *ionic) return -EFAULT; ionic_init_devinfo(ionic); + + timer_setup(&ionic->doorbell_timer, ionic_doorbell_cb, 0); ionic_watchdog_init(ionic); idev->db_pages = ionic->bars[IONIC_DOORBELL_BAR].vaddr; @@ -403,6 +405,7 @@ int ionic_probe(struct platform_device *pfdev) goto err_out_deinit_lifs; } + mod_timer(&ionic->doorbell_timer, jiffies + IONIC_NAPI_DEADLINE); mod_timer(&ionic->watchdog_timer, round_jiffies(jiffies + ionic->watchdog_period)); @@ -430,6 +433,7 @@ int ionic_remove(struct platform_device *pfdev) struct ionic *ionic = platform_get_drvdata(pfdev); if (ionic) { + del_timer_sync(&ionic->doorbell_timer); del_timer_sync(&ionic->watchdog_timer); ionic_lif_unregister(ionic->lif); ionic_lif_deinit(ionic->lif); diff --git a/drivers/linux/eth/ionic/ionic_dev.c b/drivers/linux/eth/ionic/ionic_dev.c index e212a57..01ca30d 100644 --- a/drivers/linux/eth/ionic/ionic_dev.c +++ b/drivers/linux/eth/ionic/ionic_dev.c @@ -73,6 +73,26 @@ void ionic_watchdog_init(struct ionic *ionic) ioread8(&idev->dev_info_regs->fw_status); } +void ionic_doorbell_cb(struct timer_list *timer) +{ + struct ionic *ionic = container_of(timer, struct ionic, doorbell_timer); + struct ionic_lif *lif = ionic->lif; + struct ionic_deferred_work *work; + + if (test_bit(IONIC_LIF_F_IN_SHUTDOWN, lif->state)) + return; + + if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) { + work = kzalloc(sizeof(*work), GFP_ATOMIC); + if (work) { + work->type = IONIC_DW_TYPE_DOORBELL; + ionic_lif_deferred_enqueue(&lif->deferred, work); + } + } + + mod_timer(&ionic->doorbell_timer, jiffies + IONIC_NAPI_DEADLINE); +} + void ionic_init_devinfo(struct ionic *ionic) { struct ionic_dev *idev = &ionic->idev; @@ -137,6 +157,7 @@ int ionic_dev_setup(struct ionic *ionic) return -EFAULT; } + timer_setup(&ionic->doorbell_timer, ionic_doorbell_cb, 0); ionic_watchdog_init(ionic); idev->db_pages = bar->vaddr; @@ -724,10 +745,6 @@ void ionic_q_post(struct ionic_queue *q, bool ring_doorbell) q->dbval | q->head_idx); q->dbell_jiffies = jiffies; - - if (q_to_qcq(q)->napi_qcq) - mod_timer(&q_to_qcq(q)->napi_qcq->napi_deadline, - jiffies + IONIC_NAPI_DEADLINE); } } diff --git a/drivers/linux/eth/ionic/ionic_dev.h b/drivers/linux/eth/ionic/ionic_dev.h index 9f15d08..b4cbbb2 100644 --- a/drivers/linux/eth/ionic/ionic_dev.h +++ b/drivers/linux/eth/ionic/ionic_dev.h @@ -33,7 +33,7 @@ #define IONIC_DEV_INFO_REG_COUNT 32 #define IONIC_DEV_CMD_REG_COUNT 32 -#define IONIC_NAPI_DEADLINE (HZ / 200) /* 5ms */ +#define IONIC_NAPI_DEADLINE (HZ / 50) /* 20ms */ #define IONIC_ADMIN_DOORBELL_DEADLINE (HZ / 2) /* 500ms */ #define IONIC_TX_DOORBELL_DEADLINE (HZ / 100) /* 10ms */ #define IONIC_RX_MIN_DOORBELL_DEADLINE (HZ / 100) /* 10ms */ @@ -423,6 +423,7 @@ bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos); int ionic_heartbeat_check(struct ionic *ionic); bool ionic_is_fw_running(struct ionic_dev *idev); +void ionic_doorbell_cb(struct timer_list *timer); void ionic_watchdog_cb(struct timer_list *t); void ionic_watchdog_init(struct ionic *ionic); diff --git a/drivers/linux/eth/ionic/ionic_lif.c b/drivers/linux/eth/ionic/ionic_lif.c index 91454ef..2eaa01c 100644 --- a/drivers/linux/eth/ionic/ionic_lif.c +++ b/drivers/linux/eth/ionic/ionic_lif.c @@ -87,6 +87,42 @@ static void ionic_dim_work(struct work_struct *work) dim->state = DIM_START_MEASURE; } +static void ionic_doorbell_check(struct ionic_lif *lif) +{ + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state) || + test_bit(IONIC_LIF_F_IN_SHUTDOWN, lif->state)) + return; + + mutex_lock(&lif->queue_lock); + + napi_schedule(&lif->adminqcq->napi); + + if (test_bit(IONIC_LIF_F_UP, lif->state)) { + int i; + + for (i = 0; i < lif->nxqs; i++) { + struct ionic_qcq *qcq; + + qcq = lif->txqcqs[i]; + if (qcq->flags & IONIC_QCQ_F_INTR) + napi_schedule(&qcq->napi); + + qcq = lif->rxqcqs[i]; + if (qcq->flags & IONIC_QCQ_F_INTR) + napi_schedule(&qcq->napi); + } + + if (lif->hwstamp_txq && + lif->hwstamp_txq->flags & IONIC_QCQ_F_INTR) + napi_schedule(&lif->hwstamp_txq->napi); + if (lif->hwstamp_rxq && + lif->hwstamp_rxq->flags & IONIC_QCQ_F_INTR) + napi_schedule(&lif->hwstamp_rxq->napi); + + } + mutex_unlock(&lif->queue_lock); +} + static void ionic_lif_deferred_work(struct work_struct *work) { struct ionic_lif *lif = container_of(work, struct ionic_lif, deferred.work); @@ -112,6 +148,9 @@ static void ionic_lif_deferred_work(struct work_struct *work) case IONIC_DW_TYPE_LINK_STATUS: ionic_link_status_check(lif); break; + case IONIC_DW_TYPE_DOORBELL: + ionic_doorbell_check(lif); + break; case IONIC_DW_TYPE_LIF_RESET: if (w->fw_status) { ionic_lif_handle_fw_up(lif); @@ -223,13 +262,6 @@ void ionic_link_status_check_request(struct ionic_lif *lif, bool can_sleep) } } -static void ionic_napi_deadline(struct timer_list *timer) -{ - struct ionic_qcq *qcq = container_of(timer, struct ionic_qcq, napi_deadline); - - napi_schedule(&qcq->napi); -} - static irqreturn_t ionic_isr(int irq, void *data) { struct napi_struct *napi = data; @@ -347,7 +379,6 @@ static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int f if (qcq->napi.poll) { napi_disable(&qcq->napi); - del_timer_sync(&qcq->napi_deadline); synchronize_net(); } @@ -898,7 +929,6 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq) if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) { netif_napi_add(lif->netdev, &qcq->napi, ionic_tx_napi); qcq->napi_qcq = qcq; - timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); } qcq->flags |= IONIC_QCQ_F_INITED; @@ -978,7 +1008,6 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq) netif_napi_add(lif->netdev, &qcq->napi, ionic_txrx_napi); qcq->napi_qcq = qcq; - timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); qcq->flags |= IONIC_QCQ_F_INITED; @@ -1234,7 +1263,6 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget) struct ionic_dev *idev = &lif->ionic->idev; unsigned long irqflags; unsigned int flags = 0; - bool resched = false; int rx_work = 0; int tx_work = 0; int n_work = 0; @@ -1271,15 +1299,12 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget) ionic_intr_credits(idev->intr_ctrl, intr->index, credits, flags); } - if (!a_work && ionic_adminq_poke_doorbell(&lif->adminqcq->q)) - resched = true; - if (lif->hwstamp_rxq && !rx_work && ionic_rxq_poke_doorbell(&lif->hwstamp_rxq->q)) - resched = true; - if (lif->hwstamp_txq && !tx_work && ionic_txq_poke_doorbell(&lif->hwstamp_txq->q)) - resched = true; - if (resched) - mod_timer(&lif->adminqcq->napi_deadline, - jiffies + IONIC_NAPI_DEADLINE); + if (!a_work) + ionic_adminq_poke_doorbell(&lif->adminqcq->q); + if (lif->hwstamp_rxq && !rx_work) + ionic_rxq_poke_doorbell(&lif->hwstamp_rxq->q); + if (lif->hwstamp_txq && !tx_work) + ionic_txq_poke_doorbell(&lif->hwstamp_txq->q); return work_done; } @@ -3761,7 +3786,6 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif) netif_napi_add(lif->netdev, &qcq->napi, ionic_adminq_napi); qcq->napi_qcq = qcq; - timer_setup(&qcq->napi_deadline, ionic_napi_deadline, 0); napi_enable(&qcq->napi); diff --git a/drivers/linux/eth/ionic/ionic_lif.h b/drivers/linux/eth/ionic/ionic_lif.h index 5e60539..1b869ce 100644 --- a/drivers/linux/eth/ionic/ionic_lif.h +++ b/drivers/linux/eth/ionic/ionic_lif.h @@ -120,7 +120,6 @@ struct ionic_qcq { u32 cmb_order; bool armed; struct dim dim; - struct timer_list napi_deadline; struct ionic_queue q; struct ionic_cq cq; struct napi_struct napi; @@ -142,6 +141,7 @@ enum ionic_deferred_work_type { IONIC_DW_TYPE_RX_MODE, IONIC_DW_TYPE_LINK_STATUS, IONIC_DW_TYPE_LIF_RESET, + IONIC_DW_TYPE_DOORBELL, }; struct ionic_deferred_work { diff --git a/drivers/linux/eth/ionic/ionic_txrx.c b/drivers/linux/eth/ionic/ionic_txrx.c index 503b632..808f7cf 100644 --- a/drivers/linux/eth/ionic/ionic_txrx.c +++ b/drivers/linux/eth/ionic/ionic_txrx.c @@ -1022,12 +1022,6 @@ void ionic_rx_fill(struct ionic_queue *q) ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type, q->dbval | q->head_idx); - - q->dbell_deadline = IONIC_RX_MIN_DOORBELL_DEADLINE; - q->dbell_jiffies = jiffies; - - mod_timer(&q_to_qcq(q)->napi_qcq->napi_deadline, - jiffies + IONIC_NAPI_DEADLINE); } void ionic_rx_empty(struct ionic_queue *q) @@ -1112,8 +1106,8 @@ int ionic_tx_napi(struct napi_struct *napi, int budget) work_done, flags); } - if (!work_done && ionic_txq_poke_doorbell(&qcq->q)) - mod_timer(&qcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE); + if (!work_done) + ionic_txq_poke_doorbell(&qcq->q); DEBUG_STATS_NAPI_POLL(qcq, work_done); @@ -1159,8 +1153,8 @@ int ionic_rx_napi(struct napi_struct *napi, int budget) work_done, flags); } - if (!work_done && ionic_rxq_poke_doorbell(&qcq->q)) - mod_timer(&qcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE); + if (!work_done) + ionic_rxq_poke_doorbell(&qcq->q); DEBUG_STATS_NAPI_POLL(qcq, work_done); @@ -1175,7 +1169,6 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget) struct ionic_qcq *txqcq; struct ionic_lif *lif; struct ionic_cq *txcq; - bool resched = false; u32 rx_work_done = 0; u32 tx_work_done = 0; u32 flags = 0; @@ -1210,12 +1203,10 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget) DEBUG_STATS_NAPI_POLL(rxqcq, rx_work_done); DEBUG_STATS_NAPI_POLL(txqcq, tx_work_done); - if (!rx_work_done && ionic_rxq_poke_doorbell(&rxqcq->q)) - resched = true; - if (!tx_work_done && ionic_txq_poke_doorbell(&txqcq->q)) - resched = true; - if (resched) - mod_timer(&rxqcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE); + if (!rx_work_done) + ionic_rxq_poke_doorbell(&rxqcq->q); + if (!tx_work_done) + ionic_txq_poke_doorbell(&txqcq->q); return rx_work_done; }