--- v5
+++ v7
@@ -27,10 +27,10 @@
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
drivers/nvme/hw/qedn/Makefile | 5 +-
- drivers/nvme/hw/qedn/qedn.h | 174 ++++++++++
- drivers/nvme/hw/qedn/qedn_conn.c | 536 +++++++++++++++++++++++++++++++
- drivers/nvme/hw/qedn/qedn_main.c | 168 +++++++++-
- 4 files changed, 871 insertions(+), 12 deletions(-)
+ drivers/nvme/hw/qedn/qedn.h | 178 ++++++++++
+ drivers/nvme/hw/qedn/qedn_conn.c | 552 +++++++++++++++++++++++++++++++
+ drivers/nvme/hw/qedn/qedn_main.c | 208 +++++++++++-
+ 4 files changed, 933 insertions(+), 10 deletions(-)
create mode 100644 drivers/nvme/hw/qedn/qedn_conn.c
diff --git a/drivers/nvme/hw/qedn/Makefile b/drivers/nvme/hw/qedn/Makefile
@@ -46,7 +46,7 @@
+obj-$(CONFIG_NVME_QEDN) += qedn.o
+qedn-y := qedn_main.o qedn_conn.o
diff --git a/drivers/nvme/hw/qedn/qedn.h b/drivers/nvme/hw/qedn/qedn.h
-index 4d70c34bcb0b..ac1880d1bde9 100644
+index edb0836bca87..0b1bd1ae2b0b 100644
--- a/drivers/nvme/hw/qedn/qedn.h
+++ b/drivers/nvme/hw/qedn/qedn.h
@@ -6,6 +6,7 @@
@@ -57,7 +57,7 @@
#include <linux/qed/qed_if.h>
#include <linux/qed/qed_nvmetcp_if.h>
#include <linux/qed/qed_nvmetcp_ip_services_if.h>
-@@ -37,7 +38,41 @@
+@@ -28,7 +29,41 @@
#define QEDN_IRQ_NAME_LEN 24
#define QEDN_IRQ_NO_FLAGS 0
@@ -81,7 +81,7 @@
+#define QEDN_TCP_KA_TIMEOUT 7200000
+#define QEDN_TCP_KA_INTERVAL 10000
+#define QEDN_TCP_KA_MAX_PROBE_COUNT 10
-+#define QEDN_TCP_MAX_RT_TIME 1200
++#define QEDN_TCP_MAX_RT_TIME 30000
+#define QEDN_TCP_MAX_CWND 4
+#define QEDN_TCP_RCV_WND_SCALE 2
+#define QEDN_TCP_TS_OPTION_LEN 12
@@ -99,7 +99,7 @@
enum qedn_state {
QEDN_STATE_CORE_PROBED = 0,
-@@ -73,6 +108,12 @@ struct qedn_ctx {
+@@ -64,6 +99,12 @@ struct qedn_ctx {
/* Accessed with atomic bit ops, used with enum qedn_state */
unsigned long state;
@@ -112,7 +112,7 @@
/* Fast path queues */
u8 num_fw_cqs;
struct qedn_fp_queue *fp_q_arr;
-@@ -80,4 +121,137 @@ struct qedn_ctx {
+@@ -71,4 +112,141 @@ struct qedn_ctx {
dma_addr_t fw_cq_array_phy; /* Physical address of fw_cq_array_virt */
};
@@ -177,6 +177,9 @@
+ struct nvme_tcp_ofld_queue *queue;
+ struct nvme_tcp_ofld_ctrl *ctrl;
+
++ struct sockaddr remote_mac_addr;
++ u16 vlan_id;
++
+ struct workqueue_struct *sp_wq;
+ enum qedn_ctrl_sp_wq_state sp_wq_state;
+
@@ -244,18 +247,19 @@
+void qedn_set_sp_wa(struct qedn_conn_ctx *conn_ctx, u32 bit);
+void qedn_clr_sp_wa(struct qedn_conn_ctx *conn_ctx, u32 bit);
+int qedn_initialize_endpoint(struct qedn_endpoint *ep, u8 *local_mac_addr,
-+ struct nvme_tcp_ofld_ctrl_con_params *conn_params);
++ struct nvme_tcp_ofld_ctrl *ctrl);
+int qedn_wait_for_conn_est(struct qedn_conn_ctx *conn_ctx);
+int qedn_set_con_state(struct qedn_conn_ctx *conn_ctx, enum qedn_conn_state new_state);
+void qedn_terminate_connection(struct qedn_conn_ctx *conn_ctx);
++void qedn_cleanp_fw(struct qedn_conn_ctx *conn_ctx);
+
#endif /* _QEDN_H_ */
diff --git a/drivers/nvme/hw/qedn/qedn_conn.c b/drivers/nvme/hw/qedn/qedn_conn.c
new file mode 100644
-index 000000000000..ad90b09f9a67
+index 000000000000..c780c97b6d8a
--- /dev/null
+++ b/drivers/nvme/hw/qedn/qedn_conn.c
-@@ -0,0 +1,536 @@
+@@ -0,0 +1,552 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 Marvell. All rights reserved.
@@ -369,11 +373,18 @@
+}
+
+int qedn_initialize_endpoint(struct qedn_endpoint *ep, u8 *local_mac_addr,
-+ struct nvme_tcp_ofld_ctrl_con_params *conn_params)
-+{
-+ ether_addr_copy(ep->dst_mac, conn_params->remote_mac_addr.sa_data);
++ struct nvme_tcp_ofld_ctrl *ctrl)
++{
++ struct nvme_tcp_ofld_ctrl_con_params *conn_params = &ctrl->conn_params;
++ struct qedn_ctrl *qctrl;
++
++ qctrl = (struct qedn_ctrl *)ctrl->private_data;
++ if (!qctrl)
++ return -ENODEV;
++
++ ether_addr_copy(ep->dst_mac, qctrl->remote_mac_addr.sa_data);
+ ether_addr_copy(ep->src_mac, local_mac_addr);
-+ ep->vlan_id = conn_params->vlan_id;
++ ep->vlan_id = qctrl->vlan_id;
+ if (conn_params->remote_ip_addr.ss_family == AF_INET)
+ qedn_fill_ep_addr4(ep, conn_params);
+ else
@@ -533,6 +544,8 @@
+
+ ctrl = conn_ctx->ctrl;
+ qctrl = (struct qedn_ctrl *)ctrl->private_data;
++ if (!qctrl)
++ return -ENODEV;
+
+ rc = qed_fetch_tcp_port(ctrl->conn_params.local_ip_addr,
+ &conn_ctx->sock, &conn_ctx->ep.src_port);
@@ -556,6 +569,8 @@
+ return;
+
+ qctrl = (struct qedn_ctrl *)conn_ctx->ctrl->private_data;
++ if (!qctrl)
++ return;
+
+ if (test_and_set_bit(DESTROY_CONNECTION, &conn_ctx->agg_work_action))
+ return;
@@ -606,6 +621,8 @@
+
+ ctrl = conn_ctx->ctrl;
+ qctrl = (struct qedn_ctrl *)ctrl->private_data;
++ if (!qctrl)
++ return -ENODEV;
+
+ switch (fw_event_code) {
+ case NVMETCP_EVENT_TYPE_ASYN_CONNECT_COMPLETE:
@@ -724,6 +741,11 @@
+ return -EINVAL;
+}
+
++void qedn_cleanp_fw(struct qedn_conn_ctx *conn_ctx)
++{
++ /* Placeholder - task cleanup */
++}
++
+void qedn_destroy_connection(struct qedn_conn_ctx *conn_ctx)
+{
+ struct qedn_ctx *qedn = conn_ctx->qedn;
@@ -733,8 +755,6 @@
+
+ if (qedn_set_con_state(conn_ctx, CONN_STATE_WAIT_FOR_DESTROY_DONE))
+ return;
-+
-+ /* Placeholder - task cleanup */
+
+ rc = qed_ops->destroy_conn(qedn->cdev, conn_ctx->conn_handle,
+ conn_ctx->abrt_flag);
@@ -793,10 +813,10 @@
+ set_bit(bit, &conn_ctx->agg_work_action);
+}
diff --git a/drivers/nvme/hw/qedn/qedn_main.c b/drivers/nvme/hw/qedn/qedn_main.c
-index b3a9022bf643..f132c049601f 100644
+index 21819c045b01..2e82f3ef62f5 100644
--- a/drivers/nvme/hw/qedn/qedn_main.c
+++ b/drivers/nvme/hw/qedn/qedn_main.c
-@@ -22,12 +22,22 @@ static struct pci_device_id qedn_pci_tbl[] = {
+@@ -22,6 +22,15 @@ static struct pci_device_id qedn_pci_tbl[] = {
{0, 0},
};
@@ -810,20 +830,36 @@
+}
+
static int
- qedn_claim_dev(struct nvme_tcp_ofld_dev *dev,
- struct nvme_tcp_ofld_ctrl_con_params *conn_params)
- {
+ qedn_find_dev(struct nvme_tcp_ofld_dev *dev,
+ struct nvme_tcp_ofld_ctrl *ctrl)
+@@ -29,7 +38,9 @@ qedn_find_dev(struct nvme_tcp_ofld_dev *dev,
+ struct nvme_tcp_ofld_ctrl_con_params *conn_params;
struct pci_dev *qede_pdev = NULL;
+ struct sockaddr remote_mac_addr;
++ struct qedn_ctrl *qctrl = NULL;
struct net_device *ndev = NULL;
+ struct qedn_ctx *qedn = NULL;
u16 vlan_id = 0;
int rc = 0;
-@@ -65,39 +75,164 @@ qedn_claim_dev(struct nvme_tcp_ofld_dev *dev,
+@@ -59,6 +70,12 @@ qedn_find_dev(struct nvme_tcp_ofld_dev *dev,
+
+ qed_vlan_get_ndev(&ndev, &vlan_id);
+
++ qctrl = (struct qedn_ctrl *)ctrl->private_data;
++ if (qctrl) {
++ qctrl->remote_mac_addr = remote_mac_addr;
++ qctrl->vlan_id = vlan_id;
++ }
++
+ dev->ndev = ndev;
+
+ /* route found through ndev - validate this is qede*/
+@@ -66,6 +83,13 @@ qedn_find_dev(struct nvme_tcp_ofld_dev *dev,
if (!qede_pdev)
return false;
-+ qedn = (struct qedn_ctx *)dev->private_data;
++ qedn = container_of(dev, struct qedn_ctx, qedn_ofld_dev);
+ if (!qedn)
+ return false;
+
@@ -833,13 +869,21 @@
return true;
}
- static int qedn_setup_ctrl(struct nvme_tcp_ofld_ctrl *ctrl, bool new)
+@@ -78,14 +102,71 @@ qedn_claim_dev(struct nvme_tcp_ofld_dev *dev,
+
+ static int qedn_setup_ctrl(struct nvme_tcp_ofld_ctrl *ctrl)
{
- /* Placeholder - qedn_setup_ctrl */
+ struct nvme_tcp_ofld_dev *dev = ctrl->dev;
+ struct qedn_ctrl *qctrl = NULL;
+ struct qedn_ctx *qedn = NULL;
++ bool new = true;
+ int rc = 0;
++
++ if (ctrl->private_data) {
++ qctrl = (struct qedn_ctrl *)ctrl->private_data;
++ new = false;
++ }
+
+ if (new) {
+ qctrl = kzalloc(sizeof(*qctrl), GFP_KERNEL);
@@ -862,18 +906,32 @@
+ set_bit(QEDN_STATE_SP_WORK_THREAD_SET, &qctrl->agg_state);
+ }
+
-+ qedn = (struct qedn_ctx *)dev->private_data;
++ if (!qedn_find_dev(dev, ctrl)) {
++ rc = -ENODEV;
++ goto err_out;
++ }
++
++ qedn = container_of(dev, struct qedn_ctx, qedn_ofld_dev);
+ qctrl->qedn = qedn;
+
+ /* Placeholder - setup LLH filter */
return 0;
++err_out:
++ flush_workqueue(qctrl->sp_wq);
++ kfree(qctrl);
++
++ return rc;
}
static int qedn_release_ctrl(struct nvme_tcp_ofld_ctrl *ctrl)
{
- /* Placeholder - qedn_release_ctrl */
-+ struct qedn_ctrl *qctrl = (struct qedn_ctrl *)ctrl->private_data;
++ struct qedn_ctrl *qctrl;
++
++ qctrl = (struct qedn_ctrl *)ctrl->private_data;
++ if (!qctrl)
++ return -ENODEV;
+
+ if (test_and_clear_bit(QEDN_STATE_SP_WORK_THREAD_SET, &qctrl->agg_state))
+ flush_workqueue(qctrl->sp_wq);
@@ -882,25 +940,25 @@
+ kfree(qctrl);
+ ctrl->private_data = NULL;
+ }
-+
-+ qctrl->agg_state = 0;
-+ kfree(ctrl);
return 0;
}
-
--static int qedn_create_queue(struct nvme_tcp_ofld_queue *queue, int qid,
-- size_t q_size)
-+static int qedn_create_queue(struct nvme_tcp_ofld_queue *queue, int qid, size_t q_size)
+@@ -93,19 +174,117 @@ static int qedn_release_ctrl(struct nvme_tcp_ofld_ctrl *ctrl)
+ static int qedn_create_queue(struct nvme_tcp_ofld_queue *queue, int qid,
+ size_t queue_size)
{
- /* Placeholder - qedn_create_queue */
+ struct nvme_tcp_ofld_ctrl *ctrl = queue->ctrl;
++ struct nvme_ctrl *nctrl = &ctrl->nctrl;
+ struct qedn_conn_ctx *conn_ctx;
+ struct qedn_ctrl *qctrl;
+ struct qedn_ctx *qedn;
+ int rc;
+
+ qctrl = (struct qedn_ctrl *)ctrl->private_data;
++ if (!qctrl)
++ return -ENODEV;
++
+ qedn = qctrl->qedn;
+
+ /* Allocate qedn connection context */
@@ -909,10 +967,14 @@
+ return -ENOMEM;
+
+ queue->private_data = conn_ctx;
++ queue->hdr_digest = nctrl->opts->hdr_digest;
++ queue->data_digest = nctrl->opts->data_digest;
++ queue->tos = nctrl->opts->tos;
++
+ conn_ctx->qedn = qedn;
+ conn_ctx->queue = queue;
+ conn_ctx->ctrl = ctrl;
-+ conn_ctx->sq_depth = q_size;
++ conn_ctx->sq_depth = queue_size;
+
+ init_waitqueue_head(&conn_ctx->conn_waitq);
+ atomic_set(&conn_ctx->est_conn_indicator, 0);
@@ -920,8 +982,7 @@
+
+ spin_lock_init(&conn_ctx->conn_state_lock);
+
-+ qedn_initialize_endpoint(&conn_ctx->ep, qedn->local_mac_addr,
-+ &ctrl->conn_params);
++ qedn_initialize_endpoint(&conn_ctx->ep, qedn->local_mac_addr, ctrl);
+
+ atomic_inc(&qctrl->host_num_active_conns);
+
@@ -943,7 +1004,19 @@
static void qedn_drain_queue(struct nvme_tcp_ofld_queue *queue)
{
- /* Placeholder - qedn_drain_queue */
-+ /* No queue drain is required */
++ struct qedn_conn_ctx *conn_ctx;
++
++ if (!queue) {
++ pr_err("ctrl has no queues\n");
++
++ return;
++ }
++
++ conn_ctx = (struct qedn_conn_ctx *)queue->private_data;
++ if (!conn_ctx)
++ return;
++
++ qedn_cleanp_fw(conn_ctx);
+}
+
+#define ATOMIC_READ_DESTROY_IND atomic_read(&conn_ctx->destroy_conn_indicator)
@@ -991,8 +1064,8 @@
}
static int qedn_poll_queue(struct nvme_tcp_ofld_queue *queue)
-@@ -155,6 +290,21 @@ static struct nvme_tcp_ofld_ops qedn_ofld_ops = {
- .commit_rqs = qedn_commit_rqs,
+@@ -146,6 +325,21 @@ static struct nvme_tcp_ofld_ops qedn_ofld_ops = {
+ .send_req = qedn_send_req,
};
+struct qedn_conn_ctx *qedn_get_conn_hash(struct qedn_ctx *qedn, u16 icid)
@@ -1013,7 +1086,7 @@
/* Fastpath IRQ handler */
static irqreturn_t qedn_irq_handler(int irq, void *dev_id)
{
-@@ -255,7 +405,7 @@ static int qedn_setup_irq(struct qedn_ctx *qedn)
+@@ -246,7 +440,7 @@ static int qedn_setup_irq(struct qedn_ctx *qedn)
static inline void qedn_init_pf_struct(struct qedn_ctx *qedn)
{
@@ -1022,7 +1095,7 @@
}
static inline void
-@@ -599,7 +749,7 @@ static int __qedn_probe(struct pci_dev *pdev)
+@@ -586,7 +780,7 @@ static int __qedn_probe(struct pci_dev *pdev)
rc = qed_ops->start(qedn->cdev,
NULL /* Placeholder for FW IO-path resources */,
qedn,