mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 21:04:42 -04:00
ionic: protect adminq from early destroy
Don't destroy the adminq while there is an outstanding request. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
9e8eaf8427
commit
e768929de1
@@ -393,6 +393,8 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
|
||||
static void ionic_qcqs_free(struct ionic_lif *lif)
|
||||
{
|
||||
struct device *dev = lif->ionic->dev;
|
||||
struct ionic_qcq *adminqcq;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (lif->notifyqcq) {
|
||||
ionic_qcq_free(lif, lif->notifyqcq);
|
||||
@@ -401,9 +403,14 @@ static void ionic_qcqs_free(struct ionic_lif *lif)
|
||||
}
|
||||
|
||||
if (lif->adminqcq) {
|
||||
ionic_qcq_free(lif, lif->adminqcq);
|
||||
devm_kfree(dev, lif->adminqcq);
|
||||
spin_lock_irqsave(&lif->adminq_lock, irqflags);
|
||||
adminqcq = READ_ONCE(lif->adminqcq);
|
||||
lif->adminqcq = NULL;
|
||||
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
|
||||
if (adminqcq) {
|
||||
ionic_qcq_free(lif, adminqcq);
|
||||
devm_kfree(dev, adminqcq);
|
||||
}
|
||||
}
|
||||
|
||||
if (lif->rxqcqs) {
|
||||
@@ -886,6 +893,7 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
|
||||
struct ionic_intr_info *intr = napi_to_cq(napi)->bound_intr;
|
||||
struct ionic_lif *lif = napi_to_cq(napi)->lif;
|
||||
struct ionic_dev *idev = &lif->ionic->idev;
|
||||
unsigned long irqflags;
|
||||
unsigned int flags = 0;
|
||||
int n_work = 0;
|
||||
int a_work = 0;
|
||||
@@ -895,9 +903,11 @@ static int ionic_adminq_napi(struct napi_struct *napi, int budget)
|
||||
n_work = ionic_cq_service(&lif->notifyqcq->cq, budget,
|
||||
ionic_notifyq_service, NULL, NULL);
|
||||
|
||||
spin_lock_irqsave(&lif->adminq_lock, irqflags);
|
||||
if (lif->adminqcq && lif->adminqcq->flags & IONIC_QCQ_F_INITED)
|
||||
a_work = ionic_cq_service(&lif->adminqcq->cq, budget,
|
||||
ionic_adminq_service, NULL, NULL);
|
||||
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
|
||||
|
||||
work_done = max(n_work, a_work);
|
||||
if (work_done < budget && napi_complete_done(napi, work_done)) {
|
||||
|
||||
@@ -187,10 +187,17 @@ static const char *ionic_opcode_to_str(enum ionic_cmd_opcode opcode)
|
||||
|
||||
static void ionic_adminq_flush(struct ionic_lif *lif)
|
||||
{
|
||||
struct ionic_queue *q = &lif->adminqcq->q;
|
||||
struct ionic_desc_info *desc_info;
|
||||
unsigned long irqflags;
|
||||
struct ionic_queue *q;
|
||||
|
||||
spin_lock(&lif->adminq_lock);
|
||||
spin_lock_irqsave(&lif->adminq_lock, irqflags);
|
||||
if (!lif->adminqcq) {
|
||||
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
|
||||
return;
|
||||
}
|
||||
|
||||
q = &lif->adminqcq->q;
|
||||
|
||||
while (q->tail_idx != q->head_idx) {
|
||||
desc_info = &q->info[q->tail_idx];
|
||||
@@ -199,7 +206,7 @@ static void ionic_adminq_flush(struct ionic_lif *lif)
|
||||
desc_info->cb_arg = NULL;
|
||||
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
|
||||
}
|
||||
spin_unlock(&lif->adminq_lock);
|
||||
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
|
||||
}
|
||||
|
||||
static int ionic_adminq_check_err(struct ionic_lif *lif,
|
||||
@@ -252,15 +259,18 @@ static void ionic_adminq_cb(struct ionic_queue *q,
|
||||
static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
|
||||
{
|
||||
struct ionic_desc_info *desc_info;
|
||||
unsigned long irqflags;
|
||||
struct ionic_queue *q;
|
||||
int err = 0;
|
||||
|
||||
if (!lif->adminqcq)
|
||||
spin_lock_irqsave(&lif->adminq_lock, irqflags);
|
||||
if (!lif->adminqcq) {
|
||||
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
q = &lif->adminqcq->q;
|
||||
|
||||
spin_lock(&lif->adminq_lock);
|
||||
if (!ionic_q_has_space(q, 1)) {
|
||||
err = -ENOSPC;
|
||||
goto err_out;
|
||||
@@ -280,7 +290,7 @@ static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
|
||||
ionic_q_post(q, true, ionic_adminq_cb, ctx);
|
||||
|
||||
err_out:
|
||||
spin_unlock(&lif->adminq_lock);
|
||||
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user