[RFC 2/6] qed: Add iSCSI out of order packet handling.

2016-10-18 Thread manish.rangankar
From: Yuval Mintz 

This patch adds out of order packet handling for hardware offloaded
iSCSI. Out of order packet handling requires driver buffer allocation
and assistance.

Signed-off-by: Arun Easi 
Signed-off-by: Yuval Mintz 
---
 drivers/net/ethernet/qlogic/qed/Makefile   |   2 +-
 drivers/net/ethernet/qlogic/qed/qed.h  |   1 +
 drivers/net/ethernet/qlogic/qed/qed_dev.c  |  14 +-
 drivers/net/ethernet/qlogic/qed/qed_ll2.c  | 559 +++--
 drivers/net/ethernet/qlogic/qed/qed_ll2.h  |   9 +
 drivers/net/ethernet/qlogic/qed/qed_ooo.c  | 510 ++
 drivers/net/ethernet/qlogic/qed/qed_ooo.h  | 116 ++
 drivers/net/ethernet/qlogic/qed/qed_roce.c |   1 +
 drivers/net/ethernet/qlogic/qed/qed_spq.c  |   9 +
 9 files changed, 1195 insertions(+), 26 deletions(-)
 create mode 100644 drivers/net/ethernet/qlogic/qed/qed_ooo.c
 create mode 100644 drivers/net/ethernet/qlogic/qed/qed_ooo.h

diff --git a/drivers/net/ethernet/qlogic/qed/Makefile 
b/drivers/net/ethernet/qlogic/qed/Makefile
index b76669c..9121bf0 100644
--- a/drivers/net/ethernet/qlogic/qed/Makefile
+++ b/drivers/net/ethernet/qlogic/qed/Makefile
@@ -6,4 +6,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o 
qed_init_ops.o \
 qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
 qed-$(CONFIG_QED_LL2) += qed_ll2.o
 qed-$(CONFIG_INFINIBAND_QEDR) += qed_roce.o
-qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o
+qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o qed_ooo.o
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index a61b1c0..e5626ae 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -380,6 +380,7 @@ struct qed_hwfn {
/* Protocol related */
boolusing_ll2;
struct qed_ll2_info *p_ll2_info;
+   struct qed_ooo_info *p_ooo_info;
struct qed_rdma_info*p_rdma_info;
struct qed_iscsi_info   *p_iscsi_info;
struct qed_pf_paramspf_params;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index a4234c0..060e9a4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -32,6 +32,7 @@
 #include "qed_iscsi.h"
 #include "qed_ll2.h"
 #include "qed_mcp.h"
+#include "qed_ooo.h"
 #include "qed_reg_addr.h"
 #include "qed_sp.h"
 #include "qed_sriov.h"
@@ -157,8 +158,10 @@ void qed_resc_free(struct qed_dev *cdev)
qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info);
 #endif
if (IS_ENABLED(CONFIG_QEDI) &&
-   p_hwfn->hw_info.personality == QED_PCI_ISCSI)
+   p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
qed_iscsi_free(p_hwfn, p_hwfn->p_iscsi_info);
+   qed_ooo_free(p_hwfn, p_hwfn->p_ooo_info);
+   }
qed_iov_free(p_hwfn);
qed_dmae_info_free(p_hwfn);
qed_dcbx_info_free(p_hwfn, p_hwfn->p_dcbx_info);
@@ -416,6 +419,7 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt 
*p_ptt)
 int qed_resc_alloc(struct qed_dev *cdev)
 {
struct qed_iscsi_info *p_iscsi_info;
+   struct qed_ooo_info *p_ooo_info;
 #ifdef CONFIG_QED_LL2
struct qed_ll2_info *p_ll2_info;
 #endif
@@ -543,6 +547,10 @@ int qed_resc_alloc(struct qed_dev *cdev)
if (!p_iscsi_info)
goto alloc_no_mem;
p_hwfn->p_iscsi_info = p_iscsi_info;
+   p_ooo_info = qed_ooo_alloc(p_hwfn);
+   if (!p_ooo_info)
+   goto alloc_no_mem;
+   p_hwfn->p_ooo_info = p_ooo_info;
}
 
/* DMA info initialization */
@@ -598,8 +606,10 @@ void qed_resc_setup(struct qed_dev *cdev)
qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info);
 #endif
if (IS_ENABLED(CONFIG_QEDI) &&
-   p_hwfn->hw_info.personality == QED_PCI_ISCSI)
+   p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
qed_iscsi_setup(p_hwfn, p_hwfn->p_iscsi_info);
+   qed_ooo_setup(p_hwfn, p_hwfn->p_ooo_info);
+   }
}
 }
 
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c 
b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index e67f3c9..4ce12e9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -36,6 +36,7 @@
 #include "qed_int.h"
 #include "qed_ll2.h"
 #include "qed_mcp.h"
+#include "qed_ooo.h"
 #include "qed_reg_addr.h"
 #include "qed_sp.h"
 
@@ -295,27 +296,36 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 
connection_handle)
list_del(&p_pkt->list_entry);
b_last_packet = list_empty(&p_tx->active_descq);

[RFC 3/6] qedi: Add QLogic FastLinQ offload iSCSI driver framework.

