netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Hannes Reinecke <hare-l3A5Bk7waGM@public.gmane.org>
To: "Dupuis,
	Chad" <chad.dupuis-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>,
	martin.petersen-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org
Cc: fcoe-devel-s9riP+hp16TNLxjTenLetw@public.gmane.org,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	QLogic-Storage-Upstream-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org,
	linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	yuval.mintz-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org
Subject: Re: [PATCH V3 2/2] qedf: Add QLogic FastLinQ offload FCoE driver framework.
Date: Mon, 6 Feb 2017 16:56:42 +0100	[thread overview]
Message-ID: <fc01015d-7f49-40a9-4fe8-bdd300fcb514@suse.de> (raw)
In-Reply-To: <1486149429-30095-3-git-send-email-chad.dupuis-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>

On 02/03/2017 08:17 PM, Dupuis, Chad wrote:
> From: "Dupuis, Chad" <chad.dupuis-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> 
> The QLogic FastLinQ Driver for FCoE (qedf) is the FCoE specific module for 41000
> Series Converged Network Adapters by QLogic. This patch consists of following
> changes:
> 
> - MAINTAINERS Makefile and Kconfig changes for qedf
> - PCI driver registration
> - libfc/fcoe host level initialization
> - SCSI host template initialization and callbacks
> - Debugfs and log level infrastructure
> - Link handling
> - Firmware interface structures
> - QED core module initialization
> - Light L2 interface callbacks
> - I/O request initialization
> - Firmware I/O completion handling
> - Firmware ELS request/response handling
> - FIP request/response handled by the driver itself
> 
> Signed-off-by: Nilesh Javali <nilesh.javali-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Manish Rangankar <manish.rangankar-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Saurav Kashyap <saurav.kashyap-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Arun Easi <arun.easi-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Chad Dupuis <chad.dupuis-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
> ---
[ .. ]
> +static void qedf_process_l2_frame_compl(struct qedf_rport *fcport,
> +					unsigned char *buf,
> +					u32 frame_len, u16 l2_oxid)
> +{
> +	struct fc_lport *lport = fcport->qedf->lport;
> +	struct fc_frame_header *fh;
> +	struct fc_frame *fp;
> +	u32 payload_len;
> +	u32 crc;
> +
> +	payload_len = frame_len - sizeof(struct fc_frame_header);
> +
> +	fp = fc_frame_alloc(lport, payload_len);
> +	if (!fp) {
> +		QEDF_ERR(&(fcport->qedf->dbg_ctx),
> +		    "fc_frame_alloc failure.\n");
> +		return;
> +	}
> +
> +	/* Copy FC Frame header and payload into the frame */
> +	fh = (struct fc_frame_header *)fc_frame_header_get(fp);
> +	memcpy(fh, buf, frame_len);
> +
> +	/* Set the OXID we return to what libfc used */
> +	if (l2_oxid != FC_XID_UNKNOWN)
> +		fh->fh_ox_id = htons(l2_oxid);
> +
> +	/* Setup header fields */
> +	fh->fh_r_ctl = FC_RCTL_ELS_REP;
> +	fh->fh_type = FC_TYPE_ELS;
> +	/* Last sequence, end sequence */
> +	fh->fh_f_ctl[0] = 0x98;
> +	hton24(fh->fh_d_id, lport->port_id);
> +	hton24(fh->fh_s_id, fcport->rdata->ids.port_id);
> +	fh->fh_rx_id = 0xffff;
> +
> +	/* Set frame attributes */
> +	crc = fcoe_fc_crc(fp);
> +	fc_frame_init(fp);
> +	fr_dev(fp) = lport;
> +	fr_sof(fp) = FC_SOF_I3;
> +	fr_eof(fp) = FC_EOF_T;
> +	fr_crc(fp) = cpu_to_le32(~crc);
> +
> +	/* Send completed request to libfc */
> +	fc_exch_recv(lport, fp);
> +}
> +
> +/*
> + * In instances where an ELS command times out we may need to restart the
> + * rport by logging out and then logging back in.
> + */
> +void qedf_restart_rport(struct qedf_rport *fcport)
> +{
> +	struct fc_lport *lport;
> +	struct fc_rport_priv *rdata;
> +	u32 port_id;
> +
> +	if (!fcport)
> +		return;
> +
> +	rdata = fcport->rdata;
> +	if (rdata) {
> +		lport = fcport->qedf->lport;
> +		port_id = rdata->ids.port_id;
> +		QEDF_ERR(&(fcport->qedf->dbg_ctx),
> +		    "LOGO port_id=%x.\n", port_id);
> +		fc_rport_logoff(rdata);
> +		/* Recreate the rport and log back in */
> +		rdata = fc_rport_create(lport, port_id);
> +		if (rdata)
> +			fc_rport_login(rdata);
> +	}
> +}
> +
> +static void qedf_l2_els_compl(struct qedf_els_cb_arg *cb_arg)
> +{
> +	struct qedf_ioreq *els_req;
> +	struct qedf_rport *fcport;
> +	struct qedf_mp_req *mp_req;
> +	struct fc_frame_header *fc_hdr;
> +	unsigned char *buf;
> +	void *resp_buf;
> +	u32 resp_len, hdr_len;
> +	u16 l2_oxid;
> +	int frame_len;
> +
> +	l2_oxid = cb_arg->l2_oxid;
> +	els_req = cb_arg->io_req;
> +
> +	if (!els_req) {
> +		QEDF_ERR(NULL, "els_req is NULL.\n");
> +		goto free_arg;
> +	}
> +
> +	/*
> +	 * If we are flushing the command just free the cb_arg as none of the
> +	 * response data will be valid.
> +	 */
> +	if (els_req->event == QEDF_IOREQ_EV_ELS_FLUSH)
> +		goto free_arg;
> +
> +	fcport = els_req->fcport;
> +	mp_req = &(els_req->mp_req);
> +	fc_hdr = &(mp_req->resp_fc_hdr);
> +	resp_len = mp_req->resp_len;
> +	resp_buf = mp_req->resp_buf;
> +
> +	/*
> +	 * If a middle path ELS command times out, don't try to return
> +	 * the command but rather do any internal cleanup and then libfc
> +	 * timeout the command and clean up its internal resources.
> +	 */
> +	if (els_req->event == QEDF_IOREQ_EV_ELS_TMO) {
> +		/*
> +		 * If ADISC times out, libfc will timeout the exchange and then
> +		 * try to send a PLOGI which will timeout since the session is
> +		 * still offloaded.  Force libfc to logout the session which
> +		 * will offload the connection and allow the PLOGI response to
> +		 * flow over the LL2 path.
> +		 */
> +		if (cb_arg->op == ELS_ADISC)
> +			qedf_restart_rport(fcport);
> +		return;
> +	}
> +
> +	buf = kzalloc(QEDF_PAGE_SIZE, GFP_ATOMIC);
> +	if (!buf) {
> +		QEDF_ERR(&(fcport->qedf->dbg_ctx),
> +		    "Unable to alloc mp buf.\n");
> +		goto free_arg;
> +	}
> +	hdr_len = sizeof(*fc_hdr);
> +	if (hdr_len + resp_len > QEDF_PAGE_SIZE) {
> +		QEDF_ERR(&(fcport->qedf->dbg_ctx), "resp_len is "
> +		   "beyond page size.\n");
> +		goto free_buf;
> +	}
> +	memcpy(buf, fc_hdr, hdr_len);
> +	memcpy(buf + hdr_len, resp_buf, resp_len);
> +	frame_len = hdr_len + resp_len;
> +
> +	QEDF_INFO(&(fcport->qedf->dbg_ctx), QEDF_LOG_ELS,
> +	    "Completing OX_ID 0x%x back to libfc.\n", l2_oxid);
> +	qedf_process_l2_frame_compl(fcport, buf, frame_len, l2_oxid);
> +
> +free_buf:
> +	kfree(buf);
> +free_arg:
> +	kfree(cb_arg);
> +}
> +
That looks a bit convoluted; you're allocating a buffer, copying the
frame header and the response into it, and then call 'XX_frame_compl()'
which has to extract the buffer again and discard the response.
Why not pass in the frame header directly?

> +int qedf_send_adisc(struct qedf_rport *fcport, struct fc_frame *fp)
> +{
> +	struct fc_els_adisc *adisc;
> +	struct fc_frame_header *fh;
> +	struct fc_lport *lport = fcport->qedf->lport;
> +	struct qedf_els_cb_arg *cb_arg = NULL;
> +	struct qedf_ctx *qedf;
> +	uint32_t r_a_tov = lport->r_a_tov;
> +	int rc;
> +
> +	qedf = fcport->qedf;
> +	fh = fc_frame_header_get(fp);
> +
> +	cb_arg = kzalloc(sizeof(struct qedf_els_cb_arg), GFP_NOIO);
> +	if (!cb_arg) {
> +		QEDF_ERR(&(qedf->dbg_ctx), "Unable to allocate cb_arg for "
> +			  "ADISC\n");
> +		rc = -ENOMEM;
> +		goto adisc_err;
> +	}
> +	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
> +
> +	QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS,
> +	    "Sending ADISC ox_id=0x%x.\n", cb_arg->l2_oxid);
> +
> +	adisc = fc_frame_payload_get(fp, sizeof(*adisc));
> +
> +	rc = qedf_initiate_els(fcport, ELS_ADISC, adisc, sizeof(*adisc),
> +	    qedf_l2_els_compl, cb_arg, r_a_tov);
> +
> +adisc_err:
> +	if (rc) {
> +		QEDF_ERR(&(qedf->dbg_ctx), "ADISC failed.\n");
> +		kfree(cb_arg);
> +	}
> +	return rc;
> +}
> +
> +static void qedf_srr_compl(struct qedf_els_cb_arg *cb_arg)
> +{
> +	struct qedf_ioreq *orig_io_req;
> +	struct qedf_ioreq *srr_req;
> +	struct qedf_mp_req *mp_req;
> +	struct fc_frame_header *fc_hdr, *fh;
> +	struct fc_frame *fp;
> +	unsigned char *buf;
> +	void *resp_buf;
> +	u32 resp_len, hdr_len;
> +	struct fc_lport *lport;
> +	struct qedf_ctx *qedf;
> +	int refcount;
> +	u8 opcode;
> +
> +	srr_req = cb_arg->io_req;
> +	qedf = srr_req->fcport->qedf;
> +	lport = qedf->lport;
> +
> +	orig_io_req = cb_arg->aborted_io_req;
> +
> +	if (!orig_io_req)
> +		goto out_free;
> +
> +	clear_bit(QEDF_CMD_SRR_SENT, &orig_io_req->flags);
> +
> +	if (srr_req->event != QEDF_IOREQ_EV_ELS_TMO &&
> +	    srr_req->event != QEDF_IOREQ_EV_ELS_ERR_DETECT)
> +		cancel_delayed_work_sync(&orig_io_req->timeout_work);
> +
> +	refcount = atomic_read(&orig_io_req->refcount.refcount);
> +	QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Entered: orig_io=%p,"
> +		   " orig_io_xid=0x%x, rec_xid=0x%x, refcount=%d\n",
> +		   orig_io_req, orig_io_req->xid, srr_req->xid, refcount);
> +
> +	/* If a SRR times out, simply free resources */
> +	if (srr_req->event == QEDF_IOREQ_EV_ELS_TMO)
> +		goto out_free;
> +
> +	/* Normalize response data into struct fc_frame */
> +	mp_req = &(srr_req->mp_req);
> +	fc_hdr = &(mp_req->resp_fc_hdr);
> +	resp_len = mp_req->resp_len;
> +	resp_buf = mp_req->resp_buf;
> +	hdr_len = sizeof(*fc_hdr);
> +
> +	buf = kzalloc(QEDF_PAGE_SIZE, GFP_ATOMIC);
> +	if (!buf) {
> +		QEDF_ERR(&(qedf->dbg_ctx),
> +		    "Unable to alloc mp buf.\n");
> +		goto out_free;
> +	}
> +
> +	memcpy(buf, fc_hdr, hdr_len);
> +	memcpy(buf + hdr_len, resp_buf, resp_len);
> +
> +	fp = fc_frame_alloc(lport, resp_len);
> +	if (!fp) {
> +		QEDF_ERR(&(qedf->dbg_ctx),
> +		    "fc_frame_alloc failure.\n");
> +		goto out_buf;
> +	}
> +
> +	/* Copy FC Frame header and payload into the frame */
> +	fh = (struct fc_frame_header *)fc_frame_header_get(fp);
> +	memcpy(fh, buf, hdr_len + resp_len);
> +
Same here: why do you allocate a buffer, just so that you can copy
things out of the buffer again?

