All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/24] FCoE VN2VN fixes, part two
@ 2016-10-13 13:10 Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 01/24] libfc: additional debugging messages Hannes Reinecke
                   ` (25 more replies)
  0 siblings, 26 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

Hi all,

here's now the second part of my FCoE VN2VN patchset.
The key points are:
- Configurable R_A_TOV/E_D_TOV
- Rework PRLI handling to fix a longstanding bug
- Correctly handle timed-out xids

Additionally there are some minor fixes to get things to work
when running with FCoE over virtio.

Patches are relative to mkp/4.10/scsi-queue.

As usual, comments and reviews are welcome.

Hannes Reinecke (24):
  libfc: additional debugging messages
  libfc: spurious I/O error under high load
  libfc: use configured lport R_A_TOV
  libfc: use configured rport E_D_TOV
  libfc: sanitize E_D_TOV and R_A_TOV setting
  fcoe: make R_A_TOV and E_D_TOV configurable
  libfc: do not overwrite DID_TIME_OUT status
  libfc: use error code for fc_rport_error()
  libfc: Implement RTV responder
  libfc: Rework PRLI handling
  libfc: Return LS_RJT_BUSY for PRLI in status PLOGI
  libfc: Clarify ramp-down messages
  libfc: safeguard against invalid exchange index
  libfc: quarantine timed out xids
  libfc: don't fail sequence abort for completed exchanges
  libfc: Do not drop out-of-order frames
  libfc: reset timeout on queue full
  libfc: wait for E_D_TOV when out-of-order sequence is received
  libfc: Check xid when looking up REC exchanges
  fcoe: set default TC priority
  fcoe: catch invalid values for the 'enabled' attribute
  fcoe: FIP debugging
  fcoe: correct sending FIP VLAN packets on VLAN 0
  fcoe: filter out frames from invalid vlans

 drivers/scsi/fcoe/fcoe.c       |  23 +++-
 drivers/scsi/fcoe/fcoe_ctlr.c  |  60 +++++++++-
 drivers/scsi/fcoe/fcoe_sysfs.c |  83 +++++++++++++-
 drivers/scsi/libfc/fc_exch.c   | 134 ++++++++++++++++------
 drivers/scsi/libfc/fc_fcp.c    | 196 ++++++++++++++++++++++----------
 drivers/scsi/libfc/fc_lport.c  |   8 +-
 drivers/scsi/libfc/fc_rport.c  | 248 ++++++++++++++++++++++++++++++-----------
 include/scsi/libfc.h           |   9 +-
 8 files changed, 584 insertions(+), 177 deletions(-)

-- 
1.8.5.6


^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 01/24] libfc: additional debugging messages
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 02/24] libfc: spurious I/O error under high load Hannes Reinecke
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_exch.c  | 59 +++++++++++++++++++++++++++++++++++--------
 drivers/scsi/libfc/fc_fcp.c   | 41 ++++++++++++++++++++++++------
 drivers/scsi/libfc/fc_rport.c | 25 ++++++++++++++----
 3 files changed, 101 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 16ca31a..b4bdc90 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -362,8 +362,10 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep,
 
 	fc_exch_hold(ep);		/* hold for timer */
 	if (!queue_delayed_work(fc_exch_workqueue, &ep->timeout_work,
-				msecs_to_jiffies(timer_msec)))
+				msecs_to_jiffies(timer_msec))) {
+		FC_EXCH_DBG(ep, "Exchange already queued\n");
 		fc_exch_release(ep);
+	}
 }
 
 /**
@@ -632,9 +634,13 @@ static int fc_exch_abort_locked(struct fc_exch *ep,
 	struct fc_frame *fp;
 	int error;
 
+	FC_EXCH_DBG(ep, "exch: abort, time %d msecs\n", timer_msec);
 	if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL) ||
-	    ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP))
+	    ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) {
+		FC_EXCH_DBG(ep, "exch: already completed esb %x state %x\n",
+			    ep->esb_stat, ep->state);
 		return -ENXIO;
+	}
 
 	/*
 	 * Send the abort on a new sequence if possible.
@@ -758,7 +764,7 @@ static void fc_exch_timeout(struct work_struct *work)
 	u32 e_stat;
 	int rc = 1;
 
-	FC_EXCH_DBG(ep, "Exchange timed out\n");
+	FC_EXCH_DBG(ep, "Exchange timed out state %x\n", ep->state);
 
 	spin_lock_bh(&ep->ex_lock);
 	if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
@@ -1258,8 +1264,10 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
 	 */
 	if (fc_sof_needs_ack(fr_sof(rx_fp))) {
 		fp = fc_frame_alloc(lport, 0);
-		if (!fp)
+		if (!fp) {
+			FC_EXCH_DBG(ep, "Drop ACK request, out of memory\n");
 			return;
+		}
 
 		fh = fc_frame_header_get(fp);
 		fh->fh_r_ctl = FC_RCTL_ACK_1;
@@ -1312,13 +1320,18 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
 	struct fc_frame_header *rx_fh;
 	struct fc_frame_header *fh;
 	struct fc_ba_rjt *rp;
+	struct fc_seq *sp;
 	struct fc_lport *lport;
 	unsigned int f_ctl;
 
 	lport = fr_dev(rx_fp);
+	sp = fr_seq(rx_fp);
 	fp = fc_frame_alloc(lport, sizeof(*rp));
-	if (!fp)
+	if (!fp) {
+		FC_EXCH_DBG(fc_seq_exch(sp),
+			     "Drop BA_RJT request, out of memory\n");
 		return;
+	}
 	fh = fc_frame_header_get(fp);
 	rx_fh = fc_frame_header_get(rx_fp);
 
@@ -1383,14 +1396,17 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp)
 	if (!ep)
 		goto reject;
 
+	FC_EXCH_DBG(ep, "exch: ABTS received\n");
 	fp = fc_frame_alloc(ep->lp, sizeof(*ap));
-	if (!fp)
+	if (!fp) {
+		FC_EXCH_DBG(ep, "Drop ABTS request, out of memory\n");
 		goto free;
+	}
 
 	spin_lock_bh(&ep->ex_lock);
 	if (ep->esb_stat & ESB_ST_COMPLETE) {
 		spin_unlock_bh(&ep->ex_lock);
-
+		FC_EXCH_DBG(ep, "exch: ABTS rejected, exchange complete\n");
 		fc_frame_free(fp);
 		goto reject;
 	}
@@ -1784,11 +1800,16 @@ static void fc_seq_ls_acc(struct fc_frame *rx_fp)
 	struct fc_lport *lport;
 	struct fc_els_ls_acc *acc;
 	struct fc_frame *fp;
+	struct fc_seq *sp;
 
 	lport = fr_dev(rx_fp);
+	sp = fr_seq(rx_fp);
 	fp = fc_frame_alloc(lport, sizeof(*acc));
-	if (!fp)
+	if (!fp) {
+		FC_EXCH_DBG(fc_seq_exch(sp),
+			    "exch: drop LS_ACC, out of memory\n");
 		return;
+	}
 	acc = fc_frame_payload_get(fp, sizeof(*acc));
 	memset(acc, 0, sizeof(*acc));
 	acc->la_cmd = ELS_LS_ACC;
@@ -1811,11 +1832,16 @@ static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason,
 	struct fc_lport *lport;
 	struct fc_els_ls_rjt *rjt;
 	struct fc_frame *fp;
+	struct fc_seq *sp;
 
 	lport = fr_dev(rx_fp);
+	sp = fr_seq(rx_fp);
 	fp = fc_frame_alloc(lport, sizeof(*rjt));
-	if (!fp)
+	if (!fp) {
+		FC_EXCH_DBG(fc_seq_exch(sp),
+			    "exch: drop LS_ACC, out of memory\n");
 		return;
+	}
 	rjt = fc_frame_payload_get(fp, sizeof(*rjt));
 	memset(rjt, 0, sizeof(*rjt));
 	rjt->er_cmd = ELS_LS_RJT;
@@ -1975,15 +2001,23 @@ static void fc_exch_els_rec(struct fc_frame *rfp)
 	ep = fc_exch_lookup(lport,
 			    sid == fc_host_port_id(lport->host) ? oxid : rxid);
 	explan = ELS_EXPL_OXID_RXID;
-	if (!ep)
+	if (!ep) {
+		FC_LPORT_DBG(lport,
+			     "REC request from %x: rxid %x oxid %x not found\n",
+			     sid, rxid, oxid);
 		goto reject;
+	}
+	FC_EXCH_DBG(ep, "REC request from %x: rxid %x oxid %x\n",
+		    sid, rxid, oxid);
 	if (ep->oid != sid || oxid != ep->oxid)
 		goto rel;
 	if (rxid != FC_XID_UNKNOWN && rxid != ep->rxid)
 		goto rel;
 	fp = fc_frame_alloc(lport, sizeof(*acc));
-	if (!fp)
+	if (!fp) {
+		FC_EXCH_DBG(ep, "Drop REC request, out of memory\n");
 		goto out;
+	}
 
 	acc = fc_frame_payload_get(fp, sizeof(*acc));
 	memset(acc, 0, sizeof(*acc));
@@ -2176,6 +2210,7 @@ static void fc_exch_rrq(struct fc_exch *ep)
 		return;
 
 retry:
+	FC_EXCH_DBG(ep, "exch: RRQ send failed\n");
 	spin_lock_bh(&ep->ex_lock);
 	if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) {
 		spin_unlock_bh(&ep->ex_lock);
@@ -2218,6 +2253,8 @@ static void fc_exch_els_rrq(struct fc_frame *fp)
 	if (!ep)
 		goto reject;
 	spin_lock_bh(&ep->ex_lock);
+	FC_EXCH_DBG(ep, "RRQ request from %x: xid %x rxid %x oxid %x\n",
+		    sid, xid, ntohs(rp->rrq_rx_id), ntohs(rp->rrq_ox_id));
 	if (ep->oxid != ntohs(rp->rrq_ox_id))
 		goto unlock_reject;
 	if (ep->rxid != ntohs(rp->rrq_rx_id) &&
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 5121272..5c6c73a 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -764,8 +764,11 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
 	fh = fc_frame_header_get(fp);
 	r_ctl = fh->fh_r_ctl;
 
-	if (lport->state != LPORT_ST_READY)
+	if (lport->state != LPORT_ST_READY) {
+		FC_FCP_DBG(fsp, "lport state %d, ignoring r_ctl %x\n",
+			   lport->state, r_ctl);
 		goto out;
+	}
 	if (fc_fcp_lock_pkt(fsp))
 		goto out;
 
@@ -774,8 +777,10 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
 		goto unlock;
 	}
 
-	if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING))
+	if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING)) {
+		FC_FCP_DBG(fsp, "command aborted, ignoring r_ctl %x\n", r_ctl);
 		goto unlock;
+	}
 
 	if (r_ctl == FC_RCTL_DD_DATA_DESC) {
 		/*
@@ -910,6 +915,10 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 			 * Wait a at least one jiffy to see if it is delivered.
 			 * If this expires without data, we may do SRR.
 			 */
+			FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun "
+				   "len %x, data len %x\n",
+				   fsp->rport->port_id,
+				   fsp->xfer_len, expected_len, fsp->data_len);
 			fc_fcp_timer_set(fsp, 2);
 			return;
 		}
@@ -959,8 +968,11 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp)
 		if (fsp->cdb_status == SAM_STAT_GOOD &&
 		    fsp->xfer_len < fsp->data_len && !fsp->io_status &&
 		    (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) ||
-		     fsp->xfer_len < fsp->data_len - fsp->scsi_resid))
+		     fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) {
+			FC_FCP_DBG(fsp, "data underrun, xfer %zx data %x\n",
+				    fsp->xfer_len, fsp->data_len);
 			fsp->status_code = FC_DATA_UNDRUN;
+		}
 	}
 
 	seq = fsp->seq_ptr;
@@ -1222,8 +1234,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
 	int rc = FAILED;
 	unsigned long ticks_left;
 
-	if (fc_fcp_send_abort(fsp))
+	FC_FCP_DBG(fsp, "pkt abort state %x\n", fsp->state);
+	if (fc_fcp_send_abort(fsp)) {
+		FC_FCP_DBG(fsp, "failed to send abort\n");
 		return FAILED;
+	}
 
 	init_completion(&fsp->tm_done);
 	fsp->wait_for_comp = 1;
@@ -1394,6 +1409,8 @@ static void fc_fcp_timeout(unsigned long data)
 	if (fsp->cdb_cmd.fc_tm_flags)
 		goto unlock;
 
+	FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n",
+		   rpriv->flags, fsp->state);
 	fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
 
 	if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
@@ -1486,8 +1503,8 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
 		rjt = fc_frame_payload_get(fp, sizeof(*rjt));
 		switch (rjt->er_reason) {
 		default:
-			FC_FCP_DBG(fsp, "device %x unexpected REC reject "
-				   "reason %d expl %d\n",
+			FC_FCP_DBG(fsp,
+				   "device %x invalid REC reject %d/%d\n",
 				   fsp->rport->port_id, rjt->er_reason,
 				   rjt->er_explan);
 			/* fall through */
@@ -1503,6 +1520,9 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
 			break;
 		case ELS_RJT_LOGIC:
 		case ELS_RJT_UNAB:
+			FC_FCP_DBG(fsp, "device %x REC reject %d/%d\n",
+				   fsp->rport->port_id, rjt->er_reason,
+				   rjt->er_explan);
 			/*
 			 * If no data transfer, the command frame got dropped
 			 * so we just retry.  If data was transferred, we
@@ -1608,6 +1628,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 
 	switch (error) {
 	case -FC_EX_CLOSED:
+		FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n",
+			   fsp, fsp->rport->port_id);
 		fc_fcp_retry_cmd(fsp);
 		break;
 
@@ -1622,8 +1644,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 		 * Assume REC or LS_ACC was lost.
 		 * The exchange manager will have aborted REC, so retry.
 		 */
-		FC_FCP_DBG(fsp, "REC fid %6.6x error error %d retry %d/%d\n",
-			   fsp->rport->port_id, error, fsp->recov_retry,
+		FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange timeout retry %d/%d\n",
+			   fsp, fsp->rport->port_id, fsp->recov_retry,
 			   FC_MAX_RECOV_RETRY);
 		if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
 			fc_fcp_rec(fsp);
@@ -1642,6 +1664,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
  */
 static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code)
 {
+	FC_FCP_DBG(fsp, "start recovery code %x\n", code);
 	fsp->status_code = code;
 	fsp->cdb_status = 0;
 	fsp->io_status = 0;
@@ -1768,12 +1791,14 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 		goto out;
 	switch (PTR_ERR(fp)) {
 	case -FC_EX_TIMEOUT:
+		FC_FCP_DBG(fsp, "SRR timeout, retries %d\n", fsp->recov_retry);
 		if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
 			fc_fcp_rec(fsp);
 		else
 			fc_fcp_recovery(fsp, FC_TIMED_OUT);
 		break;
 	case -FC_EX_CLOSED:			/* e.g., link failure */
+		FC_FCP_DBG(fsp, "SRR error, exchange closed\n");
 		/* fall through */
 	default:
 		fc_fcp_retry_cmd(fsp);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 4b9bb6d..bcd1cd3 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -287,8 +287,10 @@ static void fc_rport_work(struct work_struct *work)
 		kref_get(&rdata->kref);
 		mutex_unlock(&rdata->rp_mutex);
 
-		if (!rport)
+		if (!rport) {
+			FC_RPORT_DBG(rdata, "No rport!\n");
 			rport = fc_remote_port_add(lport->host, 0, &ids);
+		}
 		if (!rport) {
 			FC_RPORT_DBG(rdata, "Failed to add the rport\n");
 			lport->tt.rport_logoff(rdata);
@@ -389,8 +391,10 @@ static void fc_rport_work(struct work_struct *work)
 			 * Re-open for events.  Reissue READY event if ready.
 			 */
 			rdata->event = RPORT_EV_NONE;
-			if (rdata->rp_state == RPORT_ST_READY)
+			if (rdata->rp_state == RPORT_ST_READY) {
+				FC_RPORT_DBG(rdata, "work reopen\n");
 				fc_rport_enter_ready(rdata);
+			}
 			mutex_unlock(&rdata->rp_mutex);
 		}
 		break;
@@ -568,6 +572,7 @@ static void fc_rport_timeout(struct work_struct *work)
 	struct fc_lport *lport = rdata->local_port;
 
 	mutex_lock(&rdata->rp_mutex);
+	FC_RPORT_DBG(rdata, "Port timeout, state %s\n", fc_rport_state(rdata));
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_FLOGI:
@@ -1095,6 +1100,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		struct fc_els_spp spp;
 	} *pp;
 	struct fc_els_spp temp_spp;
+	struct fc_els_ls_rjt *rjt;
 	struct fc4_prov *prov;
 	u32 roles = FC_RPORT_ROLE_UNKNOWN;
 	u32 fcp_parm = 0;
@@ -1167,8 +1173,10 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		fc_rport_enter_rtv(rdata);
 
 	} else {
-		FC_RPORT_DBG(rdata, "Bad ELS response for PRLI command\n");
-		fc_rport_error_retry(rdata, fp);
+		rjt = fc_frame_payload_get(fp, sizeof(*rjt));
+		FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n",
+			     rjt->er_reason, rjt->er_explan);
+		fc_rport_error_retry(rdata, NULL);
 	}
 
 out:
@@ -1602,8 +1610,12 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
 	struct fc_seq_els_data els_data;
 
 	rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp));
-	if (!rdata)
+	if (!rdata) {
+		FC_RPORT_ID_DBG(lport, fc_frame_sid(fp),
+				"Received ELS 0x%02x from non-logged-in port\n",
+				fc_frame_payload_op(fp));
 		goto reject;
+	}
 
 	mutex_lock(&rdata->rp_mutex);
 
@@ -1614,6 +1626,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
 	case RPORT_ST_ADISC:
 		break;
 	default:
+		FC_RPORT_DBG(rdata,
+			     "Reject ELS 0x%02x while in state %s\n",
+			     fc_frame_payload_op(fp), fc_rport_state(rdata));
 		mutex_unlock(&rdata->rp_mutex);
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
 		goto reject;
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 02/24] libfc: spurious I/O error under high load
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 01/24] libfc: additional debugging messages Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 03/24] libfc: use configured lport R_A_TOV Hannes Reinecke
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

If a command times out libfc is sending an REC, which also
might fail (due to frames being lost or something).
If no data has been transferred we can simply retry
the command, but the current code sets a state of FC_ERROR,
which then is being translated into DID_ERROR, resulting
in an I/O error.
So to handle this properly we need to set a separate
state FC_TRANS_RESET and mapping it onto DID_SOFT_RETRY.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_fcp.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 5c6c73a..9f9eb7b 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -122,6 +122,7 @@ struct fc_fcp_internal {
 #define FC_HRD_ERROR		9
 #define FC_CRC_ERROR		10
 #define FC_TIMED_OUT		11
+#define FC_TRANS_RESET		12
 
 /*
  * Error recovery timeout values.
@@ -283,7 +284,7 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
  * fc_io_compl() will notify the SCSI-ml that the I/O is done.
  * The SCSI-ml will retry the command.
  */
-static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
+static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp, int status_code)
 {
 	if (fsp->seq_ptr) {
 		fsp->lp->tt.exch_done(fsp->seq_ptr);
@@ -292,7 +293,7 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
 
 	fsp->state &= ~FC_SRB_ABORT_PENDING;
 	fsp->io_status = 0;
-	fsp->status_code = FC_ERROR;
+	fsp->status_code = status_code;
 	fc_fcp_complete_locked(fsp);
 }
 
@@ -1208,7 +1209,7 @@ static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 		return;
 
 	if (error == -FC_EX_CLOSED) {
-		fc_fcp_retry_cmd(fsp);
+		fc_fcp_retry_cmd(fsp, FC_ERROR);
 		goto unlock;
 	}
 
@@ -1531,10 +1532,11 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
 			 */
 			if (rjt->er_explan == ELS_EXPL_OXID_RXID &&
 			    fsp->xfer_len == 0) {
-				fc_fcp_retry_cmd(fsp);
+				fsp->state |= FC_SRB_ABORTED;
+				fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
 				break;
 			}
-			fc_fcp_recovery(fsp, FC_ERROR);
+			fc_fcp_recovery(fsp, FC_TRANS_RESET);
 			break;
 		}
 	} else if (opcode == ELS_LS_ACC) {
@@ -1630,7 +1632,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 	case -FC_EX_CLOSED:
 		FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n",
 			   fsp, fsp->rport->port_id);
-		fc_fcp_retry_cmd(fsp);
+		fc_fcp_retry_cmd(fsp, FC_ERROR);
 		break;
 
 	default:
@@ -1729,7 +1731,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
 	fc_fcp_pkt_hold(fsp);		/* hold for outstanding SRR */
 	return;
 retry:
-	fc_fcp_retry_cmd(fsp);
+	fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
 }
 
 /**
@@ -1801,7 +1803,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 		FC_FCP_DBG(fsp, "SRR error, exchange closed\n");
 		/* fall through */
 	default:
-		fc_fcp_retry_cmd(fsp);
+		fc_fcp_retry_cmd(fsp, FC_ERROR);
 		break;
 	}
 	fc_fcp_unlock_pkt(fsp);
@@ -2014,6 +2016,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
 			   "due to FC_CMD_RESET\n");
 		sc_cmd->result = (DID_RESET << 16);
 		break;
+	case FC_TRANS_RESET:
+		FC_FCP_DBG(fsp, "Returning DID_SOFT_ERROR to scsi-ml "
+			   "due to FC_TRANS_RESET\n");
+		sc_cmd->result = (DID_SOFT_ERROR << 16);
+		break;
 	case FC_HRD_ERROR:
 		FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml "
 			   "due to FC_HRD_ERROR\n");
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 03/24] libfc: use configured lport R_A_TOV
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 01/24] libfc: additional debugging messages Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 02/24] libfc: spurious I/O error under high load Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 04/24] libfc: use configured rport E_D_TOV Hannes Reinecke
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

We should be using the configured R_A_TOV value when sending the
exchange.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_exch.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index b4bdc90..5e0a57f 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -2135,7 +2135,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport,
 	ep->resp = resp;
 	ep->destructor = destructor;
 	ep->arg = arg;
-	ep->r_a_tov = FC_DEF_R_A_TOV;
+	ep->r_a_tov = lport->r_a_tov;
 	ep->lp = lport;
 	sp = &ep->seq;
 
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 04/24] libfc: use configured rport E_D_TOV
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (2 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 03/24] libfc: use configured lport R_A_TOV Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 05/24] libfc: sanitize E_D_TOV and R_A_TOV setting Hannes Reinecke
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

If fc_rport_error_retry() is attempting to retry the remote
port state we should be waiting for the configured e_d_tov
value rather than the default.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_rport.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index bcd1cd3..bb7e9d9 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -662,7 +662,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
 static void fc_rport_error_retry(struct fc_rport_priv *rdata,
 				 struct fc_frame *fp)
 {
-	unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV);
+	unsigned long delay = msecs_to_jiffies(rdata->e_d_tov);
 	struct fc_lport *lport = rdata->local_port;
 
 	/* make sure this isn't an FC_EX_CLOSED error, never retry those */
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 05/24] libfc: sanitize E_D_TOV and R_A_TOV setting
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (3 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 04/24] libfc: use configured rport E_D_TOV Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:42   ` Johannes Thumshirn
  2016-10-13 13:10 ` [PATCH 06/24] fcoe: make R_A_TOV and E_D_TOV configurable Hannes Reinecke
                   ` (20 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

When setting the FCP timeout we need to ensure a lower boundary
for E_D_TOV and R_A_TOV, otherwise we'd be getting spurious I/O
issues due to the fcp timer firing too early.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_fcp.c   | 9 +++++----
 drivers/scsi/libfc/fc_lport.c | 8 +++++---
 drivers/scsi/libfc/fc_rport.c | 6 ++++--
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 9f9eb7b..10faca2 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1137,8 +1137,11 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
 static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
 {
 	struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
+	unsigned int e_d_tov = FC_DEF_E_D_TOV;
 
-	return msecs_to_jiffies(rpriv->e_d_tov) + HZ;
+	if (rpriv && rpriv->e_d_tov > e_d_tov)
+		e_d_tov = rpriv->e_d_tov;
+	return msecs_to_jiffies(e_d_tov) + HZ;
 }
 
 /**
@@ -1693,7 +1696,6 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
 	struct fc_seq *seq;
 	struct fcp_srr *srr;
 	struct fc_frame *fp;
-	unsigned int rec_tov;
 
 	rport = fsp->rport;
 	rpriv = rport->dd_data;
@@ -1717,10 +1719,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
 		       rpriv->local_port->port_id, FC_TYPE_FCP,
 		       FC_FCTL_REQ, 0);
 
-	rec_tov = get_fsp_rec_tov(fsp);
 	seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp,
 				      fc_fcp_pkt_destroy,
-				      fsp, jiffies_to_msecs(rec_tov));
+				      fsp, get_fsp_rec_tov(fsp));
 	if (!seq)
 		goto retry;
 
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 4e11c90..81ad8ac 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1777,7 +1777,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 	if ((csp_flags & FC_SP_FT_FPORT) == 0) {
 		if (e_d_tov > lport->e_d_tov)
 			lport->e_d_tov = e_d_tov;
-		lport->r_a_tov = 2 * e_d_tov;
+		lport->r_a_tov = 2 * lport->e_d_tov;
 		fc_lport_set_port_id(lport, did, fp);
 		printk(KERN_INFO "host%d: libfc: "
 		       "Port (%6.6x) entered "
@@ -1789,8 +1789,10 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 				   get_unaligned_be64(
 					   &flp->fl_wwnn));
 	} else {
-		lport->e_d_tov = e_d_tov;
-		lport->r_a_tov = r_a_tov;
+		if (e_d_tov > lport->e_d_tov)
+			lport->e_d_tov = e_d_tov;
+		if (r_a_tov > lport->r_a_tov)
+			lport->r_a_tov = r_a_tov;
 		fc_host_fabric_name(lport->host) =
 			get_unaligned_be64(&flp->fl_wwnn);
 		fc_lport_set_port_id(lport, did, fp);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index bb7e9d9..3d2baba 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1296,13 +1296,15 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
 			tov = ntohl(rtv->rtv_r_a_tov);
 			if (tov == 0)
 				tov = 1;
-			rdata->r_a_tov = tov;
+			if (tov > rdata->r_a_tov)
+				rdata->r_a_tov = tov;
 			tov = ntohl(rtv->rtv_e_d_tov);
 			if (toq & FC_ELS_RTV_EDRES)
 				tov /= 1000000;
 			if (tov == 0)
 				tov = 1;
-			rdata->e_d_tov = tov;
+			if (tov > rdata->e_d_tov)
+				rdata->e_d_tov = tov;
 		}
 	}
 
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 06/24] fcoe: make R_A_TOV and E_D_TOV configurable
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (4 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 05/24] libfc: sanitize E_D_TOV and R_A_TOV setting Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 07/24] libfc: do not overwrite DID_TIME_OUT status Hannes Reinecke
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

The user might want to modify the values for R_A_TOV and E_D_TOV,
so add new module parameters 'e_d_tov' and 'r_a_tov' for the
'fcoe' modules and allow to modify them via sysfs attributes.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/fcoe/fcoe.c       | 12 +++++--
 drivers/scsi/fcoe/fcoe_sysfs.c | 71 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 9bd41a3..c907661 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -63,6 +63,14 @@
 module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
 
+unsigned int fcoe_e_d_tov = 2 * 1000;
+module_param_named(e_d_tov, fcoe_e_d_tov, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(e_d_tov, "E_D_TOV in ms, default 2000");
+
+unsigned int fcoe_r_a_tov = 2 * 2 * 1000;
+module_param_named(r_a_tov, fcoe_r_a_tov, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(r_a_tov, "R_A_TOV in ms, default 4000");
+
 static DEFINE_MUTEX(fcoe_config_mutex);
 
 static struct workqueue_struct *fcoe_wq;
@@ -633,8 +641,8 @@ static int fcoe_lport_config(struct fc_lport *lport)
 	lport->qfull = 0;
 	lport->max_retry_count = 3;
 	lport->max_rport_retry_count = 3;
-	lport->e_d_tov = 2 * 1000;	/* FC-FS default */
-	lport->r_a_tov = 2 * 2 * 1000;
+	lport->e_d_tov = fcoe_e_d_tov;
+	lport->r_a_tov = fcoe_r_a_tov;
 	lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
 				 FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
 	lport->does_npiv = 1;
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 0675fd1..9e6baac 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -424,6 +424,75 @@ static FCOE_DEVICE_ATTR(ctlr, fip_vlan_responder, S_IRUGO | S_IWUSR,
 			store_ctlr_fip_resp);
 
 static ssize_t
+fcoe_ctlr_var_store(u32 *var, const char *buf, size_t count)
+{
+	int err;
+	unsigned long v;
+
+	err = kstrtoul(buf, 10, &v);
+	if (err || v > UINT_MAX)
+		return -EINVAL;
+
+	*var = v;
+
+	return count;
+}
+
+static ssize_t store_ctlr_r_a_tov(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+	struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+	if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
+		return -EBUSY;
+	if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
+		return fcoe_ctlr_var_store(&ctlr->lp->r_a_tov, buf, count);
+	return -ENOTSUPP;
+}
+
+static ssize_t show_ctlr_r_a_tov(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+	struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+	return sprintf(buf, "%d\n", ctlr->lp->r_a_tov);
+}
+
+static FCOE_DEVICE_ATTR(ctlr, r_a_tov, S_IRUGO | S_IWUSR,
+			show_ctlr_r_a_tov, store_ctlr_r_a_tov);
+
+static ssize_t store_ctlr_e_d_tov(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+	struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+	if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
+		return -EBUSY;
+	if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
+		return fcoe_ctlr_var_store(&ctlr->lp->e_d_tov, buf, count);
+	return -ENOTSUPP;
+}
+
+static ssize_t show_ctlr_e_d_tov(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+	struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+	return sprintf(buf, "%d\n", ctlr->lp->e_d_tov);
+}
+
+static FCOE_DEVICE_ATTR(ctlr, e_d_tov, S_IRUGO | S_IWUSR,
+			show_ctlr_e_d_tov, store_ctlr_e_d_tov);
+
+static ssize_t
 store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
 					 struct device_attribute *attr,
 					 const char *buf, size_t count)