2016-10-18 Thread manish.rangankar
From: Manish Rangankar 

The QLogic FastLinQ Driver for iSCSI (qedi) is the iSCSI specific module
for 41000 Series Converged Network Adapters by QLogic.

This patch consists of following changes:
  - MAINTAINERS Makefile and Kconfig changes for qedi,
  - PCI driver registration,
  - iSCSI host level initialization,
  - Debugfs and log level infrastructure.

Signed-off-by: Nilesh Javali 
Signed-off-by: Adheer Chandravanshi 
Signed-off-by: Chad Dupuis 
Signed-off-by: Saurav Kashyap 
Signed-off-by: Arun Easi 
Signed-off-by: Manish Rangankar 
---
 MAINTAINERS |6 +
 drivers/net/ethernet/qlogic/Kconfig |   12 -
 drivers/scsi/Kconfig|1 +
 drivers/scsi/Makefile   |1 +
 drivers/scsi/qedi/Kconfig   |   10 +
 drivers/scsi/qedi/Makefile  |5 +
 drivers/scsi/qedi/qedi.h|  286 +++
 drivers/scsi/qedi/qedi_dbg.c|  143 
 drivers/scsi/qedi/qedi_dbg.h|  144 
 drivers/scsi/qedi/qedi_debugfs.c|  244 ++
 drivers/scsi/qedi/qedi_hsi.h|   52 ++
 drivers/scsi/qedi/qedi_main.c   | 1550 +++
 drivers/scsi/qedi/qedi_sysfs.c  |   52 ++
 drivers/scsi/qedi/qedi_version.h|   14 +
 14 files changed, 2508 insertions(+), 12 deletions(-)
 create mode 100644 drivers/scsi/qedi/Kconfig
 create mode 100644 drivers/scsi/qedi/Makefile
 create mode 100644 drivers/scsi/qedi/qedi.h
 create mode 100644 drivers/scsi/qedi/qedi_dbg.c
 create mode 100644 drivers/scsi/qedi/qedi_dbg.h
 create mode 100644 drivers/scsi/qedi/qedi_debugfs.c
 create mode 100644 drivers/scsi/qedi/qedi_hsi.h
 create mode 100644 drivers/scsi/qedi/qedi_main.c
 create mode 100644 drivers/scsi/qedi/qedi_sysfs.c
 create mode 100644 drivers/scsi/qedi/qedi_version.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5e925a2..906d05f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9909,6 +9909,12 @@ F:   drivers/net/ethernet/qlogic/qed/
 F: include/linux/qed/
 F: drivers/net/ethernet/qlogic/qede/
 
+QLOGIC QL41xxx ISCSI DRIVER
+M: qlogic-storage-upstr...@cavium.com
+L: linux-s...@vger.kernel.org
+S: Supported
+F: drivers/scsi/qedi/
+
 QNX4 FILESYSTEM
 M: Anders Larsen 
 W: http://www.alarsen.net/linux/qnx4fs/
diff --git a/drivers/net/ethernet/qlogic/Kconfig 
b/drivers/net/ethernet/qlogic/Kconfig
index bad4fae..28b4366 100644
--- a/drivers/net/ethernet/qlogic/Kconfig
+++ b/drivers/net/ethernet/qlogic/Kconfig
@@ -121,16 +121,4 @@ config INFINIBAND_QEDR
 config QED_ISCSI
bool
 
-config QEDI
-   tristate "QLogic QED 25/40/100Gb iSCSI driver"
-   depends on QED
-   select QED_LL2
-   select QED_ISCSI
-   default n
-   ---help---
- This provides a temporary node that allows the compilation
- and logical testing of the hardware offload iSCSI support
- for QLogic QED. This would be replaced by the 'real' option
- once the QEDI driver is added [+relocated].
-
 endif # NET_VENDOR_QLOGIC
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 3e2bdb9..5cf03db 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1254,6 +1254,7 @@ config SCSI_QLOGICPTI
 
 source "drivers/scsi/qla2xxx/Kconfig"
 source "drivers/scsi/qla4xxx/Kconfig"
+source "drivers/scsi/qedi/Kconfig"
 
 config SCSI_LPFC
tristate "Emulex LightPulse Fibre Channel Support"
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 38d938d..da9e312 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -132,6 +132,7 @@ obj-$(CONFIG_PS3_ROM)   += ps3rom.o
 obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/
 obj-$(CONFIG_SCSI_CXGB4_ISCSI) += libiscsi.o libiscsi_tcp.o cxgbi/
 obj-$(CONFIG_SCSI_BNX2_ISCSI)  += libiscsi.o bnx2i/
+obj-$(CONFIG_QEDI)  += libiscsi.o qedi/
 obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/
 obj-$(CONFIG_SCSI_ESAS2R)  += esas2r/
 obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o
