From cc3593d3882ffa7dfaa739a8302b256955be7d99 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 12 Mar 2010 16:08:29 -0800 Subject: [SCSI] libfc: fix sequence-initiative WARN in fc_seq_start_next When starting a new response sequence in a multi-sequence exchange, a warning was issued that sequence initiative wasn't held. The bug was that sequence initiative was cleared by the previous sequence due to the END_SEQ flag being on. The intent may have been to check LAST_SEQ. Change just to check SEQ_INIT. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/libfc/fc_exch.c') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index e5df0d4db67e..7cc084cf9950 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -488,7 +488,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, */ spin_lock_bh(&ep->ex_lock); ep->f_ctl = f_ctl & ~FC_FC_FIRST_SEQ; /* not first seq */ - if (f_ctl & (FC_FC_END_SEQ | FC_FC_SEQ_INIT)) + if (f_ctl & FC_FC_SEQ_INIT) ep->esb_stat &= ~ESB_ST_SEQ_INIT; spin_unlock_bh(&ep->ex_lock); return error; -- cgit v1.2.3 From a104c844576c6bdc44c6f1336e30a5fcd90fef1c Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 12 Mar 2010 16:08:34 -0800 Subject: [SCSI] libfc: fixes unnecessary seq id jump In some cases seq is incremented twice causing unnecessary seq jump, for instance fc_exch_recv_seq_resp increments seq id when fc_sof_is_init is true and that is true for each incoming xfer ready but then fc_fcp_send_data does another seq increment to send data for xfer ready. This patch removes all such seq id jumps, at least it eliminates few calls to fc_seq_start_next using ex_lock. Also removes seq id update with incoming frame's seq id as this is not needed since each end (I or T) just need to send incremented their own seq id on each TSI from other end & before sending new sequence within a exchange. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers/scsi/libfc/fc_exch.c') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 7cc084cf9950..981021edfba9 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -920,12 +920,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, * Find or create the sequence. */ if (fc_sof_is_init(fr_sof(fp))) { - sp = fc_seq_start_next(&ep->seq); - if (!sp) { - reject = FC_RJT_SEQ_XS; /* exchange shortage */ - goto rel; - } - sp->id = fh->fh_seq_id; + sp = &ep->seq; sp->ssb_stat |= SSB_ST_RESP; } else { sp = &ep->seq; @@ -1336,17 +1331,14 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) goto rel; } sof = fr_sof(fp); - if (fc_sof_is_init(sof)) { - sp = fc_seq_start_next(&ep->seq); - sp->id = fh->fh_seq_id; + sp = &ep->seq; + if (fc_sof_is_init(sof)) sp->ssb_stat |= SSB_ST_RESP; - } else { - sp = &ep->seq; - if (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); fr_seq(fp) = sp; if (f_ctl & FC_FC_SEQ_INIT) @@ -1763,7 +1755,6 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) fc_exch_done(sp); goto out; } - sp = fc_seq_start_next(sp); acc = fc_frame_payload_get(fp, sizeof(*acc)); memset(acc, 0, sizeof(*acc)); acc->reca_cmd = ELS_LS_ACC; -- cgit v1.2.3 From 3e22760d4db6fd89e0be46c3d132390a251da9c6 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 12 Mar 2010 16:08:39 -0800 Subject: [SCSI] libfc: use offload EM instance again instead jumping to next EM Since use of offloads is more efficient than switching to non-offload EM. However kept logic same to call em_match if it is provided in the list of EMs. Converted fc_exch_alloc to inline being now tiny a function and already not an exported libfc API any more. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/scsi/libfc/fc_exch.c') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 981021edfba9..dc12a2bf0c9b 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -734,19 +734,14 @@ err: * EM is selected when a NULL match function pointer is encountered * or when a call to a match function returns true. */ -static struct fc_exch *fc_exch_alloc(struct fc_lport *lport, - struct fc_frame *fp) +static inline struct fc_exch *fc_exch_alloc(struct fc_lport *lport, + struct fc_frame *fp) { struct fc_exch_mgr_anchor *ema; - struct fc_exch *ep; - list_for_each_entry(ema, &lport->ema_list, ema_list) { - if (!ema->match || ema->match(fp)) { - ep = fc_exch_em_alloc(lport, ema->mp); - if (ep) - return ep; - } - } + list_for_each_entry(ema, &lport->ema_list, ema_list) + if (!ema->match || ema->match(fp)) + return fc_exch_em_alloc(lport, ema->mp); return NULL; } -- cgit v1.2.3 From f018b73af6db4f330ad5da9ac53997a699c30c42 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 12 Mar 2010 16:08:55 -0800 Subject: [SCSI] libfc, libfcoe, fcoe: use smp_processor_id() only when preempt disabled When the kernel is configured for preemption, using smp_processor_id() when preemption is enabled causes a warning backtrace and is wrong since we could move off of that CPU as soon as we get the ID, and we would be referencing the wrong CPU, and possibly an invalid one if it could be hotswapped out. Remove the fc_lport_get_stats() function and explicitly use per_cpu_ptr() to get the statistics. Where preemption has been disabled by holding a _bh lock continue to use smp_processor_id(), but otherwise use get_cpu()/put_cpu(). In fcoe_recv_frame() also changed the cases where we return in the middle to do a goto to the code which bumps ErrorFrames and does a put_cpu(). Two of these cases didn't bump ErrorFrames before, but doing so is harmless because they "can't happen", due to prior length checks. Also rearranged code in fcoe_recv_frame() to have only one call to fc_exch_recv(). It's just as efficient and saves a call to put_cpu(). In fc_fcp.c, adjusted a FIXME comment for code which doesn't need fixing. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/libfc/fc_exch.c') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index dc12a2bf0c9b..d0496dafd84a 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -676,9 +676,10 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, } memset(ep, 0, sizeof(*ep)); - cpu = smp_processor_id(); + cpu = get_cpu(); pool = per_cpu_ptr(mp->pool, cpu); spin_lock_bh(&pool->lock); + put_cpu(); index = pool->next_index; /* allocate new exch from pool */ while (fc_exch_ptr_get(pool, index)) { -- cgit v1.2.3 From 3b719d01617288f4c11307fcb933997d7ca895c3 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 9 Apr 2010 14:22:33 -0700 Subject: [SCSI] libfc: remove unneeded variables in fc_exch_recv_req() fc_exch_recv_req has variables eof, sof, and f_ctl, which are set but never used. Delete them. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/scsi/libfc/fc_exch.c') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index d0496dafd84a..daff880e426e 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1241,9 +1241,6 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_seq *sp = NULL; struct fc_exch *ep = NULL; - enum fc_sof sof; - enum fc_eof eof; - u32 f_ctl; enum fc_pf_rjt_reason reject; /* We can have the wrong fc_lport at this point with NPIV, which is a @@ -1260,9 +1257,6 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, if (reject == FC_RJT_NONE) { sp = fr_seq(fp); /* sequence will be held */ ep = fc_seq_exch(sp); - sof = fr_sof(fp); - eof = fr_eof(fp); - f_ctl = ntoh24(fh->fh_f_ctl); fc_seq_send_ack(sp, fp); /* -- cgit v1.2.3 From b3667f9177359b0594e4f2cd5cc01115f8c7e2af Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Fri, 7 May 2010 15:18:13 -0700 Subject: [SCSI] libfc: set seq_id for incoming sequence After the recent patch "fixes unnecessary seq id jump" the SCST module fcst stopped working because multi-sequence write data wasn't finding the sequence after the first frame. Add back the setting of the seq_id when the first frame arrives. Also fix indentation on two lines. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/libfc/fc_exch.c') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index daff880e426e..6addbd6e41e2 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -918,6 +918,7 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, if (fc_sof_is_init(fr_sof(fp))) { sp = &ep->seq; sp->ssb_stat |= SSB_ST_RESP; + sp->id = fh->fh_seq_id; } else { sp = &ep->seq; if (sp->id != fh->fh_seq_id) { @@ -1322,11 +1323,12 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) } sof = fr_sof(fp); sp = &ep->seq; - if (fc_sof_is_init(sof)) + if (fc_sof_is_init(sof)) { sp->ssb_stat |= SSB_ST_RESP; - else if (sp->id != fh->fh_seq_id) { - atomic_inc(&mp->stats.seq_not_found); - goto rel; + 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); -- cgit v1.2.3 From 7b2787ec15b9d1c2f716da61b0eec21a3f5e6520 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 7 May 2010 15:18:41 -0700 Subject: [SCSI] libfc: Move the port_id into lport This patch creates a port_id member in struct fc_lport. This allows libfc to just deal with fc_lport instances instead of calling into the fc_host to get the port_id. This change helps in only using symbols necessary for operation from the libfc structures. libfc still needs to change the fc_host_port_id() if the port_id changes so the presentation layer (scsi_transport_fc) can provide the user with the correct value, but libfc shouldn't rely on the presentation layer for operational values. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/libfc/fc_exch.c') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 6addbd6e41e2..104e0fba7c43 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1927,7 +1927,7 @@ static void fc_exch_rrq(struct fc_exch *ep) did = ep->sid; fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, did, - fc_host_port_id(lport->host), FC_TYPE_ELS, + lport->port_id, FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); if (fc_exch_seq_send(lport, fp, fc_exch_rrq_resp, NULL, ep, -- cgit v1.2.3