@@ -507,6 +576,8 @@ static FCOE_DEVICE_ATTR(fcf, dev_loss_tmo, S_IRUGO | S_IWUSR,
 static struct attribute *fcoe_ctlr_attrs[] = {
 	&device_attr_fcoe_ctlr_fip_vlan_responder.attr,
 	&device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
+	&device_attr_fcoe_ctlr_r_a_tov.attr,
+	&device_attr_fcoe_ctlr_e_d_tov.attr,
 	&device_attr_fcoe_ctlr_enabled.attr,
 	&device_attr_fcoe_ctlr_mode.attr,
 	NULL,
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 07/24] libfc: do not overwrite DID_TIME_OUT status
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (5 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 06/24] fcoe: make R_A_TOV and E_D_TOV configurable Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 08/24] libfc: use error code for fc_rport_error() Hannes Reinecke
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

When a command is aborted it might already have the DID_TIME_OUT
status set, so we shouldn't be overwriting that.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_fcp.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 10faca2..0e2a201 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -2008,9 +2008,15 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
 		sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status;
 		break;
 	case FC_CMD_ABORTED:
-		FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
-			  "due to FC_CMD_ABORTED\n");
-		sc_cmd->result = (DID_ERROR << 16) | fsp->io_status;
+		if (host_byte(sc_cmd->result) == DID_TIME_OUT)
+			FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml "
+				   "due to FC_CMD_ABORTED\n");
+		else {
+			FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
+				   "due to FC_CMD_ABORTED\n");
+			set_host_byte(sc_cmd, DID_ERROR);
+		}
+		sc_cmd->result |= fsp->io_status;
 		break;
 	case FC_CMD_RESET:
 		FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml "
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 08/24] libfc: use error code for fc_rport_error()
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (6 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 07/24] libfc: do not overwrite DID_TIME_OUT status Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 09/24] libfc: Implement RTV responder Hannes Reinecke
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

