[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190829182720.68419-9-snelson@pensando.io>
Date: Thu, 29 Aug 2019 11:27:09 -0700
From: Shannon Nelson <snelson@...sando.io>
To: snelson@...sando.io, netdev@...r.kernel.org, davem@...emloft.net
Subject: [PATCH v6 net-next 08/19] ionic: Add adminq action
Add AdminQ specific message requests and completion handling.
Signed-off-by: Shannon Nelson <snelson@...sando.io>
---
drivers/net/ethernet/pensando/ionic/ionic.h | 7 ++
.../net/ethernet/pensando/ionic/ionic_main.c | 111 ++++++++++++++++++
2 files changed, 118 insertions(+)
diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h
index 23d39be54064..16b1f054ebbe 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic.h
@@ -44,9 +44,16 @@ struct ionic {
DECLARE_BITMAP(intrs, IONIC_INTR_CTRL_REGS_MAX);
};
+struct ionic_admin_ctx {
+ struct completion work;
+ union ionic_adminq_cmd cmd;
+ union ionic_adminq_comp comp;
+};
+
int ionic_napi(struct napi_struct *napi, int budget, ionic_cq_cb cb,
ionic_cq_done_cb done_cb, void *done_arg);
+int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);
int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_wait);
int ionic_set_dma_mask(struct ionic *ionic);
int ionic_setup(struct ionic *ionic);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c
index 647f4c3b8b49..b57dcae5bc4a 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_main.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c
@@ -169,6 +169,117 @@ static const char *ionic_opcode_to_str(enum ionic_cmd_opcode opcode)
}
}
+static void ionic_adminq_flush(struct ionic_lif *lif)
+{
+ struct ionic_queue *adminq = &lif->adminqcq->q;
+
+ spin_lock(&lif->adminq_lock);
+
+ while (adminq->tail != adminq->head) {
+ memset(adminq->tail->desc, 0, sizeof(union ionic_adminq_cmd));
+ adminq->tail->cb = NULL;
+ adminq->tail->cb_arg = NULL;
+ adminq->tail = adminq->tail->next;
+ }
+ spin_unlock(&lif->adminq_lock);
+}
+
+static int ionic_adminq_check_err(struct ionic_lif *lif,
+ struct ionic_admin_ctx *ctx,
+ bool timeout)
+{
+ struct net_device *netdev = lif->netdev;
+ const char *opcode_str;
+ const char *status_str;
+ int err = 0;
+
+ if (ctx->comp.comp.status || timeout) {
+ opcode_str = ionic_opcode_to_str(ctx->cmd.cmd.opcode);
+ status_str = ionic_error_to_str(ctx->comp.comp.status);
+ err = timeout ? -ETIMEDOUT :
+ ionic_error_to_errno(ctx->comp.comp.status);
+
+ netdev_err(netdev, "%s (%d) failed: %s (%d)\n",
+ opcode_str, ctx->cmd.cmd.opcode,
+ timeout ? "TIMEOUT" : status_str, err);
+
+ if (timeout)
+ ionic_adminq_flush(lif);
+ }
+
+ return err;
+}
+
+static void ionic_adminq_cb(struct ionic_queue *q,
+ struct ionic_desc_info *desc_info,
+ struct ionic_cq_info *cq_info, void *cb_arg)
+{
+ struct ionic_admin_ctx *ctx = cb_arg;
+ struct ionic_admin_comp *comp;
+ struct device *dev;
+
+ if (!ctx)
+ return;
+
+ comp = cq_info->cq_desc;
+ dev = &q->lif->netdev->dev;
+
+ memcpy(&ctx->comp, comp, sizeof(*comp));
+
+ dev_dbg(dev, "comp admin queue command:\n");
+ dynamic_hex_dump("comp ", DUMP_PREFIX_OFFSET, 16, 1,
+ &ctx->comp, sizeof(ctx->comp), true);
+
+ complete_all(&ctx->work);
+}
+
+static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
+{
+ struct ionic_queue *adminq = &lif->adminqcq->q;
+ int err = 0;
+
+ WARN_ON(in_interrupt());
+
+ spin_lock(&lif->adminq_lock);
+ if (!ionic_q_has_space(adminq, 1)) {
+ err = -ENOSPC;
+ goto err_out;
+ }
+
+ memcpy(adminq->head->desc, &ctx->cmd, sizeof(ctx->cmd));
+
+ dev_dbg(&lif->netdev->dev, "post admin queue command:\n");
+ dynamic_hex_dump("cmd ", DUMP_PREFIX_OFFSET, 16, 1,
+ &ctx->cmd, sizeof(ctx->cmd), true);
+
+ ionic_q_post(adminq, true, ionic_adminq_cb, ctx);
+
+err_out:
+ spin_unlock(&lif->adminq_lock);
+
+ return err;
+}
+
+int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
+{
+ struct net_device *netdev = lif->netdev;
+ unsigned long remaining;
+ const char *name;
+ int err;
+
+ err = ionic_adminq_post(lif, ctx);
+ if (err) {
+ name = ionic_opcode_to_str(ctx->cmd.cmd.opcode);
+ netdev_err(netdev, "Posting of %s (%d) failed: %d\n",
+ name, ctx->cmd.cmd.opcode, err);
+ return err;
+ }
+
+ remaining = wait_for_completion_timeout(&ctx->work,
+ HZ * (ulong)DEVCMD_TIMEOUT);
+ return ionic_adminq_check_err(lif, ctx, (remaining == 0));
+}
+
int ionic_napi(struct napi_struct *napi, int budget, ionic_cq_cb cb,
ionic_cq_done_cb done_cb, void *done_arg)
{
--
2.17.1
Powered by blists - more mailing lists