diff --git a/drivers/scsi/qedi/Kconfig b/drivers/scsi/qedi/Kconfig
new file mode 100644
index 000..23ca8a2
--- /dev/null
+++ b/drivers/scsi/qedi/Kconfig
@@ -0,0 +1,10 @@
+config QEDI
+   tristate "QLogic QEDI 25/40/100Gb iSCSI Initiator Driver Support"
+   depends on PCI && SCSI
+   depends on QED
+   select SCSI_ISCSI_ATTRS
+   select QED_LL2
+   select QED_ISCSI
+   ---help---
+   This driver supports iSCSI offload for the QLogic FastLinQ
+   41000 Series Converged Network Adapters.
diff --git a/drivers/scsi/qedi/Makefile b/drivers/scsi/qedi/Makefile
new file mode 100644
index 000..2b3e16b
--- /dev/null
+++ b/drivers/scsi/qedi/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_QEDI) := qedi.o
+qedi-y := qedi_main.o qedi_iscsi.o qedi_fw.o qedi_sysfs.o \
+   qedi_dbg.o
+
+qedi-$(CONFIG_DEBUG_FS) += qedi_debugfs.o
diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h
new file mode 100644
index 000..0a5035e
--- /dev/null
+++ b/drivers/scs

[RFC 6/6] qedi: Add support for data path.

2016-10-18 Thread manish.rangankar
From: Manish Rangankar 

This patch adds support for data path and TMF handling.

Signed-off-by: Nilesh Javali 
Signed-off-by: Adheer Chandravanshi 
Signed-off-by: Chad Dupuis 
Signed-off-by: Saurav Kashyap 
Signed-off-by: Arun Easi 
Signed-off-by: Manish Rangankar 
---
 drivers/scsi/qedi/qedi_fw.c| 1282 
 drivers/scsi/qedi/qedi_gbl.h   |6 +
 drivers/scsi/qedi/qedi_iscsi.c |6 +
 drivers/scsi/qedi/qedi_main.c  |4 +
 4 files changed, 1298 insertions(+)

diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c
index a820785..af1e14d 100644
--- a/drivers/scsi/qedi/qedi_fw.c
+++ b/drivers/scsi/qedi/qedi_fw.c
@@ -147,6 +147,114 @@ static void qedi_process_text_resp(struct qedi_ctx *qedi,
spin_unlock(&session->back_lock);
 }
 