We only ever use the 'fp' argument for fc_rport_error() to
encapsulate the error code, so we can as well do away with that
and pass the error directly.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_rport.c | 101 +++++++++++++++++++++++++-----------------
 include/scsi/libfc.h          |   5 +++
 2 files changed, 66 insertions(+), 40 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 3d2baba..d2d8607 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -87,8 +87,8 @@
 static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *);
 static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *);
 static void fc_rport_timeout(struct work_struct *);
-static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *);
-static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *);
+static void fc_rport_error(struct fc_rport_priv *, int);
+static void fc_rport_error_retry(struct fc_rport_priv *, int);
 static void fc_rport_work(struct work_struct *);
 
 static const char *fc_rport_state_names[] = {
@@ -604,20 +604,19 @@ static void fc_rport_timeout(struct work_struct *work)
 /**
  * fc_rport_error() - Error handler, called once retries have been exhausted
  * @rdata: The remote port the error is happened on
- * @fp:	   The error code encapsulated in a frame pointer
+ * @err:   The error code
  *
  * Locking Note: The rport lock is expected to be held before
  * calling this routine
  *
  * Reference counting: does not modify kref
  */
-static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
+static void fc_rport_error(struct fc_rport_priv *rdata, int err)
 {
 	struct fc_lport *lport = rdata->local_port;
 
-	FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n",
-		     IS_ERR(fp) ? -PTR_ERR(fp) : 0,
-		     fc_rport_state(rdata), rdata->retries);
+	FC_RPORT_DBG(rdata, "Error %d in state %s, retries %d\n",
+		     -err, fc_rport_state(rdata), rdata->retries);
 
 	switch (rdata->rp_state) {
 	case RPORT_ST_FLOGI:
@@ -649,7 +648,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
 /**
  * fc_rport_error_retry() - Handler for remote port state retries
  * @rdata: The remote port whose state is to be retried
- * @fp:	   The error code encapsulated in a frame pointer
+ * @err:   The error code
  *
  * If the error was an exchange timeout retry immediately,
  * otherwise wait for E_D_TOV.
@@ -659,22 +658,21 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
  *
  * Reference counting: increments kref when scheduling retry_work
  */
-static void fc_rport_error_retry(struct fc_rport_priv *rdata,
-				 struct fc_frame *fp)
+static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err)
 {
 	unsigned long delay = msecs_to_jiffies(rdata->e_d_tov);
 	struct fc_lport *lport = rdata->local_port;
 
 	/* make sure this isn't an FC_EX_CLOSED error, never retry those */
-	if (PTR_ERR(fp) == -FC_EX_CLOSED)
+	if (err == -FC_EX_CLOSED)
 		goto out;
 
 	if (rdata->retries < rdata->local_port->max_rport_retry_count) {
-		FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n",
-			     PTR_ERR(fp), fc_rport_state(rdata));
+		FC_RPORT_DBG(rdata, "Error %d in state %s, retrying\n",
+			     err, fc_rport_state(rdata));
 		rdata->retries++;
 		/* no additional delay on exchange timeouts */
-		if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
+		if (err == -FC_EX_TIMEOUT)
 			delay = 0;
 		kref_get(&rdata->kref);
 		if (!schedule_delayed_work(&rdata->retry_work, delay))
@@ -683,7 +681,7 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
 	}
 
 out:
-	fc_rport_error(rdata, fp);
+	fc_rport_error(rdata, err);
 }
 
 /**
@@ -743,8 +741,11 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 	struct fc_lport *lport = rdata->local_port;
 	struct fc_els_flogi *flogi;
 	unsigned int r_a_tov;
+	u8 opcode;
+	int err = 0;
 
-	FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp));
+	FC_RPORT_DBG(rdata, "Received a FLOGI %s\n",
+		     IS_ERR(fp) ? "error" : fc_els_resp_type(fp));
 
 	if (fp == ERR_PTR(-FC_EX_CLOSED))
 		goto put;
@@ -760,18 +761,32 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error(rdata, fp);
+		fc_rport_error(rdata, PTR_ERR(fp));
 		goto err;
 	}
+	opcode = fc_frame_payload_op(fp);
+	if (opcode == ELS_LS_RJT) {
+		struct fc_els_ls_rjt *rjt;
 
-	if (fc_frame_payload_op(fp) != ELS_LS_ACC)
+		rjt = fc_frame_payload_get(fp, sizeof(*rjt));
+		FC_RPORT_DBG(rdata, "FLOGI ELS rejected, reason %x expl %x\n",
+			     rjt->er_reason, rjt->er_explan);
+		err = -FC_EX_ELS_RJT;
+		goto bad;
+	} else if (opcode != ELS_LS_ACC) {
+		FC_RPORT_DBG(rdata, "FLOGI ELS invalid opcode %x\n", opcode);
+		err = -FC_EX_ELS_RJT;
 		goto bad;
-	if (fc_rport_login_complete(rdata, fp))
+	}
+	if (fc_rport_login_complete(rdata, fp)) {
+		FC_RPORT_DBG(rdata, "FLOGI failed, no login\n");
+		err = -FC_EX_INV_LOGIN;
 		goto bad;
+	}
 
 	flogi = fc_frame_payload_get(fp, sizeof(*flogi));
 	if (!flogi) {
-		FC_RPORT_DBG(rdata, "Bad FLOGI response\n");
+		err = -FC_EX_ALLOC_ERR;
 		goto bad;
 	}
 	r_a_tov = ntohl(flogi->fl_csp.sp_r_a_tov);
@@ -790,7 +805,8 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 	kref_put(&rdata->kref, lport->tt.rport_destroy);
 	return;
 bad:
-	fc_rport_error_retry(rdata, fp);
+	FC_RPORT_DBG(rdata, "Bad FLOGI response\n");
+	fc_rport_error_retry(rdata, err);
 	goto out;
 }
 
@@ -818,13 +834,13 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata)
 
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
 	if (!fp)
-		return fc_rport_error_retry(rdata, fp);
+		return fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
 
 	kref_get(&rdata->kref);
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI,
 				  fc_rport_flogi_resp, rdata,
 				  2 * lport->r_a_tov)) {
-		fc_rport_error_retry(rdata, NULL);
+		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
 	}
 }
@@ -991,7 +1007,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, PTR_ERR(fp));
 		goto err;
 	}
 
@@ -1013,9 +1029,14 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 		rdata->max_seq = csp_seq;
 		rdata->maxframe_size = fc_plogi_get_maxframe(plp, lport->mfs);
 		fc_rport_enter_prli(rdata);
-	} else
-		fc_rport_error_retry(rdata, fp);
+	} else {
+		struct fc_els_ls_rjt *rjt;
 
+		rjt = fc_frame_payload_get(fp, sizeof(*rjt));
+		FC_RPORT_DBG(rdata, "PLOGI ELS rejected, reason %x expl %x\n",
+			     rjt->er_reason, rjt->er_explan);
+		fc_rport_error_retry(rdata, -FC_EX_ELS_RJT);
+	}
 out:
 	fc_frame_free(fp);
 err:
@@ -1067,7 +1088,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
 	if (!fp) {
 		FC_RPORT_DBG(rdata, "%s frame alloc failed\n", __func__);
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
 		return;
 	}
 	rdata->e_d_tov = lport->e_d_tov;
@@ -1076,7 +1097,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI,
 				  fc_rport_plogi_resp, rdata,
 				  2 * lport->r_a_tov)) {
-		fc_rport_error_retry(rdata, NULL);
+		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
 	}
 }
@@ -1123,7 +1144,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, PTR_ERR(fp));
 		goto err;
 	}
 
@@ -1142,9 +1163,9 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		rdata->spp_type = pp->spp.spp_type;
 		if (resp_code != FC_SPP_RESP_ACK) {
 			if (resp_code == FC_SPP_RESP_CONF)
-				fc_rport_error(rdata, fp);
+				fc_rport_error(rdata, -FC_EX_SEQ_ERR);
 			else
-				fc_rport_error_retry(rdata, fp);
+				fc_rport_error_retry(rdata, -FC_EX_SEQ_ERR);
 			goto out;
 		}
 		if (pp->prli.prli_spp_len < sizeof(pp->spp))
@@ -1176,7 +1197,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		rjt = fc_frame_payload_get(fp, sizeof(*rjt));
 		FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n",
 			     rjt->er_reason, rjt->er_explan);
-		fc_rport_error_retry(rdata, NULL);
+		fc_rport_error_retry(rdata, FC_EX_ELS_RJT);
 	}
 
 out:
@@ -1222,7 +1243,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 
 	fp = fc_frame_alloc(lport, sizeof(*pp));
 	if (!fp) {
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
 		return;
 	}
 
@@ -1241,7 +1262,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 	kref_get(&rdata->kref);
 	if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp,
 				     NULL, rdata, 2 * lport->r_a_tov)) {
-		fc_rport_error_retry(rdata, NULL);
+		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
 	}
 }
@@ -1280,7 +1301,7 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error(rdata, fp);
+		fc_rport_error(rdata, PTR_ERR(fp));
 		goto err;
 	}
 
@@ -1339,7 +1360,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
 
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv));
 	if (!fp) {
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
 		return;
 	}
 
@@ -1347,7 +1368,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV,
 				  fc_rport_rtv_resp, rdata,
 				  2 * lport->r_a_tov)) {
-		fc_rport_error_retry(rdata, NULL);
+		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
 	}
 }
@@ -1430,7 +1451,7 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp,
 	}
 
 	if (IS_ERR(fp)) {
-		fc_rport_error(rdata, fp);
+		fc_rport_error(rdata, PTR_ERR(fp));
 		goto err;
 	}
 
@@ -1480,14 +1501,14 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
 
 	fp = fc_frame_alloc(lport, sizeof(struct fc_els_adisc));
 	if (!fp) {
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR);
 		return;
 	}
 	kref_get(&rdata->kref);
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC,
 				  fc_rport_adisc_resp, rdata,
 				  2 * lport->r_a_tov)) {
-		fc_rport_error_retry(rdata, NULL);
+		fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR);
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
 	}
 }
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 7428a53..dc42d80 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -44,6 +44,11 @@
 #define	FC_NO_ERR	0	/* no error */
 #define	FC_EX_TIMEOUT	1	/* Exchange timeout */
 #define	FC_EX_CLOSED	2	/* Exchange closed */
+#define FC_EX_ALLOC_ERR	3	/* Exchange allocation failed */
+#define FC_EX_XMIT_ERR	4	/* Exchange transmit failed */
+#define FC_EX_ELS_RJT	5	/* ELS rejected */
+#define FC_EX_INV_LOGIN	6	/* Login not completed */
+#define FC_EX_SEQ_ERR	6	/* Exchange sequence error */
 
 /**
  * enum fc_lport_state - Local port states
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 09/24] libfc: Implement RTV responder
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (7 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 08/24] libfc: use error code for fc_rport_error() Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 10/24] libfc: Rework PRLI handling Hannes Reinecke
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

The libfc stack generates an RTV request, so we should be implementing
an RTV responder, too.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_rport.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index d2d8607..426c399 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1268,7 +1268,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 }
 
 /**
- * fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses
+ * fc_rport_rtv_resp() - Handler for Request Timeout Value (RTV) responses
  * @sp:	       The sequence the RTV was on
  * @fp:	       The RTV response frame
  * @rdata_arg: The remote port that sent the RTV response
@@ -1374,6 +1374,41 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata)
 }
 
 /**
+ * fc_rport_recv_rtv_req() - Handler for Read Timeout Value (RTV) requests
+ * @rdata: The remote port that sent the RTV request
+ * @in_fp: The RTV request frame
+ *
+ * Locking Note:  Called with the lport and rport locks held.
+ */
+static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata,
+				  struct fc_frame *in_fp)
+{
+	struct fc_lport *lport = rdata->local_port;
+	struct fc_frame *fp;
+	struct fc_els_rtv_acc *rtv;
+	struct fc_seq_els_data rjt_data;
+
+	FC_RPORT_DBG(rdata, "Received RTV request\n");
+
+	fp = fc_frame_alloc(lport, sizeof(*rtv));
+	if (!fp) {
+		rjt_data.reason = ELS_RJT_UNAB;
+		rjt_data.reason = ELS_EXPL_INSUF_RES;
+		lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);
+		goto drop;
+	}
+	rtv = fc_frame_payload_get(fp, sizeof(*rtv));
+	rtv->rtv_cmd = ELS_LS_ACC;
+	rtv->rtv_r_a_tov = htonl(lport->r_a_tov);
+	rtv->rtv_e_d_tov = htonl(lport->e_d_tov);
+	rtv->rtv_toq = 0;
+	fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0);
+	lport->tt.frame_send(lport, fp);
+drop:
+	fc_frame_free(in_fp);
+}
+
+/**
  * fc_rport_logo_resp() - Handler for logout (LOGO) responses
  * @sp:	       The sequence the LOGO was on
  * @fp:	       The LOGO response frame
@@ -1678,6 +1713,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
 	case ELS_RLS:
 		fc_rport_recv_rls_req(rdata, fp);
 		break;
+	case ELS_RTV:
+		fc_rport_recv_rtv_req(rdata, fp);
+		break;
 	default:
 		fc_frame_free(fp);	/* can't happen */
 		break;
@@ -1729,6 +1767,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
 	case ELS_RRQ:
 	case ELS_REC:
 	case ELS_RLS:
+	case ELS_RTV:
 		fc_rport_recv_els_req(lport, fp);
 		break;
 	default:
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 10/24] libfc: Rework PRLI handling
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (8 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 09/24] libfc: Implement RTV responder Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 14:02   ` Johannes Thumshirn
  2016-10-13 13:10 ` [PATCH 11/24] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Hannes Reinecke
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

PRLI is only required if the port is acting as an initiator; ports
which support target functionality only do not need to send PRLI.
At the same time the PRLI state is only used if the port initiated
a PRLI transfer; if we received a PRLI request we should _not_
change the state as this would cause our PRLI response to be dropped.
And when we receive a PRLI response we need to check if an image
pair has been established; if not the remote port cannot act as a
target for us and we need to disable target functionality.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_rport.c | 56 +++++++++++++++++++++++++++++--------------
 1 file changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 426c399..2b8214f 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1126,7 +1126,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 	u32 roles = FC_RPORT_ROLE_UNKNOWN;
 	u32 fcp_parm = 0;
 	u8 op;
-	u8 resp_code = 0;
+	enum fc_els_spp_resp resp_code;
 
 	FC_RPORT_DBG(rdata, "Received a PRLI %s\n", fc_els_resp_type(fp));
 
@@ -1158,8 +1158,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 			goto out;
 
 		resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
-		FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
-			     pp->spp.spp_flags);
+		FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x spp_type 0x%x\n",
+			     pp->spp.spp_flags, pp->spp.spp_type);
 		rdata->spp_type = pp->spp.spp_type;
 		if (resp_code != FC_SPP_RESP_ACK) {
 			if (resp_code == FC_SPP_RESP_CONF)
@@ -1177,13 +1177,26 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		if (fcp_parm & FCP_SPPF_CONF_COMPL)
 			rdata->flags |= FC_RP_FLAGS_CONF_REQ;
 
-		prov = fc_passive_prov[FC_TYPE_FCP];
+		/*
+		 * Call prli provider if we should act as a target
+		 */
+		prov = fc_passive_prov[rdata->spp_type];
 		if (prov) {
 			memset(&temp_spp, 0, sizeof(temp_spp));
 			prov->prli(rdata, pp->prli.prli_spp_len,
 				   &pp->spp, &temp_spp);
 		}
-
+		/*
+		 * Check if the image pair could be established
+		 */
+		if (rdata->spp_type != FC_TYPE_FCP ||
+		    resp_code != FC_SPP_RESP_ACK ||
+		    !(pp->spp.spp_flags & FC_SPP_EST_IMG_PAIR)) {
+			/*
+			 * Nope; we can't use this port as a target.
+			 */
+			fcp_parm &= ~FCP_SPPF_TARG_FCN;
+		}
 		rdata->supported_classes = FC_COS_CLASS3;
 		if (fcp_parm & FCP_SPPF_INIT_FCN)
 			roles |= FC_RPORT_ROLE_FCP_INITIATOR;
@@ -1236,6 +1249,15 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 		return;
 	}
 
+	/*
+	 * And if the local port does not support the initiator function
+	 * there's no need to send a PRLI, either.
+	 */
+	if (!(lport->service_params & FCP_SPPF_INIT_FCN)) {
+		    fc_rport_enter_ready(rdata);
+		    return;
+	}
+
 	FC_RPORT_DBG(rdata, "Port entered PRLI state from %s state\n",
 		     fc_rport_state(rdata));
 
@@ -1926,7 +1948,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 	unsigned int len;
 	unsigned int plen;
 	enum fc_els_spp_resp resp;
-	enum fc_els_spp_resp passive;
 	struct fc_seq_els_data rjt_data;
 	struct fc4_prov *prov;
 
@@ -1976,15 +1997,21 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 		resp = 0;
 
 		if (rspp->spp_type < FC_FC4_PROV_SIZE) {
+			enum fc_els_spp_resp active = 0, passive = 0;
+
 			prov = fc_active_prov[rspp->spp_type];
 			if (prov)
-				resp = prov->prli(rdata, plen, rspp, spp);
+				active = prov->prli(rdata, plen, rspp, spp);
 			prov = fc_passive_prov[rspp->spp_type];
-			if (prov) {
+			if (prov)
 				passive = prov->prli(rdata, plen, rspp, spp);
-				if (!resp || passive == FC_SPP_RESP_ACK)
-					resp = passive;
-			}
+			if (!active || passive == FC_SPP_RESP_ACK)
+				resp = passive;
+			else
+				resp = active;
+			FC_RPORT_DBG(rdata, "PRLI rspp type %x "
+				     "active %x passive %x\n",
+				     rspp->spp_type, active, passive);
 		}
 		if (!resp) {
 			if (spp->spp_flags & FC_SPP_EST_IMG_PAIR)
@@ -2005,13 +2032,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 	fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
 	lport->tt.frame_send(lport, fp);
 
-	switch (rdata->rp_state) {
-	case RPORT_ST_PRLI:
-		fc_rport_enter_ready(rdata);
-		break;
-	default:
-		break;
-	}
 	goto drop;
 
 reject_len:
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 11/24] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (9 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 10/24] libfc: Rework PRLI handling Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-14 21:25   ` Bart Van Assche
  2016-10-13 13:10 ` [PATCH 12/24] libfc: Clarify ramp-down messages Hannes Reinecke
                   ` (14 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

Occasionally it might happen that we receive a PRLI while we're still
waiting for our PLOGI response. In that case we should return
'busy' LS status instead of 'plogi required' LS status.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_rport.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 2b8214f..a867874 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1705,6 +1705,15 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
 	case RPORT_ST_READY:
 	case RPORT_ST_ADISC:
 		break;
+	case RPORT_ST_PLOGI:
+		if (fc_frame_payload_op(fp) == ELS_PRLI) {
+			FC_RPORT_DBG(rdata, "Reject ELS PRLI "
+				     "while in state %s\n",
+				     fc_rport_state(rdata));
+			mutex_unlock(&rdata->rp_mutex);
+			kref_put(&rdata->kref, lport->tt.rport_destroy);
+			goto busy;
+		}
 	default:
 		FC_RPORT_DBG(rdata,
 			     "Reject ELS 0x%02x while in state %s\n",
@@ -1752,6 +1761,14 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
 	els_data.explan = ELS_EXPL_PLOGI_REQD;
 	lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);
 	fc_frame_free(fp);
+	return;
+
+busy:
+	els_data.reason = ELS_RJT_BUSY;
+	els_data.explan = ELS_EXPL_NONE;
+	lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);
+	fc_frame_free(fp);
+	return;
 }
 
 /**
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 12/24] libfc: Clarify ramp-down messages
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (10 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 11/24] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 14:06   ` Johannes Thumshirn
  2016-10-13 13:10 ` [PATCH 13/24] libfc: safeguard against invalid exchange index Hannes Reinecke
                   ` (13 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

When the queue depth is reduced we should print out the reason
for this; it might be due to a queue full condition.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_fcp.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 0e2a201..f7700cc 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -403,8 +403,6 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
 	if (!can_queue)
 		can_queue = 1;
 	lport->host->can_queue = can_queue;
-	shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n"
-		     "Reducing can_queue to %d.\n", can_queue);
 
 unlock:
 	spin_unlock_irqrestore(lport->host->host_lock, flags);
@@ -431,6 +429,9 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
 	put_cpu();
 	/* error case */
 	fc_fcp_can_queue_ramp_down(lport);
+	shost_printk(KERN_ERR, lport->host,
+		     "libfc: Could not allocate frame, "
+		     "reducing can_queue to %d.\n", lport->host->can_queue);
 	return NULL;
 }
 
@@ -1860,8 +1861,13 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
 	rpriv = rport->dd_data;
 
 	if (!fc_fcp_lport_queue_ready(lport)) {
-		if (lport->qfull)
+		if (lport->qfull) {
 			fc_fcp_can_queue_ramp_down(lport);
+			shost_printk(KERN_ERR, lport->host,
+				     "libfc: queue full, "
+				     "reducing can_queue to %d.\n",
+				     lport->host->can_queue);
+		}
 		rc = SCSI_MLQUEUE_HOST_BUSY;
 		goto out;
 	}
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 13/24] libfc: safeguard against invalid exchange index
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (11 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 12/24] libfc: Clarify ramp-down messages Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-14 21:27   ` Bart Van Assche
  2016-10-13 13:10 ` [PATCH 14/24] libfc: quarantine timed out xids Hannes Reinecke
                   ` (12 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

The cached exchange index might be invalid, in which case
we should drop down to allocate a new one.
And we should not try to access an invalid exchange when
responding to a BA_ABTS.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_exch.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 5e0a57f..e8784a7 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -827,14 +827,18 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
 
 	/* peek cache of free slot */
 	if (pool->left != FC_XID_UNKNOWN) {
-		index = pool->left;
-		pool->left = FC_XID_UNKNOWN;
-		goto hit;
+		if (!WARN_ON(fc_exch_ptr_get(pool, pool->left))) {
+			index = pool->left;
+			pool->left = FC_XID_UNKNOWN;
+			goto hit;
+		}
 	}
 	if (pool->right != FC_XID_UNKNOWN) {
-		index = pool->right;
-		pool->right = FC_XID_UNKNOWN;
-		goto hit;
+		if (!WARN_ON(fc_exch_ptr_get(pool, pool->right))) {
+			index = pool->right;
+			pool->right = FC_XID_UNKNOWN;
+			goto hit;
+		}
 	}
 
 	index = pool->next_index;
@@ -1777,7 +1781,10 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp)
 				fc_frame_free(fp);
 			break;
 		case FC_RCTL_BA_ABTS:
-			fc_exch_recv_abts(ep, fp);
+			if (ep)
+				fc_exch_recv_abts(ep, fp);
+			else
+				fc_frame_free(fp);
 			break;
 		default:			/* ignore junk */
 			fc_frame_free(fp);
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 14/24] libfc: quarantine timed out xids
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (12 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 13/24] libfc: safeguard against invalid exchange index Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-14 21:33   ` Bart Van Assche
  2016-10-13 13:10 ` [PATCH 15/24] libfc: don't fail sequence abort for completed exchanges Hannes Reinecke
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

When a sequence times out we have no idea what happened to the
frame. And we do not know if we will ever receive the frame.
Hence we cannot re-use the xid as we would risk data corruption
if the xid had been re-used and the timed out frame would be
received after that.
So we need to quarantine the xid until the lport is reset.
Yes, I know this will (eventually) deplete the xid pool.
But for now it's the safest method.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_exch.c | 33 ++++++++++++++++++++++-----------
 drivers/scsi/libfc/fc_fcp.c  | 13 +++++++------
 include/scsi/libfc.h         |  1 +
 3 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index e8784a7..5868824 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -94,6 +94,7 @@ struct fc_exch_pool {
 struct fc_exch_mgr {
 	struct fc_exch_pool __percpu *pool;
 	mempool_t	*ep_pool;
+	struct fc_lport	*lport;
 	enum fc_class	class;
 	struct kref	kref;
 	u16		min_xid;
@@ -408,6 +409,8 @@ static int fc_exch_done_locked(struct fc_exch *ep)
 	return rc;
 }
 
+static struct fc_exch fc_quarantine_exch;
+
 /**
  * fc_exch_ptr_get() - Return an exchange from an exchange pool
  * @pool:  Exchange Pool to get an exchange from
@@ -452,14 +455,17 @@ static void fc_exch_delete(struct fc_exch *ep)
 
 	/* update cache of free slot */
 	index = (ep->xid - ep->em->min_xid) >> fc_cpu_order;
-	if (pool->left == FC_XID_UNKNOWN)
-		pool->left = index;
-	else if (pool->right == FC_XID_UNKNOWN)
-		pool->right = index;
-	else
-		pool->next_index = index;
-
-	fc_exch_ptr_set(pool, index, NULL);
+	if (!(ep->state & FC_EX_QUARANTINE)) {
+		if (pool->left == FC_XID_UNKNOWN)
+			pool->left = index;
+		else if (pool->right == FC_XID_UNKNOWN)
+			pool->right = index;
+		else
+			pool->next_index = index;
+		fc_exch_ptr_set(pool, index, NULL);
+	} else {
+		fc_exch_ptr_set(pool, index, &fc_quarantine_exch);
+	}
 	list_del(&ep->ex_list);
 	spin_unlock_bh(&pool->lock);
 	fc_exch_release(ep);	/* drop hold for exch in mp */
@@ -916,14 +922,14 @@ static inline struct fc_exch *fc_exch_alloc(struct fc_lport *lport,
  */
 static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
 {
+	struct fc_lport *lport = mp->lport;
 	struct fc_exch_pool *pool;
 	struct fc_exch *ep = NULL;
 	u16 cpu = xid & fc_cpu_mask;
 
 	if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) {
-		printk_ratelimited(KERN_ERR
-			"libfc: lookup request for XID = %d, "
-			"indicates invalid CPU %d\n", xid, cpu);
+		pr_err("host%u: lport %6.6x: xid %d invalid CPU %d\n:",
+		       lport->host->host_no, lport->port_id, xid, cpu);
 		return NULL;
 	}
 
@@ -931,6 +937,10 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
 		pool = per_cpu_ptr(mp->pool, cpu);
 		spin_lock_bh(&pool->lock);
 		ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order);
+		if (ep == &fc_quarantine_exch) {
+			FC_LPORT_DBG(lport, "xid %x quarantined\n", xid);
+			ep = NULL;
+		}
 		if (ep) {
 			WARN_ON(ep->xid != xid);
 			fc_exch_hold(ep);
@@ -2429,6 +2439,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
 		return NULL;
 
 	mp->class = class;
+	mp->lport = lport;
 	/* adjust em exch xid range for offload */
 	mp->min_xid = min_xid;
 
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index f7700cc..780d9f0 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1529,13 +1529,14 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
 				   fsp->rport->port_id, rjt->er_reason,
 				   rjt->er_explan);
 			/*
-			 * If no data transfer, the command frame got dropped
-			 * so we just retry.  If data was transferred, we
-			 * lost the response but the target has no record,
-			 * so we abort and retry.
+			 * If response got lost or is stuck in the
+			 * queue somewhere we have no idea if and when
+			 * the response will be received. So quarantine
+			 * the xid and retry the command.
 			 */
-			if (rjt->er_explan == ELS_EXPL_OXID_RXID &&
-			    fsp->xfer_len == 0) {
+			if (rjt->er_explan == ELS_EXPL_OXID_RXID) {
+				struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr);
+				ep->state |= FC_EX_QUARANTINE;
 				fsp->state |= FC_SRB_ABORTED;
 				fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
 				break;
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index dc42d80..8cb752f 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -390,6 +390,7 @@ struct fc_seq {
 
 #define FC_EX_DONE		(1 << 0) /* ep is completed */
 #define FC_EX_RST_CLEANUP	(1 << 1) /* reset is forcing completion */
+#define FC_EX_QUARANTINE	(1 << 2) /* exch is quarantined */
 
 /**
  * struct fc_exch - Fibre Channel Exchange
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 15/24] libfc: don't fail sequence abort for completed exchanges
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (13 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 14/24] libfc: quarantine timed out xids Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 16/24] libfc: Do not drop out-of-order frames Hannes Reinecke
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

If a sequence should be aborted the exchange might already
be completed (eg if the response is still queued in the rx
queue), so this shouldn't considered as an error.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_fcp.c | 40 ++++++++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 780d9f0..d43c925 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -258,6 +258,17 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
 		mod_timer(&fsp->timer, jiffies + delay);
 }
 
+static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp)
+{
+	fsp->state |= FC_SRB_ABORTED;
+	fsp->state &= ~FC_SRB_ABORT_PENDING;
+
+	if (fsp->wait_for_comp)
+		complete(&fsp->tm_done);
+	else
+		fc_fcp_complete_locked(fsp);
+}
+
 /**
  * fc_fcp_send_abort() - Send an abort for exchanges associated with a
  *			 fcp_pkt
@@ -265,6 +276,8 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
  */
 static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
 {
+	int rc;
+
 	if (!fsp->seq_ptr)
 		return -EINVAL;
 
@@ -272,7 +285,16 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
 	put_cpu();
 
 	fsp->state |= FC_SRB_ABORT_PENDING;
-	return fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0);
+	rc = fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0);
+	/*
+	 * ->seq_exch_abort() might return -ENXIO if
+	 * the sequence is already completed
+	 */
+	if (rc == -ENXIO) {
+		fc_fcp_abort_done(fsp);
+		rc = 0;
+	}
+	return rc;
 }
 
 /**
@@ -729,15 +751,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 		ba_done = 0;
 	}
 
-	if (ba_done) {
-		fsp->state |= FC_SRB_ABORTED;
-		fsp->state &= ~FC_SRB_ABORT_PENDING;
-
-		if (fsp->wait_for_comp)
-			complete(&fsp->tm_done);
-		else
-			fc_fcp_complete_locked(fsp);
-	}
+	if (ba_done)
+		fc_fcp_abort_done(fsp);
 }
 
 /**
@@ -1245,6 +1260,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
 		return FAILED;
 	}
 
+	if (fsp->state & FC_SRB_ABORTED) {
+		FC_FCP_DBG(fsp, "target abort cmd  completed\n");
+		return SUCCESS;
+	}
+
 	init_completion(&fsp->tm_done);
 	fsp->wait_for_comp = 1;
 
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 16/24] libfc: Do not drop out-of-order frames
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (14 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 15/24] libfc: don't fail sequence abort for completed exchanges Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 17/24] libfc: reset timeout on queue full Hannes Reinecke
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

When receiving packets from the network we cannot guarantee any
frame ordering, so we should be receiving all valid frames and
let the upper layers deal with it.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_exch.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 5868824..c62fc27 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1592,9 +1592,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
 	if (fc_sof_is_init(sof)) {
 		sp->ssb_stat |= SSB_ST_RESP;
 		sp->id = fh->fh_seq_id;
-	} else if (sp->id != fh->fh_seq_id) {
-		atomic_inc(&mp->stats.seq_not_found);
-		goto rel;
 	}
 
 	f_ctl = ntoh24(fh->fh_f_ctl);
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 17/24] libfc: reset timeout on queue full
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (15 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 16/24] libfc: Do not drop out-of-order frames Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:10 ` [PATCH 18/24] libfc: wait for E_D_TOV when out-of-order sequence is received Hannes Reinecke
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

