Commit e768929d authored by Shannon Nelson's avatar Shannon Nelson Committed by David S. Miller

ionic: protect adminq from early destroy

Don't destroy the adminq while there is an outstanding request.
Signed-off-by: default avatarShannon Nelson <snelson@pensando.io>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9e8eaf84
......@@ -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_irqsave(&lif->adminq_lock, irqflags);
if (!lif->adminqcq) {
spin_unlock_irqrestore(&lif->adminq_lock, irqflags);
return;
}
spin_lock(&lif->adminq_lock);
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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment