Re: [Open-FCoE] [PATCH RFC 4/5] qedf: Add offload ELS request handling.

2016-12-28 Thread Hannes Reinecke
On 12/23/2016 08:17 PM, Dupuis, Chad wrote:
> From: "Dupuis, Chad" 
> 
> This patch adds support for ELS requests that are handled by the firmware for
> offloaded sessions.
> 
> Signed-off-by: Nilesh Javali 
> Signed-off-by: Manish Rangankar 
> Signed-off-by: Saurav Kashyap 
> Signed-off-by: Chad Dupuis 
> ---
>  drivers/scsi/qedf/qedf_els.c | 984 
> +++
>  1 file changed, 984 insertions(+)
>  create mode 100644 drivers/scsi/qedf/qedf_els.c
> 
Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
-- 
Dr. Hannes Reinecke   zSeries & Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH RFC 4/5] qedf: Add offload ELS request handling.

2016-12-23 Thread Dupuis, Chad
From: "Dupuis, Chad" 

This patch adds support for ELS requests that are handled by the firmware for
offloaded sessions.

Signed-off-by: Nilesh Javali 
Signed-off-by: Manish Rangankar 
Signed-off-by: Saurav Kashyap 
Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_els.c | 984 +++
 1 file changed, 984 insertions(+)
 create mode 100644 drivers/scsi/qedf/qedf_els.c

diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c
new file mode 100644
index 000..98a80b3
--- /dev/null
+++ b/drivers/scsi/qedf/qedf_els.c
@@ -0,0 +1,984 @@
+/*
+ *  QLogic FCoE 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 "qedf.h"
+
+/* It's assumed that the lock is held when calling this function. */
+static int qedf_initiate_els(struct qedf_rport *fcport, unsigned int op,
+   void *data, uint32_t data_len,
+   void (*cb_func)(struct qedf_els_cb_arg *cb_arg),
+   struct qedf_els_cb_arg *cb_arg, uint32_t timer_msec)
+{
+   struct qedf_ctx *qedf = fcport->qedf;
+   struct fc_lport *lport = qedf->lport;
+   struct qedf_ioreq *els_req;
+   struct qedf_mp_req *mp_req;
+   struct fc_frame_header *fc_hdr;
+   struct fcoe_task_context *task;
+   int rc = 0;
+   uint32_t did, sid;
+   uint16_t xid;
+   uint32_t start_time = jiffies / HZ;
+   uint32_t current_time;
+
+   QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Sending ELS\n");
+
+   rc = fc_remote_port_chkready(fcport->rport);
+   if (rc) {
+   QEDF_ERR(&(qedf->dbg_ctx), "els 0x%x: rport not ready\n", op);
+   rc = -EAGAIN;
+   goto els_err;
+   }
+   if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
+   QEDF_ERR(&(qedf->dbg_ctx), "els 0x%x: link is not ready\n",
+ op);
+   rc = -EAGAIN;
+   goto els_err;
+   }
+
+   if (!(test_bit(QEDF_RPORT_SESSION_READY, >flags))) {
+   QEDF_ERR(&(qedf->dbg_ctx), "els 0x%x: fcport not ready\n", op);
+   rc = -EINVAL;
+   goto els_err;
+   }
+
+retry_els:
+   els_req = qedf_alloc_cmd(fcport, QEDF_ELS);
+   if (!els_req) {
+   current_time = jiffies / HZ;
+   if ((current_time - start_time) > 10) {
+   QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS,
+  "els: Failed els 0x%x\n", op);
+   rc = -ENOMEM;
+   goto els_err;
+   }
+   mdelay(20 * USEC_PER_MSEC);
+   goto retry_els;
+   }
+
+   QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "initiate_els els_req = "
+  "0x%p cb_arg = %p xid = %x\n", els_req, cb_arg,
+  els_req->xid);
+   els_req->sc_cmd = NULL;
+   els_req->cmd_type = QEDF_ELS;
+   els_req->fcport = fcport;
+   els_req->cb_func = cb_func;
+   cb_arg->io_req = els_req;
+   cb_arg->op = op;
+   els_req->cb_arg = cb_arg;
+   els_req->data_xfer_len = data_len;
+
+   /* Record which cpu this request is associated with */
+   els_req->cpu = smp_processor_id();
+   qedf_inc_percpu_requests(els_req->cpu);
+
+   mp_req = (struct qedf_mp_req *)&(els_req->mp_req);
+   rc = qedf_init_mp_req(els_req);
+   if (rc) {
+   QEDF_ERR(&(qedf->dbg_ctx), "ELS MP request init failed\n");
+   kref_put(_req->refcount, qedf_release_cmd);
+   goto els_err;
+   } else {
+   rc = 0;
+   }
+
+   /* Fill ELS Payload */
+   if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
+   memcpy(mp_req->req_buf, data, data_len);
+   } else {
+   QEDF_ERR(&(qedf->dbg_ctx), "Invalid ELS op 0x%x\n", op);
+   els_req->cb_func = NULL;
+   els_req->cb_arg = NULL;
+   kref_put(_req->refcount, qedf_release_cmd);
+   rc = -EINVAL;
+   }
+
+   if (rc)
+   goto els_err;
+
+   /* Fill FC header */
+   fc_hdr = &(mp_req->req_fc_hdr);
+
+   did = fcport->rdata->ids.port_id;
+   sid = fcport->sid;
+
+   __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, sid, did,
+  FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
+  FC_FC_SEQ_INIT, 0);
+
+   /* Obtain exchange id */
+   xid = els_req->xid;
+
+   /* Initialize task context for this IO request */
+   task = qedf_get_task_mem(>tasks, xid);
+   qedf_init_mp_task(els_req, task);
+
+   /* Put timer on original I/O request */
+   if (timer_msec)
+