When we're receiving a timeout we should be checking for queue
full status; if there are still some packets pending we should
be resetting the counter to ensure we're not missing out any
packets which are still queued.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
---
 drivers/scsi/libfc/fc_fcp.c | 20 +++++++++++++++++---
 include/scsi/libfc.h        |  3 ++-
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index d43c925..fb2ebc7 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -254,8 +254,10 @@ static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt *fsp)
  */
 static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
 {
-	if (!(fsp->state & FC_SRB_COMPL))
+	if (!(fsp->state & FC_SRB_COMPL)) {
 		mod_timer(&fsp->timer, jiffies + delay);
+		fsp->timer_delay = delay;
+	}
 }
 
 static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp)
@@ -932,6 +934,11 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 			 * Wait a at least one jiffy to see if it is delivered.
 			 * If this expires without data, we may do SRR.
 			 */
+			if (fsp->lp->qfull) {
+				FC_FCP_DBG(fsp, "tgt %6.6x queue busy retry\n",
+					   fsp->rport->port_id);
+				return;
+			}
 			FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun "
 				   "len %x, data len %x\n",
 				   fsp->rport->port_id,
@@ -1434,8 +1441,15 @@ static void fc_fcp_timeout(unsigned long data)
 	if (fsp->cdb_cmd.fc_tm_flags)
 		goto unlock;
 
