mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
ionic: missed doorbell workaround
In one version of the HW there is a remote possibility that it
will miss the doorbell ring. This adds a bit of protection to
be sure we don't stall a queue from a missed doorbell.
Fixes: 0f3154e6bc ("ionic: Add Tx and Rx handling")
Signed-off-by: Allen Hubbe <allen.hubbe@amd.com>
Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
1fffb02541
commit
b69585bfce
@@ -708,9 +708,16 @@ void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb,
|
|||||||
q->lif->index, q->name, q->hw_type, q->hw_index,
|
q->lif->index, q->name, q->hw_type, q->hw_index,
|
||||||
q->head_idx, ring_doorbell);
|
q->head_idx, ring_doorbell);
|
||||||
|
|
||||||
if (ring_doorbell)
|
if (ring_doorbell) {
|
||||||
ionic_dbell_ring(lif->kern_dbpage, q->hw_type,
|
ionic_dbell_ring(lif->kern_dbpage, q->hw_type,
|
||||||
q->dbval | q->head_idx);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos)
|
static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos)
|
||||||
|
|||||||
@@ -25,6 +25,12 @@
|
|||||||
#define IONIC_DEV_INFO_REG_COUNT 32
|
#define IONIC_DEV_INFO_REG_COUNT 32
|
||||||
#define IONIC_DEV_CMD_REG_COUNT 32
|
#define IONIC_DEV_CMD_REG_COUNT 32
|
||||||
|
|
||||||
|
#define IONIC_NAPI_DEADLINE (HZ / 200) /* 5ms */
|
||||||
|
#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 */
|
||||||
|
#define IONIC_RX_MAX_DOORBELL_DEADLINE (HZ * 5) /* 5s */
|
||||||
|
|
||||||
struct ionic_dev_bar {
|
struct ionic_dev_bar {
|
||||||
void __iomem *vaddr;
|
void __iomem *vaddr;
|
||||||
phys_addr_t bus_addr;
|
phys_addr_t bus_addr;
|
||||||
@@ -216,6 +222,8 @@ struct ionic_queue {
|
|||||||
struct ionic_lif *lif;
|
struct ionic_lif *lif;
|
||||||
struct ionic_desc_info *info;
|
struct ionic_desc_info *info;
|
||||||
u64 dbval;
|
u64 dbval;
|
||||||
|
unsigned long dbell_deadline;
|
||||||
|
unsigned long dbell_jiffies;
|
||||||
u16 head_idx;
|
u16 head_idx;
|
||||||
u16 tail_idx;
|
u16 tail_idx;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
@@ -361,4 +369,8 @@ void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
|
|||||||
int ionic_heartbeat_check(struct ionic *ionic);
|
int ionic_heartbeat_check(struct ionic *ionic);
|
||||||
bool ionic_is_fw_running(struct ionic_dev *idev);
|
bool ionic_is_fw_running(struct ionic_dev *idev);
|
||||||
|
|
||||||
|
bool ionic_adminq_poke_doorbell(struct ionic_queue *q);
|
||||||
|
bool ionic_txq_poke_doorbell(struct ionic_queue *q);
|
||||||
|
bool ionic_rxq_poke_doorbell(struct ionic_queue *q);
|
||||||
|
|
||||||
#endif /* _IONIC_DEV_H_ */
|
#endif /* _IONIC_DEV_H_ */
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "ionic.h"
|
#include "ionic.h"
|
||||||
#include "ionic_bus.h"
|
#include "ionic_bus.h"
|
||||||
|
#include "ionic_dev.h"
|
||||||
#include "ionic_lif.h"
|
#include "ionic_lif.h"
|
||||||
#include "ionic_txrx.h"
|
#include "ionic_txrx.h"
|
||||||
#include "ionic_ethtool.h"
|
#include "ionic_ethtool.h"
|
||||||
@@ -200,6 +201,13 @@ 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)
|
static irqreturn_t ionic_isr(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct napi_struct *napi = data;
|
struct napi_struct *napi = data;
|
||||||
@@ -325,6 +333,7 @@ static int ionic_qcq_disable(struct ionic_lif *lif, struct ionic_qcq *qcq, int f
|
|||||||
synchronize_irq(qcq->intr.vector);
|
synchronize_irq(qcq->intr.vector);
|
||||||
irq_set_affinity_hint(qcq->intr.vector, NULL);
|
irq_set_affinity_hint(qcq->intr.vector, NULL);
|
||||||
napi_disable(&qcq->napi);
|
napi_disable(&qcq->napi);
|
||||||
|
del_timer_sync(&qcq->napi_deadline);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there was a previous fw communcation error, don't bother with
|
/* If there was a previous fw communcation error, don't bother with
|
||||||
@@ -460,6 +469,7 @@ static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
|
|||||||
|
|
||||||
n_qcq->intr.vector = src_qcq->intr.vector;
|
n_qcq->intr.vector = src_qcq->intr.vector;
|
||||||
n_qcq->intr.index = src_qcq->intr.index;
|
n_qcq->intr.index = src_qcq->intr.index;
|
||||||
|
n_qcq->napi_qcq = src_qcq->napi_qcq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
static int ionic_alloc_qcq_interrupt(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
||||||
@@ -784,8 +794,14 @@ static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
|||||||
dev_dbg(dev, "txq->hw_type %d\n", q->hw_type);
|
dev_dbg(dev, "txq->hw_type %d\n", q->hw_type);
|
||||||
dev_dbg(dev, "txq->hw_index %d\n", q->hw_index);
|
dev_dbg(dev, "txq->hw_index %d\n", q->hw_index);
|
||||||
|
|
||||||
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
|
q->dbell_deadline = IONIC_TX_DOORBELL_DEADLINE;
|
||||||
|
q->dbell_jiffies = jiffies;
|
||||||
|
|
||||||
|
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state)) {
|
||||||
netif_napi_add(lif->netdev, &qcq->napi, ionic_tx_napi);
|
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;
|
qcq->flags |= IONIC_QCQ_F_INITED;
|
||||||
|
|
||||||
@@ -839,11 +855,17 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
|||||||
dev_dbg(dev, "rxq->hw_type %d\n", q->hw_type);
|
dev_dbg(dev, "rxq->hw_type %d\n", q->hw_type);
|
||||||
dev_dbg(dev, "rxq->hw_index %d\n", q->hw_index);
|
dev_dbg(dev, "rxq->hw_index %d\n", q->hw_index);
|
||||||
|
|
||||||
|
q->dbell_deadline = IONIC_RX_MIN_DOORBELL_DEADLINE;
|
||||||
|
q->dbell_jiffies = jiffies;
|
||||||
|
|
||||||
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
|
if (test_bit(IONIC_LIF_F_SPLIT_INTR, lif->state))
|
||||||
netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi);
|
netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi);
|
||||||
else
|
else
|
||||||
netif_napi_add(lif->netdev, &qcq->napi, ionic_txrx_napi);
|
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;
|
qcq->flags |= IONIC_QCQ_F_INITED;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1161,6 +1183,7 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
|
|||||||
struct ionic_dev *idev = &lif->ionic->idev;
|
struct ionic_dev *idev = &lif->ionic->idev;
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
|
bool resched = false;
|
||||||
int rx_work = 0;
|
int rx_work = 0;
|
||||||
int tx_work = 0;
|
int tx_work = 0;
|
||||||
int n_work = 0;
|
int n_work = 0;
|
||||||
@@ -1198,6 +1221,16 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
|
|||||||
ionic_intr_credits(idev->intr_ctrl, intr->index, credits, flags);
|
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);
|
||||||
|
|
||||||
return work_done;
|
return work_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3256,8 +3289,14 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif)
|
|||||||
dev_dbg(dev, "adminq->hw_type %d\n", q->hw_type);
|
dev_dbg(dev, "adminq->hw_type %d\n", q->hw_type);
|
||||||
dev_dbg(dev, "adminq->hw_index %d\n", q->hw_index);
|
dev_dbg(dev, "adminq->hw_index %d\n", q->hw_index);
|
||||||
|
|
||||||
|
q->dbell_deadline = IONIC_ADMIN_DOORBELL_DEADLINE;
|
||||||
|
q->dbell_jiffies = jiffies;
|
||||||
|
|
||||||
netif_napi_add(lif->netdev, &qcq->napi, ionic_adminq_napi);
|
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);
|
napi_enable(&qcq->napi);
|
||||||
|
|
||||||
if (qcq->flags & IONIC_QCQ_F_INTR)
|
if (qcq->flags & IONIC_QCQ_F_INTR)
|
||||||
|
|||||||
@@ -74,8 +74,10 @@ struct ionic_qcq {
|
|||||||
struct ionic_queue q;
|
struct ionic_queue q;
|
||||||
struct ionic_cq cq;
|
struct ionic_cq cq;
|
||||||
struct ionic_intr_info intr;
|
struct ionic_intr_info intr;
|
||||||
|
struct timer_list napi_deadline;
|
||||||
struct napi_struct napi;
|
struct napi_struct napi;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
struct ionic_qcq *napi_qcq;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -289,6 +289,35 @@ static void ionic_adminq_cb(struct ionic_queue *q,
|
|||||||
complete_all(&ctx->work);
|
complete_all(&ctx->work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ionic_adminq_poke_doorbell(struct ionic_queue *q)
|
||||||
|
{
|
||||||
|
struct ionic_lif *lif = q->lif;
|
||||||
|
unsigned long now, then, dif;
|
||||||
|
unsigned long irqflags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&lif->adminq_lock, irqflags);
|
||||||
|
|
||||||
|
if (q->tail_idx == q->head_idx) {
|
||||||
|
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
now = READ_ONCE(jiffies);
|
||||||
|
then = q->dbell_jiffies;
|
||||||
|
dif = now - then;
|
||||||
|
|
||||||
|
if (dif > q->dbell_deadline) {
|
||||||
|
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
|
||||||
|
q->dbval | q->head_idx);
|
||||||
|
|
||||||
|
q->dbell_jiffies = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
|
int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct ionic_desc_info *desc_info;
|
struct ionic_desc_info *desc_info;
|
||||||
|
|||||||
@@ -22,6 +22,67 @@ static inline void ionic_rxq_post(struct ionic_queue *q, bool ring_dbell,
|
|||||||
ionic_q_post(q, ring_dbell, cb_func, cb_arg);
|
ionic_q_post(q, ring_dbell, cb_func, cb_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ionic_txq_poke_doorbell(struct ionic_queue *q)
|
||||||
|
{
|
||||||
|
unsigned long now, then, dif;
|
||||||
|
struct netdev_queue *netdev_txq;
|
||||||
|
struct net_device *netdev;
|
||||||
|
|
||||||
|
netdev = q->lif->netdev;
|
||||||
|
netdev_txq = netdev_get_tx_queue(netdev, q->index);
|
||||||
|
|
||||||
|
HARD_TX_LOCK(netdev, netdev_txq, smp_processor_id());
|
||||||
|
|
||||||
|
if (q->tail_idx == q->head_idx) {
|
||||||
|
HARD_TX_UNLOCK(netdev, netdev_txq);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
now = READ_ONCE(jiffies);
|
||||||
|
then = q->dbell_jiffies;
|
||||||
|
dif = now - then;
|
||||||
|
|
||||||
|
if (dif > q->dbell_deadline) {
|
||||||
|
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
|
||||||
|
q->dbval | q->head_idx);
|
||||||
|
|
||||||
|
q->dbell_jiffies = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
HARD_TX_UNLOCK(netdev, netdev_txq);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ionic_rxq_poke_doorbell(struct ionic_queue *q)
|
||||||
|
{
|
||||||
|
unsigned long now, then, dif;
|
||||||
|
|
||||||
|
/* no lock, called from rx napi or txrx napi, nothing else can fill */
|
||||||
|
|
||||||
|
if (q->tail_idx == q->head_idx)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
now = READ_ONCE(jiffies);
|
||||||
|
then = q->dbell_jiffies;
|
||||||
|
dif = now - then;
|
||||||
|
|
||||||
|
if (dif > q->dbell_deadline) {
|
||||||
|
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
|
||||||
|
q->dbval | q->head_idx);
|
||||||
|
|
||||||
|
q->dbell_jiffies = now;
|
||||||
|
|
||||||
|
dif = 2 * q->dbell_deadline;
|
||||||
|
if (dif > IONIC_RX_MAX_DOORBELL_DEADLINE)
|
||||||
|
dif = IONIC_RX_MAX_DOORBELL_DEADLINE;
|
||||||
|
|
||||||
|
q->dbell_deadline = dif;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q)
|
static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q)
|
||||||
{
|
{
|
||||||
return netdev_get_tx_queue(q->lif->netdev, q->index);
|
return netdev_get_tx_queue(q->lif->netdev, q->index);
|
||||||
@@ -424,6 +485,12 @@ void ionic_rx_fill(struct ionic_queue *q)
|
|||||||
|
|
||||||
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
|
ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,
|
||||||
q->dbval | q->head_idx);
|
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)
|
void ionic_rx_empty(struct ionic_queue *q)
|
||||||
@@ -511,6 +578,9 @@ int ionic_tx_napi(struct napi_struct *napi, int budget)
|
|||||||
work_done, flags);
|
work_done, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!work_done && ionic_txq_poke_doorbell(&qcq->q))
|
||||||
|
mod_timer(&qcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE);
|
||||||
|
|
||||||
return work_done;
|
return work_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,23 +614,29 @@ int ionic_rx_napi(struct napi_struct *napi, int budget)
|
|||||||
work_done, flags);
|
work_done, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!work_done && ionic_rxq_poke_doorbell(&qcq->q))
|
||||||
|
mod_timer(&qcq->napi_deadline, jiffies + IONIC_NAPI_DEADLINE);
|
||||||
|
|
||||||
return work_done;
|
return work_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ionic_txrx_napi(struct napi_struct *napi, int budget)
|
int ionic_txrx_napi(struct napi_struct *napi, int budget)
|
||||||
{
|
{
|
||||||
struct ionic_qcq *qcq = napi_to_qcq(napi);
|
struct ionic_qcq *rxqcq = napi_to_qcq(napi);
|
||||||
struct ionic_cq *rxcq = napi_to_cq(napi);
|
struct ionic_cq *rxcq = napi_to_cq(napi);
|
||||||
unsigned int qi = rxcq->bound_q->index;
|
unsigned int qi = rxcq->bound_q->index;
|
||||||
|
struct ionic_qcq *txqcq;
|
||||||
struct ionic_dev *idev;
|
struct ionic_dev *idev;
|
||||||
struct ionic_lif *lif;
|
struct ionic_lif *lif;
|
||||||
struct ionic_cq *txcq;
|
struct ionic_cq *txcq;
|
||||||
|
bool resched = false;
|
||||||
u32 rx_work_done = 0;
|
u32 rx_work_done = 0;
|
||||||
u32 tx_work_done = 0;
|
u32 tx_work_done = 0;
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
|
|
||||||
lif = rxcq->bound_q->lif;
|
lif = rxcq->bound_q->lif;
|
||||||
idev = &lif->ionic->idev;
|
idev = &lif->ionic->idev;
|
||||||
|
txqcq = lif->txqcqs[qi];
|
||||||
txcq = &lif->txqcqs[qi]->cq;
|
txcq = &lif->txqcqs[qi]->cq;
|
||||||
|
|
||||||
tx_work_done = ionic_cq_service(txcq, IONIC_TX_BUDGET_DEFAULT,
|
tx_work_done = ionic_cq_service(txcq, IONIC_TX_BUDGET_DEFAULT,
|
||||||
@@ -572,7 +648,7 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
|
|||||||
ionic_rx_fill(rxcq->bound_q);
|
ionic_rx_fill(rxcq->bound_q);
|
||||||
|
|
||||||
if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) {
|
if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) {
|
||||||
ionic_dim_update(qcq, 0);
|
ionic_dim_update(rxqcq, 0);
|
||||||
flags |= IONIC_INTR_CRED_UNMASK;
|
flags |= IONIC_INTR_CRED_UNMASK;
|
||||||
rxcq->bound_intr->rearm_count++;
|
rxcq->bound_intr->rearm_count++;
|
||||||
}
|
}
|
||||||
@@ -583,6 +659,13 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
|
|||||||
tx_work_done + rx_work_done, flags);
|
tx_work_done + rx_work_done, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
return rx_work_done;
|
return rx_work_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user