+static void qedi_tmf_resp_work(struct work_struct *work)
+{
+   struct qedi_cmd *qedi_cmd =
+   container_of(work, struct qedi_cmd, tmf_work);
+   struct qedi_conn *qedi_conn = qedi_cmd->conn;
+   struct qedi_ctx *qedi = qedi_conn->qedi;
+   struct iscsi_conn *conn = qedi_conn->cls_conn->dd_data;
+   struct iscsi_session *session = conn->session;
+   struct iscsi_tm_rsp *resp_hdr_ptr;
+   struct iscsi_cls_session *cls_sess;
+   int rval = 0;
+
+   set_bit(QEDI_CONN_FW_CLEANUP, &qedi_conn->flags);
+   resp_hdr_ptr =  (struct iscsi_tm_rsp *)qedi_cmd->tmf_resp_buf;
+   cls_sess = iscsi_conn_to_session(qedi_conn->cls_conn);
+
+   iscsi_block_session(session->cls_session);
+   rval = qedi_cleanup_all_io(qedi, qedi_conn, qedi_cmd->task, true);
+   if (rval) {
+   clear_bit(QEDI_CONN_FW_CLEANUP, &qedi_conn->flags);
+   qedi_clear_task_idx(qedi, qedi_cmd->task_id);
+   iscsi_unblock_session(session->cls_session);
+   return;
+   }
+
+   iscsi_unblock_session(session->cls_session);
+   qedi_clear_task_idx(qedi, qedi_cmd->task_id);
+
+   spin_lock(&session->back_lock);
+   __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, NULL, 0);
+   spin_unlock(&session->back_lock);
+   kfree(resp_hdr_ptr);
+   clear_bit(QEDI_CONN_FW_CLEANUP, &qedi_conn->flags);
+}
+
+static void qedi_process_tmf_resp(struct qedi_ctx *qedi,
+ union iscsi_cqe *cqe,
+ struct iscsi_task *task,
+ struct qedi_conn *qedi_conn)
+
+{
+   struct iscsi_conn *conn = qedi_conn->cls_conn->dd_data;
+   struct iscsi_session *session = conn->session;
+   struct iscsi_tmf_response_hdr *cqe_tmp_response;
+   struct iscsi_tm_rsp *resp_hdr_ptr;
+   struct iscsi_tm *tmf_hdr;
+   struct qedi_cmd *qedi_cmd = NULL;
+   u32 *tmp;
+
+   cqe_tmp_response = &cqe->cqe_common.iscsi_hdr.tmf_response;
+
+   qedi_cmd = task->dd_data;
+   qedi_cmd->tmf_resp_buf = kzalloc(sizeof(*resp_hdr_ptr), GFP_KERNEL);
+   if (!qedi_cmd->tmf_resp_buf) {
+   QEDI_ERR(&qedi->dbg_ctx,
+"Failed to allocate resp buf, cid=0x%x\n",
+ qedi_conn->iscsi_conn_id);
+   return;
+   }
+
+   spin_lock(&session->back_lock);
+   resp_hdr_ptr =  (struct iscsi_tm_rsp *)qedi_cmd->tmf_resp_buf;
+   memset(resp_hdr_ptr, 0, sizeof(struct iscsi_tm_rsp));
+
+   /* Fill up the header */
+   resp_hdr_ptr->opcode = cqe_tmp_response->opcode;
+   resp_hdr_ptr->flags = cqe_tmp_response->hdr_flags;
+   resp_hdr_ptr->response = cqe_tmp_response->hdr_response;
+   resp_hdr_ptr->hlength = 0;
+
+   hton24(resp_hdr_ptr->dlength,
+  (cqe_tmp_response->hdr_second_dword &
+   ISCSI_TMF_RESPONSE_HDR_DATA_SEG_LEN_MASK));
+   tmp = (u32 *)resp_hdr_ptr->dlength;
+   resp_hdr_ptr->itt = build_itt(cqe->cqe_solicited.itid,
+ conn->session->age);
+   resp_hdr_ptr->statsn = cpu_to_be32(cqe_tmp_response->stat_sn);
+   resp_hdr_ptr->exp_cmdsn  = cpu_to_be32(cqe_tmp_response->exp_cmd_sn);
+   resp_hdr_ptr->max_cmdsn = cpu_to_be32(cqe_tmp_response->max_cmd_sn);
+
+   tmf_hdr = (struct iscsi_tm *)qedi_cmd->task->hdr;
+
+   if (likely(qedi_cmd->io_cmd_in_list)) {
+   qedi_cmd->io_cmd_in_list = false;
+   list_del_init(&qedi_cmd->io_cmd);
+   qedi_conn->active_cmd_count--;
+   }
+
+   if (((tmf_hdr->flags & ISCSI_FLAG_TM_FUNC_MASK) ==
+ ISCSI_TM_FUNC_LOGICAL_UNIT_RESET) ||
+   ((tmf_hdr->flags & ISCSI_FLAG_TM_FUNC_MASK) ==
+ ISCSI_TM_FUNC_TARGET_WARM_RESET) ||
+   ((tmf_hdr->flags & ISCSI_FLAG_TM_FUNC_MASK) ==
+ ISCSI_TM_FUNC_TARGET_COLD_RESET)) {
+   INIT_WORK(&qedi_cmd->tmf_work, qedi_tmf_resp_work);
+   queue_work(qedi->tmf_thread, &qedi_cmd->tmf_work);
+   goto unblock_sess;
+   }
+
+   qedi_clear_task_idx(q

[RFC 5/6] qedi: Add support for iSCSI session management.

2016-10-18 Thread manish.rangankar
From: Manish Rangankar 

This patch adds support for iscsi_transport LLD Login,
Logout, NOP-IN/NOP-OUT, Async, Reject PDU processing
and Firmware async event handling support.

Signed-off-by: Nilesh Javali 
Signed-off-by: Adheer Chandravanshi 
Signed-off-by: Chad Dupuis 
Signed-off-by: Saurav Kashyap 
Signed-off-by: Arun Easi 
Signed-off-by: Manish Rangankar 
---
 drivers/scsi/qedi/qedi_fw.c| 1123 
 drivers/scsi/qedi/qedi_gbl.h   |   67 ++
 drivers/scsi/qedi/qedi_iscsi.c | 1604 
 drivers/scsi/qedi/qedi_iscsi.h |  228 ++
 drivers/scsi/qedi/qedi_main.c  |  164 
 5 files changed, 3186 insertions(+)
 create mode 100644 drivers/scsi/qedi/qedi_fw.c
 create mode 100644 drivers/scsi/qedi/qedi_gbl.h
 create mode 100644 drivers/scsi/qedi/qedi_iscsi.c
 create mode 100644 drivers/scsi/qedi/qedi_iscsi.h

diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c
new file mode 100644
index 000..a820785
--- /dev/null
+++ b/drivers/scsi/qedi/qedi_fw.c
@@ -0,0 +1,1123 @@
+/*
+ * QLogic iSCSI Offload Driver
+ * Copyright (c) 2016 Cavium Inc.
+ *
+ * This software is available under the terms of the GNU General Public License
+ * (GPL) Version 2, available from the file COPYING in the main directory of
+ * this source tree.
+ */
+
+#include 
+#include 
+#include 
+
+#include "qedi.h"
+#include "qedi_iscsi.h"
+#include "qedi_gbl.h"
+
+static int qedi_send_iscsi_tmf(struct qedi_conn *qedi_conn,
+  struct iscsi_task *mtask);
+
+void qedi_iscsi_unmap_sg_list(struct qedi_cmd *cmd)
+{
+   struct scsi_cmnd *sc = cmd->scsi_cmd;
+
+   if (cmd->io_tbl.sge_valid && sc) {
+   scsi_dma_unmap(sc);
+   cmd->io_tbl.sge_valid = 0;
+   }
+}
+
+static void qedi_process_logout_resp(struct qedi_ctx *qedi,
+union iscsi_cqe *cqe,
+struct iscsi_task *task,
+struct qedi_conn *qedi_conn)
+{
+   struct iscsi_conn *conn = qedi_conn->cls_conn->dd_data;
+   struct iscsi_logout_rsp *resp_hdr;
+   struct iscsi_session *session = conn->session;
+   struct iscsi_logout_response_hdr *cqe_logout_response;
+   struct qedi_cmd *cmd;
+
+   cmd = (struct qedi_cmd *)task->dd_data;
+   cqe_logout_response = &cqe->cqe_common.iscsi_hdr.logout_response;
+   spin_lock(&session->back_lock);
+   resp_hdr = (struct iscsi_logout_rsp *)&qedi_conn->gen_pdu.resp_hdr;
+   memset(resp_hdr, 0, sizeof(struct iscsi_hdr));
+   resp_hdr->opcode = cqe_logout_response->opcode;
+   resp_hdr->flags = cqe_logout_response->flags;
+   resp_hdr->hlength = 0;
+
+   resp_hdr->itt = build_itt(cqe->cqe_solicited.itid, conn->session->age);
+   resp_hdr->statsn = cpu_to_be32(cqe_logout_response->stat_sn);
+   resp_hdr->exp_cmdsn = cpu_to_be32(cqe_logout_response->exp_cmd_sn);
+   resp_hdr->max_cmdsn = cpu_to_be32(cqe_logout_response->max_cmd_sn);
+
+   resp_hdr->t2wait = cpu_to_be32(cqe_logout_response->time2wait);
+   resp_hdr->t2retain = cpu_to_be32(cqe_logout_response->time2retain);
+
+   QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_TID,
+ "Freeing tid=0x%x for cid=0x%x\n",
+ cmd->task_id, qedi_conn->iscsi_conn_id);
+
+   if (likely(cmd->io_cmd_in_list)) {
+   cmd->io_cmd_in_list = false;
+   list_del_init(&cmd->io_cmd);
+   qedi_conn->active_cmd_count--;
+   } else {
+   QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
+ "Active cmd list node already deleted, tid=0x%x, 
cid=0x%x, io_cmd_node=%p\n",
+ cmd->task_id, qedi_conn->iscsi_conn_id,
+ &cmd->io_cmd);
+   }
+
+   cmd->state = RESPONSE_RECEIVED;
+   qedi_clear_task_idx(qedi, cmd->task_id);
+   __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr, NULL, 0);
+
+   spin_unlock(&session->back_lock);
+}
+
+static void qedi_process_text_resp(struct qedi_ctx *qedi,
+  union iscsi_cqe *cqe,
+  struct iscsi_task *task,
+  struct qedi_conn *qedi_conn)
+{
+   struct iscsi_conn *conn = qedi_conn->cls_conn->dd_data;
+   struct iscsi_session *session = conn->session;
+   struct iscsi_task_context *task_ctx;
+   struct iscsi_text_rsp *resp_hdr_ptr;
+   struct iscsi_text_response_hdr *cqe_text_response;
+   struct qedi_cmd *cmd;
+   int pld_len;
+   u32 *tmp;
+
+   cmd = (struct qedi_cmd *)task->dd_data;
+   task_ctx = (struct iscsi_task_context *)qedi_get_task_mem(&qedi->tasks,
+ cmd->task_id);
+
+   cqe_text_response = &cqe->cqe_common.iscsi_hdr.text_response;
+   spin_lock(&session->back_lock);
+   resp_hdr_ptr =  (struct iscsi_text_rsp *)&q

[RFC 1/6] qed: Add support for hardware offloaded iSCSI.

2016-10-18 Thread manish.rangankar
From: Yuval Mintz 

This adds the backbone required for the various HW initalizations
which are necessary for the iSCSI driver (qedi) for QLogic FastLinQ
4 line of adapters - FW notification, resource initializations, etc.

Signed-off-by: Arun Easi 
Signed-off-by: Yuval Mintz 
---
 drivers/net/ethernet/qlogic/Kconfig|   15 +
 drivers/net/ethernet/qlogic/qed/Makefile   |1 +
 drivers/net/ethernet/qlogic/qed/qed.h  |8 +-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  |   15 +
 drivers/net/ethernet/qlogic/qed/qed_int.h  |1 -
 drivers/net/ethernet/qlogic/qed/qed_iscsi.c| 1310 
 drivers/net/ethernet/qlogic/qed/qed_iscsi.h|   52 +
 drivers/net/ethernet/qlogic/qed/qed_l2.c   |1 -
 drivers/net/ethernet/qlogic/qed/qed_ll2.c  |   35 +-
 drivers/net/ethernet/qlogic/qed/qed_main.c |2 -
 drivers/net/ethernet/qlogic/qed/qed_mcp.h  |6 -
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |2 +
 drivers/net/ethernet/qlogic/qed/qed_spq.c  |   15 +
 include/linux/qed/qed_if.h |2 +
 include/linux/qed/qed_iscsi_if.h   |  249 +
 15 files changed, 1692 insertions(+), 22 deletions(-)
 create mode 100644 drivers/net/ethernet/qlogic/qed/qed_iscsi.c
 create mode 100644 drivers/net/ethernet/qlogic/qed/qed_iscsi.h
 create mode 100644 include/linux/qed/qed_iscsi_if.h

diff --git a/drivers/net/ethernet/qlogic/Kconfig 
b/drivers/net/ethernet/qlogic/Kconfig
index 0df1391f9..bad4fae 100644
--- a/drivers/net/ethernet/qlogic/Kconfig
+++ b/drivers/net/ethernet/qlogic/Kconfig
@@ -118,4 +118,19 @@ config INFINIBAND_QEDR
  for QLogic QED. This would be replaced by the 'real' option
  once the QEDR driver is added [+relocated].
 
+config QED_ISCSI
+   bool
+
+config QEDI
+   tristate "QLogic QED 25/40/100Gb iSCSI driver"
+   depends on QED
+   select QED_LL2
+   select QED_ISCSI
+   default n
+   ---help---
+ This provides a temporary node that allows the compilation
+ and logical testing of the hardware offload iSCSI support
+ for QLogic QED. This would be replaced by the 'real' option
+ once the QEDI driver is added [+relocated].
+
 endif # NET_VENDOR_QLOGIC
diff --git a/drivers/net/ethernet/qlogic/qed/Makefile 
b/drivers/net/ethernet/qlogic/qed/Makefile
index cda0af7..b76669c 100644
--- a/drivers/net/ethernet/qlogic/qed/Makefile
+++ b/drivers/net/ethernet/qlogic/qed/Makefile
@@ -6,3 +6,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o 
qed_init_ops.o \
 qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
 qed-$(CONFIG_QED_LL2) += qed_ll2.o
 qed-$(CONFIG_INFINIBAND_QEDR) += qed_roce.o
+qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h 
b/drivers/net/ethernet/qlogic/qed/qed.h
index 653bb57..a61b1c0 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -35,6 +35,7 @@
 
 #define QED_WFQ_UNIT   100
 
+#define ISCSI_BDQ_ID(_port_id) (_port_id)
 #define QED_WID_SIZE(1024)
 #define QED_PF_DEMS_SIZE(4)
 
@@ -167,6 +168,7 @@ enum QED_RESOURCES {
QED_ILT,
QED_LL2_QUEUE,
QED_RDMA_STATS_QUEUE,
+   QED_CMDQS_CQS,
QED_MAX_RESC,
 };
 
@@ -379,6 +381,7 @@ struct qed_hwfn {
boolusing_ll2;
struct qed_ll2_info *p_ll2_info;
struct qed_rdma_info*p_rdma_info;
+   struct qed_iscsi_info   *p_iscsi_info;
struct qed_pf_paramspf_params;
 
bool b_rdma_enabled_in_prs;
@@ -578,6 +581,8 @@ struct qed_dev {
/* Linux specific here */
struct  qede_dev*edev;
struct  pci_dev *pdev;
+   u32 flags;
+#define QED_FLAG_STORAGE_STARTED   (BIT(0))
int msg_enable;
 
struct pci_params   pci_params;
@@ -591,6 +596,7 @@ struct qed_dev {
union {
struct qed_common_cb_ops*common;
struct qed_eth_cb_ops   *eth;
+   struct qed_iscsi_cb_ops *iscsi;
} protocol_ops;
void*ops_cookie;
 
@@ -600,7 +606,7 @@ struct qed_dev {
struct qed_cb_ll2_info  *ll2;
u8  ll2_mac_address[ETH_ALEN];
 #endif
-
+   DECLARE_HASHTABLE(connections, 10);
const struct firmware   *firmware;
 
u32 rdma_max_sge;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c 
b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 754f6a9..a4234c0 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -29,6 +29,7 @@
 #include "qed_hw.h"
 #include "qed_init_ops.h"
 #include "qed_int.h"
+#include "qed_iscsi.h"
 #include "qed_ll2.h"
 #include "qed_mcp.h"
 #include "qed_reg_addr.h"
@@ -155,6 +156,9 @@ v

[RFC 0/6] Add QLogic FastLinQ iSCSI (qedi) driver.

2016-10-18 Thread manish.rangankar
From: Manish Rangankar 

This series introduces hardware offload iSCSI initiator driver for the
41000 Series Converged Network Adapters (579xx chip) by Qlogic. The overall
driver design includes a common module ('qed') and protocol specific
dependent modules ('qedi' for iSCSI).

This is an open iSCSI driver, modifications to open iSCSI user components
'iscsid', 'iscsiuio', etc. are required for the solution to work. The user
space changes are also in the process of being submitted.

https://groups.google.com/forum/#!forum/open-iscsi

The 'qed' common module, under drivers/net/ethernet/qlogic/qed/, is
enhanced with functionality required for the iSCSI support. This series
is based on:

net-next: 1b830996c1603225a96e233c3b09bf2b12607d78

qedi patches are divided logically for review purpose and individual
patches do not compile.

We really appreciate any review comments you may have on the patch series.

Manish Rangankar (4):
  qedi: Add QLogic FastLinQ offload iSCSI driver framework.
  qedi: Add LL2 iSCSI interface for offload iSCSI.
  qedi: Add support for iSCSI session management.
  qedi: Add support for data path.

Yuval Mintz (2):
  qed: Add support for hardware offloaded iSCSI.
  qed: Add iSCSI out of order packet handling.

 MAINTAINERS|6 +
 drivers/net/ethernet/qlogic/Kconfig|3 +
 drivers/net/ethernet/qlogic/qed/Makefile   |1 +
 drivers/net/ethernet/qlogic/qed/qed.h  |9 +-
 drivers/net/ethernet/qlogic/qed/qed_dev.c  |   25 +
 drivers/net/ethernet/qlogic/qed/qed_int.h  |1 -
 drivers/net/ethernet/qlogic/qed/qed_iscsi.c| 1310 +
 drivers/net/ethernet/qlogic/qed/qed_iscsi.h|   52 +
 drivers/net/ethernet/qlogic/qed/qed_l2.c   |1 -
 drivers/net/ethernet/qlogic/qed/qed_ll2.c  |  594 +-
 drivers/net/ethernet/qlogic/qed/qed_ll2.h  |9 +
 drivers/net/ethernet/qlogic/qed/qed_main.c |2 -
 drivers/net/ethernet/qlogic/qed/qed_mcp.h  |6 -
 drivers/net/ethernet/qlogic/qed/qed_ooo.c  |  510 +
 drivers/net/ethernet/qlogic/qed/qed_ooo.h  |  116 ++
 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h |2 +
 drivers/net/ethernet/qlogic/qed/qed_roce.c |1 +
 drivers/net/ethernet/qlogic/qed/qed_spq.c  |   24 +
 drivers/scsi/Kconfig   |1 +
 drivers/scsi/Makefile  |1 +
 drivers/scsi/qedi/Kconfig  |   10 +
 drivers/scsi/qedi/Makefile |5 +
 drivers/scsi/qedi/qedi.h   |  359 
 drivers/scsi/qedi/qedi_dbg.c   |  143 ++
 drivers/scsi/qedi/qedi_dbg.h   |  144 ++
 drivers/scsi/qedi/qedi_debugfs.c   |  244 +++
 drivers/scsi/qedi/qedi_fw.c| 2405 
 drivers/scsi/qedi/qedi_gbl.h   |   73 +
 drivers/scsi/qedi/qedi_hsi.h   |   52 +
 drivers/scsi/qedi/qedi_iscsi.c | 1610 
 drivers/scsi/qedi/qedi_iscsi.h |  228 +++
 drivers/scsi/qedi/qedi_main.c  | 2075 
 drivers/scsi/qedi/qedi_sysfs.c |   52 +
 drivers/scsi/qedi/qedi_version.h   |   14 +
 include/linux/qed/qed_if.h |2 +
 include/linux/qed/qed_iscsi_if.h   |  249 +++
 36 files changed, 10294 insertions(+), 45 deletions(-)
 create mode 100644 drivers/net/ethernet/qlogic/qed/qed_iscsi.c
 create mode 100644 drivers/net/ethernet/qlogic/qed/qed_iscsi.h
 create mode 100644 drivers/net/ethernet/qlogic/qed/qed_ooo.c
 create mode 100644 drivers/net/ethernet/qlogic/qed/qed_ooo.h
 create mode 100644 drivers/scsi/qedi/Kconfig
 create mode 100644 drivers/scsi/qedi/Makefile
 create mode 100644 drivers/scsi/qedi/qedi.h
 create mode 100644 drivers/scsi/qedi/qedi_dbg.c
 create mode 100644 drivers/scsi/qedi/qedi_dbg.h
 create mode 100644 drivers/scsi/qedi/qedi_debugfs.c
 create mode 100644 drivers/scsi/qedi/qedi_fw.c
 create mode 100644 drivers/scsi/qedi/qedi_gbl.h
 create mode 100644 drivers/scsi/qedi/qedi_hsi.h
 create mode 100644 drivers/scsi/qedi/qedi_iscsi.c
 create mode 100644 drivers/scsi/qedi/qedi_iscsi.h
 create mode 100644 drivers/scsi/qedi/qedi_main.c
 create mode 100644 drivers/scsi/qedi/qedi_sysfs.c
 create mode 100644 drivers/scsi/qedi/qedi_version.h
 create mode 100644 include/linux/qed/qed_iscsi_if.h

-- 
1.8.3.1



[RFC 4/6] qedi: Add LL2 iSCSI interface for offload iSCSI.

2016-10-18 Thread manish.rangankar
From: Manish Rangankar 

This patch adds support for iscsiuio interface using Light L2 (LL2) qed
interface.

Signed-off-by: Nilesh Javali 
Signed-off-by: Adheer Chandravanshi 
Signed-off-by: Chad Dupuis 
Signed-off-by: Saurav Kashyap 
Signed-off-by: Arun Easi 
Signed-off-by: Manish Rangankar 
---
 drivers/scsi/qedi/qedi.h  |  73 +
 drivers/scsi/qedi/qedi_main.c | 357 ++
 2 files changed, 430 insertions(+)

diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h
index 0a5035e..02fefbd 100644
--- a/drivers/scsi/qedi/qedi.h
+++ b/drivers/scsi/qedi/qedi.h
@@ -21,6 +21,7 @@
 #include 
 #include "qedi_dbg.h"
 #include 
+#include 
 #include "qedi_version.h"
 
 #define QEDI_MODULE_NAME   "qedi"
@@ -54,6 +55,78 @@
 #define QEDI_LOCAL_PORT_MAX 61024
 #define QEDI_LOCAL_PORT_RANGE   (QEDI_LOCAL_PORT_MAX - QEDI_LOCAL_PORT_MIN)
 #define QEDI_LOCAL_PORT_INVALID0x
+#define TX_RX_RING 16
+#define RX_RING(TX_RX_RING - 1)
+#define LL2_SINGLE_BUF_SIZE0x400
+#define QEDI_PAGE_SIZE 4096
+#define QEDI_PAGE_ALIGN(addr)  ALIGN(addr, QEDI_PAGE_SIZE)
+#define QEDI_PAGE_MASK (~((QEDI_PAGE_SIZE) - 1))
+
+#define QEDI_PAGE_SIZE 4096
+#define QEDI_PATH_HANDLE   0xFE000UL
+
+struct qedi_uio_ctrl {
+   /* meta data */
+   u32 uio_hsi_version;
+
+   /* user writes */
+   u32 host_tx_prod;
+   u32 host_rx_cons;
+   u32 host_rx_bd_cons;
+   u32 host_tx_pkt_len;
+   u32 host_rx_cons_cnt;
+
+   /* driver writes */
+   u32 hw_tx_cons;
+   u32 hw_rx_prod;
+   u32 hw_rx_bd_prod;
+   u32 hw_rx_prod_cnt;
+
+   /* other */
+   u8 mac_addr[6];
+   u8 reserve[2];
+};
+
+struct qedi_rx_bd {
+   u32 rx_pkt_index;
+   u32 rx_pkt_len;
+   u16 vlan_id;
+};
+
+#define QEDI_RX_DESC_CNT   (QEDI_PAGE_SIZE / sizeof(struct qedi_rx_bd))
+#define QEDI_MAX_RX_DESC_CNT   (QEDI_RX_DESC_CNT - 1)
+#define QEDI_NUM_RX_BD (QEDI_RX_DESC_CNT * 1)
+#define QEDI_MAX_RX_BD (QEDI_NUM_RX_BD - 1)
+
+#define QEDI_NEXT_RX_IDX(x)x) & (QEDI_MAX_RX_DESC_CNT)) == \
+ (QEDI_MAX_RX_DESC_CNT - 1)) ? \
+(x) + 2 : (x) + 1)
+
+struct qedi_uio_dev {
+   struct uio_info qedi_uinfo;
+   u32 uio_dev;
+   struct list_headlist;
+
+   u32 ll2_ring_size;
+   void*ll2_ring;
+
+   u32 ll2_buf_size;
+   void*ll2_buf;
+
+   void*rx_pkt;
+   void*tx_pkt;
+
+   struct qedi_ctx *qedi;
+   struct pci_dev  *pdev;
+   void*uctrl;
+};
+
+/* List to maintain the skb pointers */
+struct skb_work_list {
+   struct list_head list;
+   struct sk_buff *skb;
+   u16 vlan_id;
+};
 
 /* Queue sizes in number of elements */
 #define QEDI_SQ_SIZE   MAX_OUSTANDING_TASKS_PER_CON
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index 35ab2f9..58ac9a2 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -45,9 +45,12 @@
 static struct scsi_transport_template *qedi_scsi_transport;
 static struct pci_driver qedi_pci_driver;
 static DEFINE_PER_CPU(struct qedi_percpu_s, qedi_percpu);
+static LIST_HEAD(qedi_udev_list);
 /* Static function declaration */
 static int qedi_alloc_global_queues(struct qedi_ctx *qedi);
 static void qedi_free_global_queues(struct qedi_ctx *qedi);
+static void qedi_reset_uio_rings(struct qedi_uio_dev *udev);
+static void qedi_ll2_free_skbs(struct qedi_ctx *qedi);
 
 static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void 
*fw_handle)
 {
@@ -112,6 +115,224 @@ static int qedi_iscsi_event_cb(void *context, u8 
fw_event_code, void *fw_handle)
return rval;
 }
 
+static int qedi_uio_open(struct uio_info *uinfo, struct inode *inode)
+{
+   struct qedi_uio_dev *udev = uinfo->priv;
+   struct qedi_ctx *qedi = udev->qedi;
+
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
+   if (udev->uio_dev != -1)
+   return -EBUSY;
+
+   rtnl_lock();
+   udev->uio_dev = iminor(inode);
+   qedi_reset_uio_rings(udev);
+   set_bit(UIO_DEV_OPENED, &qedi->flags);
+   rtnl_unlock();
+
+   return 0;
+}
+
+static int qedi_uio_close(struct uio_info *uinfo, struct inode *inode)
+{
+   struct qedi_uio_dev *udev = uinfo->priv;
+   struct qedi_ctx *qedi = udev->qedi;
+
+   udev->uio_dev = -1;
+   clear_bit(UIO_DEV_OPENED, &qedi->flags);
+   qedi_ll2_free_skbs(qedi);
+   return 0;
+}
+
+static void __qedi_free_uio_rings(struct qedi_uio_dev *udev)
+{
+   if (udev->ll2_ring) {
+   free_page((unsigned long)udev->ll2_ring);
+   udev->ll2_ring = NULL;
+   }