-	FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n",
-		   rpriv->flags, fsp->state);
+	if (fsp->lp->qfull) {
+		FC_FCP_DBG(fsp, "fcp timeout, resetting timer delay %d\n",
+			   fsp->timer_delay);
+		setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
+		fc_fcp_timer_set(fsp, fsp->timer_delay);
+		goto unlock;
+	}
+	FC_FCP_DBG(fsp, "fcp timeout, delay %d flags %x state %x\n",
+		   fsp->timer_delay, rpriv->flags, fsp->state);
 	fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
 
 	if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 8cb752f..f5aa54b 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -355,7 +355,8 @@ struct fc_fcp_pkt {
 
 	/* Timeout/error related information */
 	struct timer_list timer;
-	int	          wait_for_comp;
+	int		  wait_for_comp;
+	int		  timer_delay;
 	u32		  recov_retry;
 	struct fc_seq	  *recov_seq;
 	struct completion tm_done;
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 18/24] libfc: wait for E_D_TOV when out-of-order sequence is received
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (16 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 17/24] libfc: reset timeout on queue full Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-14 21:34   ` Bart Van Assche
  2016-10-13 13:10 ` [PATCH 19/24] libfc: Check xid when looking up REC exchanges Hannes Reinecke
                   ` (7 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

When detecting an out-of-order sequence we should be waiting for
E_D_TOV before trying to abort the sequence.
The response might still be stuck in the queue somewhere.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_fcp.c | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index fb2ebc7..c033946 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -460,6 +460,22 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
 }
 
 /**
+ * get_fsp_rec_tov() - Helper function to get REC_TOV
+ * @fsp: the FCP packet
+ *
+ * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second
+ */
+static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
+{
+	struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
+	unsigned int e_d_tov = FC_DEF_E_D_TOV;
+
+	if (rpriv && rpriv->e_d_tov > e_d_tov)
+		e_d_tov = rpriv->e_d_tov;
+	return msecs_to_jiffies(e_d_tov) + HZ;
+}
+
+/**
  * fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target
  * @fsp: The FCP packet the data is on
  * @fp:	 The data frame
@@ -562,8 +578,10 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 	 * and completes the transfer, call the completion handler.
 	 */
 	if (unlikely(fsp->state & FC_SRB_RCV_STATUS) &&
-	    fsp->xfer_len == fsp->data_len - fsp->scsi_resid)
+	    fsp->xfer_len == fsp->data_len - fsp->scsi_resid) {
+		FC_FCP_DBG( fsp, "complete out-of-order sequence\n" );
 		fc_fcp_complete_locked(fsp);
+	}
 	return;
 err:
 	fc_fcp_recovery(fsp, host_bcode);
@@ -943,7 +961,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 				   "len %x, data len %x\n",
 				   fsp->rport->port_id,
 				   fsp->xfer_len, expected_len, fsp->data_len);
-			fc_fcp_timer_set(fsp, 2);
+			fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
 			return;
 		}
 		fsp->status_code = FC_DATA_OVRRUN;
@@ -1152,22 +1170,6 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
 }
 
 /**
- * get_fsp_rec_tov() - Helper function to get REC_TOV
- * @fsp: the FCP packet
- *
- * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second
- */
-static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
-{
-	struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
-	unsigned int e_d_tov = FC_DEF_E_D_TOV;
-
-	if (rpriv && rpriv->e_d_tov > e_d_tov)
-		e_d_tov = rpriv->e_d_tov;
-	return msecs_to_jiffies(e_d_tov) + HZ;
-}
-
-/**
  * fc_fcp_cmd_send() - Send a FCP command
  * @lport: The local port to send the command on
  * @fsp:   The FCP packet the command is on
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 19/24] libfc: Check xid when looking up REC exchanges
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (17 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 18/24] libfc: wait for E_D_TOV when out-of-order sequence is received Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-14 21:34   ` Bart Van Assche
  2016-10-13 13:10 ` [PATCH 20/24] fcoe: set default TC priority Hannes Reinecke
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

We currently can only lookup the local xid, so we need
to reject REC with empty rxid.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/libfc/fc_exch.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index c62fc27..4c69a99 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -2000,8 +2000,7 @@ static void fc_exch_els_rec(struct fc_frame *rfp)
 	enum fc_els_rjt_reason reason = ELS_RJT_LOGIC;
 	enum fc_els_rjt_explan explan;
 	u32 sid;
-	u16 rxid;
-	u16 oxid;
+	u16 xid, rxid, oxid;
 
 	lport = fr_dev(rfp);
 	rp = fc_frame_payload_get(rfp, sizeof(*rp));
@@ -2012,9 +2011,18 @@ static void fc_exch_els_rec(struct fc_frame *rfp)
 	rxid = ntohs(rp->rec_rx_id);
 	oxid = ntohs(rp->rec_ox_id);
 
-	ep = fc_exch_lookup(lport,
-			    sid == fc_host_port_id(lport->host) ? oxid : rxid);
 	explan = ELS_EXPL_OXID_RXID;
+	if (sid == fc_host_port_id(lport->host))
+		xid = oxid;
+	else
+		xid = rxid;
+	if (xid == FC_XID_UNKNOWN) {
+		FC_LPORT_DBG(lport,
+			     "REC request from %x: invalid rxid %x oxid %x\n",
+			     sid, rxid, oxid);
+		goto reject;
+	}
+	ep = fc_exch_lookup(lport, xid);
 	if (!ep) {
 		FC_LPORT_DBG(lport,
 			     "REC request from %x: rxid %x oxid %x not found\n",
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 20/24] fcoe: set default TC priority
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (18 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 19/24] libfc: Check xid when looking up REC exchanges Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-14 21:35   ` Bart Van Assche
  2016-10-13 13:10 ` [PATCH 21/24] fcoe: catch invalid values for the 'enabled' attribute Hannes Reinecke
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

If DCB is not enabled or compiled in we still should be setting
a sane default priority. So put FCoE frames in priority class
'interactive' and FIP frames in priority class 'besteffort'.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/fcoe/fcoe.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index c907661..9876fca 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -2168,6 +2168,8 @@ static bool fcoe_match(struct net_device *netdev)
  */
 static void fcoe_dcb_create(struct fcoe_interface *fcoe)
 {
+	int ctlr_prio = TC_PRIO_BESTEFFORT;
+	int fcoe_prio = TC_PRIO_INTERACTIVE;
 #ifdef CONFIG_DCB
 	int dcbx;
 	u8 fup, up;
@@ -2194,10 +2196,12 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe)
 			fup = dcb_getapp(netdev, &app);
 		}
 
-		fcoe->priority = ffs(up) ? ffs(up) - 1 : 0;
-		ctlr->priority = ffs(fup) ? ffs(fup) - 1 : fcoe->priority;
+		fcoe_prio = ffs(up) ? ffs(up) - 1 : 0;
+		ctlr_prio = ffs(fup) ? ffs(fup) - 1 : fcoe_prio;
 	}
 #endif
+	fcoe->priority = fcoe_prio;
+	ctlr->priority = ctlr_prio;
 }
 
 enum fcoe_create_link_state {
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 21/24] fcoe: catch invalid values for the 'enabled' attribute
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (19 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 20/24] fcoe: set default TC priority Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-13 13:37   ` Johannes Thumshirn
  2016-10-13 13:10 ` [PATCH 22/24] fcoe: FIP debugging Hannes Reinecke
                   ` (4 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

The 'enabled' sysfs attribute only accepts the values '0' and '1',
so we should error out any other values.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/fcoe/fcoe_sysfs.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 9e6baac..9cf3d56 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -335,16 +335,24 @@ static ssize_t store_ctlr_enabled(struct device *dev,
 				  const char *buf, size_t count)
 {
 	struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
+	bool enabled;
 	int rc;
 
+	if (*buf == '1')
+		enabled = true;
+	else if (*buf == '0')
+		enabled = false;
+	else
+		return -EINVAL;
+
 	switch (ctlr->enabled) {
 	case FCOE_CTLR_ENABLED:
-		if (*buf == '1')
+		if (enabled)
 			return count;
 		ctlr->enabled = FCOE_CTLR_DISABLED;
 		break;
 	case FCOE_CTLR_DISABLED:
-		if (*buf == '0')
+		if (!enabled)
 			return count;
 		ctlr->enabled = FCOE_CTLR_ENABLED;
 		break;
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 22/24] fcoe: FIP debugging
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (20 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 21/24] fcoe: catch invalid values for the 'enabled' attribute Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-14 21:37   ` Bart Van Assche
  2016-10-13 13:10 ` [PATCH 23/24] fcoe: correct sending FIP VLAN packets on VLAN 0 Hannes Reinecke
                   ` (3 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

Add additional statements for debugging FIP frames.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/fcoe/fcoe_ctlr.c | 48 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 05573c3..d773b46 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -801,6 +801,8 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
 	return -EINPROGRESS;
 drop:
 	kfree_skb(skb);
+	LIBFCOE_FIP_DBG(fip, "drop els_send op %u d_id %x\n",
+			op, ntoh24(fh->fh_d_id));
 	return -EINVAL;
 }
 EXPORT_SYMBOL(fcoe_ctlr_els_send);
@@ -2428,6 +2430,8 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
 	switch (fip->state) {
 	case FIP_ST_VNMP_CLAIM:
 	case FIP_ST_VNMP_UP:
+		LIBFCOE_FIP_DBG(fip, "vn_probe_req: send reply, state %x\n",
+				fip->state);
 		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
 				  frport->enode_mac, 0);
 		break;
@@ -2442,15 +2446,21 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
 		 */
 		if (fip->lp->wwpn > rdata->ids.port_name &&
 		    !(frport->flags & FIP_FL_REC_OR_P2P)) {
+			LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
+					"port_id collision\n");
 			fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
 					  frport->enode_mac, 0);
 			break;
 		}
 		/* fall through */
 	case FIP_ST_VNMP_START:
+		LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
+				"restart VN2VN negotiation\n");
 		fcoe_ctlr_vn_restart(fip);
 		break;
 	default:
+		LIBFCOE_FIP_DBG(fip, "vn_probe_req: ignore state %x\n",
+				fip->state);
 		break;
 	}
 }
@@ -2472,9 +2482,12 @@ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
 	case FIP_ST_VNMP_PROBE1:
 	case FIP_ST_VNMP_PROBE2:
 	case FIP_ST_VNMP_CLAIM:
+		LIBFCOE_FIP_DBG(fip, "vn_probe_reply: restart state %x\n",
+				fip->state);
 		fcoe_ctlr_vn_restart(fip);
 		break;
 	case FIP_ST_VNMP_UP:
+		LIBFCOE_FIP_DBG(fip, "vn_probe_reply: send claim notify\n");
 		fcoe_ctlr_vn_send_claim(fip);
 		break;
 	default:
@@ -2517,6 +2530,7 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
 	if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
 	    (ids->node_name != -1 && ids->node_name != new->ids.node_name)) {
 		mutex_unlock(&rdata->rp_mutex);
+		LIBFCOE_FIP_DBG(fip, "vn_add rport logoff %6.6x\n", port_id);
 		lport->tt.rport_logoff(rdata);
 		mutex_lock(&rdata->rp_mutex);
 	}
@@ -2525,8 +2539,9 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
 	mutex_unlock(&rdata->rp_mutex);
 
 	frport = fcoe_ctlr_rport(rdata);
-	LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n",
-			port_id, frport->fcoe_len ? "old" : "new");
+	LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s state %d\n",
+			port_id, frport->fcoe_len ? "old" : "new",
+			rdata->rp_state);
 	*frport = *fcoe_ctlr_rport(new);
 	frport->time = 0;
 }
@@ -2569,6 +2584,7 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
 	struct fcoe_rport *frport = fcoe_ctlr_rport(new);
 
 	if (frport->flags & FIP_FL_REC_OR_P2P) {
+		LIBFCOE_FIP_DBG(fip, "send probe req for P2P/REC\n");
 		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
 		return;
 	}
@@ -2576,25 +2592,37 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
 	case FIP_ST_VNMP_START:
 	case FIP_ST_VNMP_PROBE1:
 	case FIP_ST_VNMP_PROBE2:
-		if (new->ids.port_id == fip->port_id)
+		if (new->ids.port_id == fip->port_id) {
+			LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+					"restart, state %d\n",
+					fip->state);
 			fcoe_ctlr_vn_restart(fip);
+		}
 		break;
 	case FIP_ST_VNMP_CLAIM:
 	case FIP_ST_VNMP_UP:
 		if (new->ids.port_id == fip->port_id) {
 			if (new->ids.port_name > fip->lp->wwpn) {
+				LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+						"restart, port_id collision\n");
 				fcoe_ctlr_vn_restart(fip);
 				break;
 			}
+			LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+					"send claim notify\n");
 			fcoe_ctlr_vn_send_claim(fip);
 			break;
 		}
+		LIBFCOE_FIP_DBG(fip, "vn_claim_notify: send reply to %x\n",
+				new->ids.port_id);
 		fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
 				  min((u32)frport->fcoe_len,
 				      fcoe_ctlr_fcoe_size(fip)));
 		fcoe_ctlr_vn_add(fip, new);
 		break;
 	default:
+		LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+				"ignoring claim from %x\n", new->ids.port_id);
 		break;
 	}
 }
@@ -2631,6 +2659,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
 
 	frport = fcoe_ctlr_rport(new);
 	if (frport->flags & FIP_FL_REC_OR_P2P) {
+		LIBFCOE_FIP_DBG(fip, "p2p beacon while in vn2vn mode\n");
 		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
 		return;
 	}
@@ -2639,8 +2668,14 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
 		if (rdata->ids.node_name == new->ids.node_name &&
 		    rdata->ids.port_name == new->ids.port_name) {
 			frport = fcoe_ctlr_rport(rdata);
-			if (!frport->time && fip->state == FIP_ST_VNMP_UP)
+			LIBFCOE_FIP_DBG(fip, "beacon from rport %x\n",
+					rdata->ids.port_id);
+			if (!frport->time && fip->state == FIP_ST_VNMP_UP) {
+				LIBFCOE_FIP_DBG(fip, "beacon expired "
+						"for rport %x\n",
+						rdata->ids.port_id);
 				lport->tt.rport_login(rdata);
+			}
 			frport->time = jiffies;
 		}
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
@@ -3065,11 +3100,13 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
 	switch (fip->state) {
 	case FIP_ST_VNMP_START:
 		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1);
+		LIBFCOE_FIP_DBG(fip, "vn_timeout: send 1st probe request\n");
 		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
 		next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT);
 		break;
 	case FIP_ST_VNMP_PROBE1:
 		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2);
+		LIBFCOE_FIP_DBG(fip, "vn_timeout: send 2nd probe request\n");
 		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
 		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
 		break;
@@ -3080,6 +3117,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
 		hton24(mac + 3, new_port_id);
 		fcoe_ctlr_map_dest(fip);
 		fip->update_mac(fip->lp, mac);
+		LIBFCOE_FIP_DBG(fip, "vn_timeout: send claim notify\n");
 		fcoe_ctlr_vn_send_claim(fip);
 		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
 		break;
@@ -3091,6 +3129,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
 		next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT);
 		if (time_after_eq(jiffies, next_time)) {
 			fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP);
+			LIBFCOE_FIP_DBG(fip, "vn_timeout: send vn2vn beacon\n");
 			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
 					  fcoe_all_vn2vn, 0);
 			next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
@@ -3101,6 +3140,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
 	case FIP_ST_VNMP_UP:
 		next_time = fcoe_ctlr_vn_age(fip);
 		if (time_after_eq(jiffies, fip->port_ka_time)) {
+			LIBFCOE_FIP_DBG(fip, "vn_timeout: send vn2vn beacon\n");
 			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
 					  fcoe_all_vn2vn, 0);
 			fip->port_ka_time = jiffies +
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 23/24] fcoe: correct sending FIP VLAN packets on VLAN 0
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (21 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 22/24] fcoe: FIP debugging Hannes Reinecke
@ 2016-10-13 13:10 ` Hannes Reinecke
  2016-10-14 21:37   ` Bart Van Assche
  2016-10-13 13:11 ` [PATCH 24/24] fcoe: filter out frames from invalid vlans Hannes Reinecke
                   ` (2 subsequent siblings)
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:10 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke, Hannes Reinecke

The FIP VLAN frame consists of an ethernet header followed
by the FIP VLAN frame, so we need to skip the ethernet header
if we want to check the FIP opcode.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 drivers/scsi/fcoe/fcoe.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 9876fca..cf4adaa 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -590,7 +590,8 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
 	 * Use default VLAN for FIP VLAN discovery protocol
 	 */
 	frame = (struct fip_frame *)skb->data;
-	if (frame->fip.fip_op == ntohs(FIP_OP_VLAN) &&
+	if (ntohs(frame->eth.h_proto) == ETH_P_FIP &&
+	    ntohs(frame->fip.fip_op) == FIP_OP_VLAN &&
 	    fcoe->realdev != fcoe->netdev)
 		skb->dev = fcoe->realdev;
 	else
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 24/24] fcoe: filter out frames from invalid vlans
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (22 preceding siblings ...)
  2016-10-13 13:10 ` [PATCH 23/24] fcoe: correct sending FIP VLAN packets on VLAN 0 Hannes Reinecke
@ 2016-10-13 13:11 ` Hannes Reinecke
  2016-10-14 21:38   ` Bart Van Assche
  2016-10-14 20:43 ` [PATCH 00/24] FCoE VN2VN fixes, part two Martin K. Petersen
  2016-10-17 17:42 ` Martin K. Petersen
  25 siblings, 1 reply; 40+ messages in thread
From: Hannes Reinecke @ 2016-10-13 13:11 UTC (permalink / raw)
  To: Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

Any multicase address is set on all interfaces, the base interface
and any VLAN interfaces on top of this. So we might receive frames
which are not destined for us.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/scsi/fcoe/fcoe_ctlr.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index d773b46..4aacd60 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2754,11 +2754,21 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
 		struct fc_rport_priv rdata;
 		struct fcoe_rport frport;
 	} buf;
-	int rc;
+	int rc, vlan_id = 0;
 
 	fiph = (struct fip_header *)skb->data;
 	sub = fiph->fip_subcode;
 
+	if (fip->lp->vlan)
+		vlan_id = skb_vlan_tag_get_id(skb);
+
+	if (vlan_id && vlan_id != fip->lp->vlan) {
+		LIBFCOE_FIP_DBG(fip, "vn_recv drop frame sub %x vlan %d\n",
+				sub, vlan_id);
+		rc = -EAGAIN;
+		goto drop;
+	}
+
 	rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
 	if (rc) {
 		LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH 21/24] fcoe: catch invalid values for the 'enabled' attribute
  2016-10-13 13:10 ` [PATCH 21/24] fcoe: catch invalid values for the 'enabled' attribute Hannes Reinecke
@ 2016-10-13 13:37   ` Johannes Thumshirn
  0 siblings, 0 replies; 40+ messages in thread
From: Johannes Thumshirn @ 2016-10-13 13:37 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Martin K. Petersen, Johannes Thumshirn, Christoph Hellwig,
	James Bottomley, linux-scsi, Hannes Reinecke

On Thu, Oct 13, 2016 at 03:10:57PM +0200, Hannes Reinecke wrote:
> The 'enabled' sysfs attribute only accepts the values '0' and '1',
> so we should error out any other values.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.com>
> ---

Acked-by: Johannes Thumshirn <jth@kernel.org>

-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 05/24] libfc: sanitize E_D_TOV and R_A_TOV setting
  2016-10-13 13:10 ` [PATCH 05/24] libfc: sanitize E_D_TOV and R_A_TOV setting Hannes Reinecke
@ 2016-10-13 13:42   ` Johannes Thumshirn
  0 siblings, 0 replies; 40+ messages in thread
From: Johannes Thumshirn @ 2016-10-13 13:42 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Martin K. Petersen, Johannes Thumshirn, Christoph Hellwig,
	James Bottomley, linux-scsi, Hannes Reinecke

On Thu, Oct 13, 2016 at 03:10:41PM +0200, Hannes Reinecke wrote:
> When setting the FCP timeout we need to ensure a lower boundary
> for E_D_TOV and R_A_TOV, otherwise we'd be getting spurious I/O
> issues due to the fcp timer firing too early.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.com>
> ---

Acked-by: Johannes Thumshirn <jth@kernel.org>
-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 10/24] libfc: Rework PRLI handling
  2016-10-13 13:10 ` [PATCH 10/24] libfc: Rework PRLI handling Hannes Reinecke
@ 2016-10-13 14:02   ` Johannes Thumshirn
  0 siblings, 0 replies; 40+ messages in thread
From: Johannes Thumshirn @ 2016-10-13 14:02 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Martin K. Petersen, Johannes Thumshirn, Christoph Hellwig,
	James Bottomley, linux-scsi, Hannes Reinecke