[ .. ]
> +static void qedf_rec_compl(struct qedf_els_cb_arg *cb_arg)
> +{
> +	struct qedf_ioreq *orig_io_req;
> +	struct qedf_ioreq *rec_req;
> +	struct qedf_mp_req *mp_req;
> +	struct fc_frame_header *fc_hdr, *fh;
> +	struct fc_frame *fp;
> +	unsigned char *buf;
> +	void *resp_buf;
> +	u32 resp_len, hdr_len;
> +	struct fc_lport *lport;
> +	struct qedf_ctx *qedf;
> +	int refcount;
> +	enum fc_rctl r_ctl;
> +	struct fc_els_ls_rjt *rjt;
> +	struct fc_els_rec_acc *acc;
> +	u8 opcode;
> +	u32 offset, e_stat;
> +	struct scsi_cmnd *sc_cmd;
> +	bool srr_needed = false;
> +
> +	rec_req = cb_arg->io_req;
> +	qedf = rec_req->fcport->qedf;
> +	lport = qedf->lport;
> +
> +	orig_io_req = cb_arg->aborted_io_req;
> +
> +	if (!orig_io_req)
> +		goto out_free;
> +
> +	if (rec_req->event != QEDF_IOREQ_EV_ELS_TMO &&
> +	    rec_req->event != QEDF_IOREQ_EV_ELS_ERR_DETECT)
> +		cancel_delayed_work_sync(&orig_io_req->timeout_work);
> +
> +	refcount = atomic_read(&orig_io_req->refcount.refcount);
> +	QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Entered: orig_io=%p,"
> +		   " orig_io_xid=0x%x, rec_xid=0x%x, refcount=%d\n",
> +		   orig_io_req, orig_io_req->xid, rec_req->xid, refcount);
> +
> +	/* If a REC times out, free resources */
> +	if (rec_req->event == QEDF_IOREQ_EV_ELS_TMO)
> +		goto out_free;
> +
> +	/* Normalize response data into struct fc_frame */
> +	mp_req = &(rec_req->mp_req);
> +	fc_hdr = &(mp_req->resp_fc_hdr);
> +	resp_len = mp_req->resp_len;
> +	acc = resp_buf = mp_req->resp_buf;
> +	hdr_len = sizeof(*fc_hdr);
> +
> +	buf = kzalloc(QEDF_PAGE_SIZE, GFP_ATOMIC);
> +	if (!buf) {
> +		QEDF_ERR(&(qedf->dbg_ctx),
> +		    "Unable to alloc mp buf.\n");
> +		goto out_free;
> +	}
> +
> +	memcpy(buf, fc_hdr, hdr_len);
> +	memcpy(buf + hdr_len, resp_buf, resp_len);
> +
> +	fp = fc_frame_alloc(lport, resp_len);
> +	if (!fp) {
> +		QEDF_ERR(&(qedf->dbg_ctx),
> +		    "fc_frame_alloc failure.\n");
> +		goto out_buf;
> +	}
> +
> +	/* Copy FC Frame header and payload into the frame */
> +	fh = (struct fc_frame_header *)fc_frame_header_get(fp);
> +	memcpy(fh, buf, hdr_len + resp_len);
> +
Again, same story.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare-l3A5Bk7waGM@public.gmane.org			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)

  parent reply	other threads:[~2017-02-06 15:56 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-03 19:17 [PATCH V3 0/2] Add QLogic FastLinQ FCoE (qedf) driver Dupuis, Chad
2017-02-03 19:17 ` [PATCH V3 net-next 1/2] qed: Add support for hardware offloaded FCoE Dupuis, Chad
2017-02-03 19:17 ` [PATCH V3 2/2] qedf: Add QLogic FastLinQ offload FCoE driver framework Dupuis, Chad
2017-02-04  8:50   ` kbuild test robot
     [not found]   ` <1486149429-30095-3-git-send-email-chad.dupuis-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org>
2017-02-06 15:56     ` Hannes Reinecke [this message]
     [not found]       ` <fc01015d-7f49-40a9-4fe8-bdd300fcb514-l3A5Bk7waGM@public.gmane.org>
2017-02-06 20:17         ` Chad Dupuis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fc01015d-7f49-40a9-4fe8-bdd300fcb514@suse.de \
    --to=hare-l3a5bk7wagm@public.gmane.org \
    --cc=QLogic-Storage-Upstream-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org \
    --cc=chad.dupuis-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org \
    --cc=fcoe-devel-s9riP+hp16TNLxjTenLetw@public.gmane.org \
    --cc=linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=martin.petersen-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org \
    --cc=netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=yuval.mintz-YGCgFSpz5w/QT0dZR+AlfA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).