On Thu, Oct 13, 2016 at 03:10:46PM +0200, Hannes Reinecke wrote:
> PRLI is only required if the port is acting as an initiator; ports
> which support target functionality only do not need to send PRLI.
> At the same time the PRLI state is only used if the port initiated
> a PRLI transfer; if we received a PRLI request we should _not_
> change the state as this would cause our PRLI response to be dropped.
> And when we receive a PRLI response we need to check if an image
> pair has been established; if not the remote port cannot act as a
> target for us and we need to disable target functionality.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.com>
> ---

Acked-by: Johannes Thumshirn <jth@kernel.org>
-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 12/24] libfc: Clarify ramp-down messages
  2016-10-13 13:10 ` [PATCH 12/24] libfc: Clarify ramp-down messages Hannes Reinecke
@ 2016-10-13 14:06   ` Johannes Thumshirn
  0 siblings, 0 replies; 40+ messages in thread
From: Johannes Thumshirn @ 2016-10-13 14:06 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Martin K. Petersen, Johannes Thumshirn, Christoph Hellwig,
	James Bottomley, linux-scsi, Hannes Reinecke

On Thu, Oct 13, 2016 at 03:10:48PM +0200, Hannes Reinecke wrote:
> When the queue depth is reduced we should print out the reason
> for this; it might be due to a queue full condition.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.com>
> ---

Acked-by: Johannes Thumshirn <jth@kernel.org>
-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 00/24] FCoE VN2VN fixes, part two
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (23 preceding siblings ...)
  2016-10-13 13:11 ` [PATCH 24/24] fcoe: filter out frames from invalid vlans Hannes Reinecke
@ 2016-10-14 20:43 ` Martin K. Petersen
  2016-10-17 17:42 ` Martin K. Petersen
  25 siblings, 0 replies; 40+ messages in thread
From: Martin K. Petersen @ 2016-10-14 20:43 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Martin K. Petersen, Johannes Thumshirn, Christoph Hellwig,
	James Bottomley, linux-scsi

>>>>> "Hannes" == Hannes Reinecke <hare@suse.de> writes:

Hannes> Hi all, here's now the second part of my FCoE VN2VN patchset.
Hannes> The key points are:
Hannes> - Configurable R_A_TOV/E_D_TOV
Hannes> - Rework PRLI handling to fix a longstanding bug
Hannes> - Correctly handle timed-out xids

Hannes> Additionally there are some minor fixes to get things to work
Hannes> when running with FCoE over virtio.

Hannes> Patches are relative to mkp/4.10/scsi-queue.

Hannes> As usual, comments and reviews are welcome.

Somebody please review patches 11, 13, 14, 18, 19, 20, 22, 23 and 24.

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 11/24] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI
  2016-10-13 13:10 ` [PATCH 11/24] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Hannes Reinecke
@ 2016-10-14 21:25   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:25 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

On 10/13/2016 06:10 AM, Hannes Reinecke wrote:
> Occasionally it might happen that we receive a PRLI while we're still
> waiting for our PLOGI response. In that case we should return
> 'busy' LS status instead of 'plogi required' LS status.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 13/24] libfc: safeguard against invalid exchange index
  2016-10-13 13:10 ` [PATCH 13/24] libfc: safeguard against invalid exchange index Hannes Reinecke
@ 2016-10-14 21:27   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:27 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

On 10/13/2016 06:10 AM, Hannes Reinecke wrote:
> The cached exchange index might be invalid, in which case
> we should drop down to allocate a new one.
> And we should not try to access an invalid exchange when
> responding to a BA_ABTS.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 14/24] libfc: quarantine timed out xids
  2016-10-13 13:10 ` [PATCH 14/24] libfc: quarantine timed out xids Hannes Reinecke
@ 2016-10-14 21:33   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:33 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

On 10/13/2016 06:10 AM, Hannes Reinecke wrote:
> When a sequence times out we have no idea what happened to the
> frame. And we do not know if we will ever receive the frame.
> Hence we cannot re-use the xid as we would risk data corruption
> if the xid had been re-used and the timed out frame would be
> received after that.
> So we need to quarantine the xid until the lport is reset.
> Yes, I know this will (eventually) deplete the xid pool.
> But for now it's the safest method.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 18/24] libfc: wait for E_D_TOV when out-of-order sequence is received
  2016-10-13 13:10 ` [PATCH 18/24] libfc: wait for E_D_TOV when out-of-order sequence is received Hannes Reinecke
@ 2016-10-14 21:34   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:34 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

On 10/13/2016 06:10 AM, Hannes Reinecke wrote:
> When detecting an out-of-order sequence we should be waiting for
> E_D_TOV before trying to abort the sequence.
> The response might still be stuck in the queue somewhere.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 19/24] libfc: Check xid when looking up REC exchanges
  2016-10-13 13:10 ` [PATCH 19/24] libfc: Check xid when looking up REC exchanges Hannes Reinecke
@ 2016-10-14 21:34   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:34 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

On 10/13/2016 06:10 AM, Hannes Reinecke wrote:
> We currently can only lookup the local xid, so we need
> to reject REC with empty rxid.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 20/24] fcoe: set default TC priority
  2016-10-13 13:10 ` [PATCH 20/24] fcoe: set default TC priority Hannes Reinecke
@ 2016-10-14 21:35   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:35 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

On 10/13/2016 06:10 AM, Hannes Reinecke wrote:
> If DCB is not enabled or compiled in we still should be setting
> a sane default priority. So put FCoE frames in priority class
> 'interactive' and FIP frames in priority class 'besteffort'.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 22/24] fcoe: FIP debugging
  2016-10-13 13:10 ` [PATCH 22/24] fcoe: FIP debugging Hannes Reinecke
@ 2016-10-14 21:37   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:37 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

On 10/13/2016 06:10 AM, Hannes Reinecke wrote:
> Add additional statements for debugging FIP frames.
 > [ ... ]
> @@ -2442,15 +2446,21 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
>  		 */
>  		if (fip->lp->wwpn > rdata->ids.port_name &&
>  		    !(frport->flags & FIP_FL_REC_OR_P2P)) {
> +			LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
> +					"port_id collision\n");
>  			fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
>  					  frport->enode_mac, 0);

Hmm ... checkpatch should have complained about this and should have 
recommended to keep the format string on a single line. Anyway:

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 23/24] fcoe: correct sending FIP VLAN packets on VLAN 0
  2016-10-13 13:10 ` [PATCH 23/24] fcoe: correct sending FIP VLAN packets on VLAN 0 Hannes Reinecke
@ 2016-10-14 21:37   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:37 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley,
	linux-scsi, Hannes Reinecke

On 10/13/2016 06:10 AM, Hannes Reinecke wrote:
> The FIP VLAN frame consists of an ethernet header followed
> by the FIP VLAN frame, so we need to skip the ethernet header
> if we want to check the FIP opcode.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 24/24] fcoe: filter out frames from invalid vlans
  2016-10-13 13:11 ` [PATCH 24/24] fcoe: filter out frames from invalid vlans Hannes Reinecke
@ 2016-10-14 21:38   ` Bart Van Assche
  0 siblings, 0 replies; 40+ messages in thread
From: Bart Van Assche @ 2016-10-14 21:38 UTC (permalink / raw)
  To: Hannes Reinecke, Martin K. Petersen
  Cc: Johannes Thumshirn, Christoph Hellwig, James Bottomley, linux-scsi

On 10/13/2016 06:11 AM, Hannes Reinecke wrote:
> Any multicase address is set on all interfaces, the base interface
> and any VLAN interfaces on top of this. So we might receive frames
> which are not destined for us.

Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 00/24] FCoE VN2VN fixes, part two
  2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
                   ` (24 preceding siblings ...)
  2016-10-14 20:43 ` [PATCH 00/24] FCoE VN2VN fixes, part two Martin K. Petersen
@ 2016-10-17 17:42 ` Martin K. Petersen
  25 siblings, 0 replies; 40+ messages in thread
From: Martin K. Petersen @ 2016-10-17 17:42 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Martin K. Petersen, Johannes Thumshirn, Christoph Hellwig,
	James Bottomley, linux-scsi

>>>>> "Hannes" == Hannes Reinecke <hare@suse.de> writes:

Hannes> Hi all, here's now the second part of my FCoE VN2VN patchset.
Hannes> The key points are:
Hannes> - Configurable R_A_TOV/E_D_TOV
Hannes> - Rework PRLI handling to fix a longstanding bug
Hannes> - Correctly handle timed-out xids

Hannes> Additionally there are some minor fixes to get things to work
Hannes> when running with FCoE over virtio.

Hannes> Patches are relative to mkp/4.10/scsi-queue.

Applied to 4.10/scsi-queue.

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2016-10-17 17:42 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-13 13:10 [PATCH 00/24] FCoE VN2VN fixes, part two Hannes Reinecke
2016-10-13 13:10 ` [PATCH 01/24] libfc: additional debugging messages Hannes Reinecke
2016-10-13 13:10 ` [PATCH 02/24] libfc: spurious I/O error under high load Hannes Reinecke
2016-10-13 13:10 ` [PATCH 03/24] libfc: use configured lport R_A_TOV Hannes Reinecke
2016-10-13 13:10 ` [PATCH 04/24] libfc: use configured rport E_D_TOV Hannes Reinecke
2016-10-13 13:10 ` [PATCH 05/24] libfc: sanitize E_D_TOV and R_A_TOV setting Hannes Reinecke
2016-10-13 13:42   ` Johannes Thumshirn
2016-10-13 13:10 ` [PATCH 06/24] fcoe: make R_A_TOV and E_D_TOV configurable Hannes Reinecke
2016-10-13 13:10 ` [PATCH 07/24] libfc: do not overwrite DID_TIME_OUT status Hannes Reinecke
2016-10-13 13:10 ` [PATCH 08/24] libfc: use error code for fc_rport_error() Hannes Reinecke
2016-10-13 13:10 ` [PATCH 09/24] libfc: Implement RTV responder Hannes Reinecke
2016-10-13 13:10 ` [PATCH 10/24] libfc: Rework PRLI handling Hannes Reinecke
2016-10-13 14:02   ` Johannes Thumshirn
2016-10-13 13:10 ` [PATCH 11/24] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Hannes Reinecke
2016-10-14 21:25   ` Bart Van Assche
2016-10-13 13:10 ` [PATCH 12/24] libfc: Clarify ramp-down messages Hannes Reinecke
2016-10-13 14:06   ` Johannes Thumshirn
2016-10-13 13:10 ` [PATCH 13/24] libfc: safeguard against invalid exchange index Hannes Reinecke
2016-10-14 21:27   ` Bart Van Assche
2016-10-13 13:10 ` [PATCH 14/24] libfc: quarantine timed out xids Hannes Reinecke
2016-10-14 21:33   ` Bart Van Assche
2016-10-13 13:10 ` [PATCH 15/24] libfc: don't fail sequence abort for completed exchanges Hannes Reinecke
2016-10-13 13:10 ` [PATCH 16/24] libfc: Do not drop out-of-order frames Hannes Reinecke
2016-10-13 13:10 ` [PATCH 17/24] libfc: reset timeout on queue full Hannes Reinecke
2016-10-13 13:10 ` [PATCH 18/24] libfc: wait for E_D_TOV when out-of-order sequence is received Hannes Reinecke
2016-10-14 21:34   ` Bart Van Assche
2016-10-13 13:10 ` [PATCH 19/24] libfc: Check xid when looking up REC exchanges Hannes Reinecke
2016-10-14 21:34   ` Bart Van Assche
2016-10-13 13:10 ` [PATCH 20/24] fcoe: set default TC priority Hannes Reinecke
2016-10-14 21:35   ` Bart Van Assche
2016-10-13 13:10 ` [PATCH 21/24] fcoe: catch invalid values for the 'enabled' attribute Hannes Reinecke
2016-10-13 13:37   ` Johannes Thumshirn
2016-10-13 13:10 ` [PATCH 22/24] fcoe: FIP debugging Hannes Reinecke
2016-10-14 21:37   ` Bart Van Assche
2016-10-13 13:10 ` [PATCH 23/24] fcoe: correct sending FIP VLAN packets on VLAN 0 Hannes Reinecke
2016-10-14 21:37   ` Bart Van Assche
2016-10-13 13:11 ` [PATCH 24/24] fcoe: filter out frames from invalid vlans Hannes Reinecke
2016-10-14 21:38   ` Bart Van Assche
2016-10-14 20:43 ` [PATCH 00/24] FCoE VN2VN fixes, part two Martin K. Petersen
2016-10-17 17:42 ` Martin K. Petersen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.