diff options
author | James Bottomley <James.Bottomley@suse.de> | 2010-05-18 10:33:43 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-05-18 10:37:41 -0400 |
commit | 95bb335c0ebe96afe926387a1ef3a096bd884a82 (patch) | |
tree | 56115332b4f2f7ef300c36248a6a7d20db2e639d /drivers/scsi/libfc | |
parent | 1b4d0d8ea7b3cbd107f345ab766416f9b38ce66a (diff) | |
parent | 9cccde93fed1ca988eb2fb17ab9194bf7b5ed1b0 (diff) |
[SCSI] Merge scsi-misc-2.6 into scsi-rc-fixes-2.6
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r-- | drivers/scsi/libfc/fc_disc.c | 8 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_elsct.c | 2 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 51 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 103 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_libfc.h | 8 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 58 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_npiv.c | 7 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 195 |
8 files changed, 211 insertions, 221 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 1087a7f18e8..c7985da8809 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -132,7 +132,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, switch (fmt) { case ELS_ADDR_FMT_PORT: FC_DISC_DBG(disc, "Port address format for port " - "(%6x)\n", ntoh24(pp->rscn_fid)); + "(%6.6x)\n", ntoh24(pp->rscn_fid)); dp = kzalloc(sizeof(*dp), GFP_KERNEL); if (!dp) { redisc = 1; @@ -440,7 +440,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) ids.port_id = ntoh24(np->fp_fid); ids.port_name = ntohll(np->fp_wwpn); - if (ids.port_id != fc_host_port_id(lport->host) && + if (ids.port_id != lport->port_id && ids.port_name != lport->wwpn) { rdata = lport->tt.rport_create(lport, ids.port_id); if (rdata) { @@ -449,7 +449,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) } else { printk(KERN_WARNING "libfc: Failed to allocate " "memory for the newly discovered port " - "(%6x)\n", ids.port_id); + "(%6.6x)\n", ids.port_id); error = -ENOMEM; } } @@ -607,7 +607,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, rdata->ids.port_name = port_name; else if (rdata->ids.port_name != port_name) { FC_DISC_DBG(disc, "GPN_ID accepted. WWPN changed. " - "Port-id %x wwpn %llx\n", + "Port-id %6.6x wwpn %16.16llx\n", rdata->ids.port_id, port_name); lport->tt.rport_logoff(rdata); diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index 53748724f2c..e9412b710fa 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -63,7 +63,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, return NULL; } - fc_fill_fc_hdr(fp, r_ctl, did, fc_host_port_id(lport->host), fh_type, + fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index e5df0d4db67..104e0fba7c4 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; @@ -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)) { @@ -734,19 +735,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; } @@ -920,13 +916,9 @@ 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; + sp->id = fh->fh_seq_id; } else { sp = &ep->seq; if (sp->id != fh->fh_seq_id) { @@ -1250,9 +1242,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 @@ -1269,9 +1258,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); /* @@ -1336,17 +1322,15 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) goto rel; } sof = fr_sof(fp); + sp = &ep->seq; if (fc_sof_is_init(sof)) { - sp = fc_seq_start_next(&ep->seq); - sp->id = fh->fh_seq_id; sp->ssb_stat |= SSB_ST_RESP; - } else { - sp = &ep->seq; - 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); fr_seq(fp) = sp; if (f_ctl & FC_FC_SEQ_INIT) @@ -1763,7 +1747,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; @@ -1944,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, diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 17396c708b0..ec1f66c4a9d 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -97,7 +97,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *, struct fc_frame *); static void fc_fcp_complete_locked(struct fc_fcp_pkt *); static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *); static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *); -static void fc_timeout_error(struct fc_fcp_pkt *); +static void fc_fcp_recovery(struct fc_fcp_pkt *); static void fc_fcp_timeout(unsigned long); static void fc_fcp_rec(struct fc_fcp_pkt *); static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *); @@ -121,7 +121,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *); #define FC_DATA_UNDRUN 7 #define FC_ERROR 8 #define FC_HRD_ERROR 9 -#define FC_CMD_TIME_OUT 10 +#define FC_CMD_RECOVERY 10 /* * Error recovery timeout values. @@ -446,9 +446,16 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) len = fr_len(fp) - sizeof(*fh); buf = fc_frame_payload_get(fp, 0); - /* if this I/O is ddped, update xfer len */ - fc_fcp_ddp_done(fsp); - + /* + * if this I/O is ddped then clear it + * and initiate recovery since data + * frames are expected to be placed + * directly in that case. + */ + if (fsp->xfer_ddp != FC_XID_UNKNOWN) { + fc_fcp_ddp_done(fsp); + goto err; + } if (offset + len > fsp->data_len) { /* this should never happen */ if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && @@ -456,8 +463,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) goto crc_err; FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx " "data_len %x\n", len, offset, fsp->data_len); - fc_fcp_retry_cmd(fsp); - return; + goto err; } if (offset != fsp->xfer_len) fsp->state |= FC_SRB_DISCONTIG; @@ -478,13 +484,14 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (~crc != le32_to_cpu(fr_crc(fp))) { crc_err: - stats = fc_lport_get_stats(lport); + stats = per_cpu_ptr(lport->dev_stats, get_cpu()); stats->ErrorFrames++; - /* FIXME - per cpu count, not total count! */ + /* per cpu count, not total count, but OK for limit */ if (stats->InvalidCRCCount++ < 5) printk(KERN_WARNING "libfc: CRC error on data " - "frame for port (%6x)\n", - fc_host_port_id(lport->host)); + "frame for port (%6.6x)\n", + lport->port_id); + put_cpu(); /* * Assume the frame is total garbage. * We may have copied it over the good part @@ -493,7 +500,7 @@ crc_err: * Otherwise, ignore it. */ if (fsp->state & FC_SRB_DISCONTIG) - fc_fcp_retry_cmd(fsp); + goto err; return; } } @@ -509,6 +516,9 @@ crc_err: if (unlikely(fsp->state & FC_SRB_RCV_STATUS) && fsp->xfer_len == fsp->data_len - fsp->scsi_resid) fc_fcp_complete_locked(fsp); + return; +err: + fc_fcp_recovery(fsp); } /** @@ -834,8 +844,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * exit here */ return; - } else - goto err; + } } if (flags & FCP_SNS_LEN_VAL) { snsl = ntohl(rp_ex->fr_sns_len); @@ -885,7 +894,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) return; } fsp->status_code = FC_DATA_OVRRUN; - FC_FCP_DBG(fsp, "tgt %6x xfer len %zx greater than expected, " + FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx greater than expected, " "len %x, data len %x\n", fsp->rport->port_id, fsp->xfer_len, expected_len, fsp->data_len); @@ -1100,7 +1109,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, rpriv = rport->dd_data; fc_fill_fc_hdr(fp, FC_RCTL_DD_UNSOL_CMD, rport->port_id, - fc_host_port_id(rpriv->local_port->host), FC_TYPE_FCP, + rpriv->local_port->port_id, FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, @@ -1341,7 +1350,7 @@ static void fc_fcp_timeout(unsigned long data) else if (fsp->state & FC_SRB_RCV_STATUS) fc_fcp_complete_locked(fsp); else - fc_timeout_error(fsp); + fc_fcp_recovery(fsp); fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO; unlock: fc_fcp_unlock_pkt(fsp); @@ -1373,7 +1382,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) fr_seq(fp) = fsp->seq_ptr; fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id, - fc_host_port_id(rpriv->local_port->host), FC_TYPE_ELS, + rpriv->local_port->port_id, FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, fc_fcp_rec_resp, fsp, @@ -1385,7 +1394,7 @@ retry: if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); else - fc_timeout_error(fsp); + fc_fcp_recovery(fsp); } /** @@ -1454,7 +1463,7 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fc_fcp_retry_cmd(fsp); break; } - fc_timeout_error(fsp); + fc_fcp_recovery(fsp); break; } } else if (opcode == ELS_LS_ACC) { @@ -1553,7 +1562,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) break; default: - FC_FCP_DBG(fsp, "REC %p fid %x error unexpected error %d\n", + FC_FCP_DBG(fsp, "REC %p fid %6.6x error unexpected error %d\n", fsp, fsp->rport->port_id, error); fsp->status_code = FC_CMD_PLOGO; /* fall through */ @@ -1563,13 +1572,13 @@ 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 %x error error %d retry %d/%d\n", + FC_FCP_DBG(fsp, "REC fid %6.6x error error %d retry %d/%d\n", fsp->rport->port_id, error, fsp->recov_retry, FC_MAX_RECOV_RETRY); if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); else - fc_timeout_error(fsp); + fc_fcp_recovery(fsp); break; } fc_fcp_unlock_pkt(fsp); @@ -1578,12 +1587,12 @@ out: } /** - * fc_timeout_error() - Handler for fcp_pkt timeouts - * @fsp: The FCP packt that has timed out + * fc_fcp_recovery() - Handler for fcp_pkt recovery + * @fsp: The FCP pkt that needs to be aborted */ -static void fc_timeout_error(struct fc_fcp_pkt *fsp) +static void fc_fcp_recovery(struct fc_fcp_pkt *fsp) { - fsp->status_code = FC_CMD_TIME_OUT; + fsp->status_code = FC_CMD_RECOVERY; fsp->cdb_status = 0; fsp->io_status = 0; /* @@ -1631,7 +1640,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) srr->srr_rel_off = htonl(offset); fc_fill_fc_hdr(fp, FC_RCTL_ELS4_REQ, rport->port_id, - fc_host_port_id(rpriv->local_port->host), FC_TYPE_FCP, + rpriv->local_port->port_id, FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, @@ -1689,7 +1698,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) break; case ELS_LS_RJT: default: - fc_timeout_error(fsp); + fc_fcp_recovery(fsp); break; } fc_fcp_unlock_pkt(fsp); @@ -1715,7 +1724,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); else - fc_timeout_error(fsp); + fc_fcp_recovery(fsp); break; case -FC_EX_CLOSED: /* e.g., link failure */ /* fall through */ @@ -1810,7 +1819,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) /* * setup the data direction */ - stats = fc_lport_get_stats(lport); + stats = per_cpu_ptr(lport->dev_stats, get_cpu()); if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { fsp->req_flags = FC_SRB_READ; stats->InputRequests++; @@ -1823,6 +1832,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) fsp->req_flags = 0; stats->ControlRequests++; } + put_cpu(); fsp->tgt_flags = rpriv->flags; @@ -1907,6 +1917,8 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) } break; case FC_ERROR: + FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " + "due to FC_ERROR\n"); sc_cmd->result = DID_ERROR << 16; break; case FC_DATA_UNDRUN: @@ -1915,12 +1927,19 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) * scsi status is good but transport level * underrun. */ - sc_cmd->result = (fsp->state & FC_SRB_RCV_STATUS ? - DID_OK : DID_ERROR) << 16; + if (fsp->state & FC_SRB_RCV_STATUS) { + sc_cmd->result = DID_OK << 16; + } else { + FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml" + " due to FC_DATA_UNDRUN (trans)\n"); + sc_cmd->result = DID_ERROR << 16; + } } else { /* * scsi got underrun, this is an error */ + FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " + "due to FC_DATA_UNDRUN (scsi)\n"); CMD_RESID_LEN(sc_cmd) = fsp->scsi_resid; sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status; } @@ -1929,12 +1948,16 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) /* * overrun is an error */ + FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " + "due to FC_DATA_OVRRUN\n"); 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; break; - case FC_CMD_TIME_OUT: + case FC_CMD_RECOVERY: sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status; break; case FC_CMD_RESET: @@ -1944,6 +1967,8 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) sc_cmd->result = (DID_NO_CONNECT << 16); break; default: + FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " + "due to unknown error\n"); sc_cmd->result = (DID_ERROR << 16); break; } @@ -2028,7 +2053,7 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd) if (lport->state != LPORT_ST_READY) return rc; - FC_SCSI_DBG(lport, "Resetting rport (%6x)\n", rport->port_id); + FC_SCSI_DBG(lport, "Resetting rport (%6.6x)\n", rport->port_id); fsp = fc_fcp_pkt_alloc(lport, GFP_NOIO); if (fsp == NULL) { @@ -2076,12 +2101,12 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) if (fc_fcp_lport_queue_ready(lport)) { shost_printk(KERN_INFO, shost, "libfc: Host reset succeeded " - "on port (%6x)\n", fc_host_port_id(lport->host)); + "on port (%6.6x)\n", lport->port_id); return SUCCESS; } else { shost_printk(KERN_INFO, shost, "libfc: Host reset failed, " - "port (%6x) is not ready.\n", - fc_host_port_id(lport->host)); + "port (%6.6x) is not ready.\n", + lport->port_id); return FAILED; } } @@ -2166,7 +2191,7 @@ void fc_fcp_destroy(struct fc_lport *lport) if (!list_empty(&si->scsi_pkt_queue)) printk(KERN_ERR "libfc: Leaked SCSI packets when destroying " - "port (%6x)\n", fc_host_port_id(lport->host)); + "port (%6.6x)\n", lport->port_id); mempool_destroy(si->scsi_pkt_pool); kfree(si); diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h index 741fd5c72e1..f5c0ca4b6ef 100644 --- a/drivers/scsi/libfc/fc_libfc.h +++ b/drivers/scsi/libfc/fc_libfc.h @@ -45,9 +45,9 @@ extern unsigned int fc_debug_logging; #define FC_LPORT_DBG(lport, fmt, args...) \ FC_CHECK_LOGGING(FC_LPORT_LOGGING, \ - printk(KERN_INFO "host%u: lport %6x: " fmt, \ + printk(KERN_INFO "host%u: lport %6.6x: " fmt, \ (lport)->host->host_no, \ - fc_host_port_id((lport)->host), ##args)) + (lport)->port_id, ##args)) #define FC_DISC_DBG(disc, fmt, args...) \ FC_CHECK_LOGGING(FC_DISC_LOGGING, \ @@ -57,7 +57,7 @@ extern unsigned int fc_debug_logging; #define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \ FC_CHECK_LOGGING(FC_RPORT_LOGGING, \ - printk(KERN_INFO "host%u: rport %6x: " fmt, \ + printk(KERN_INFO "host%u: rport %6.6x: " fmt, \ (lport)->host->host_no, \ (port_id), ##args)) @@ -66,7 +66,7 @@ extern unsigned int fc_debug_logging; #define FC_FCP_DBG(pkt, fmt, args...) \ FC_CHECK_LOGGING(FC_FCP_LOGGING, \ - printk(KERN_INFO "host%u: fcp: %6x: " fmt, \ + printk(KERN_INFO "host%u: fcp: %6.6x: " fmt, \ (pkt)->lp->host->host_no, \ pkt->rport->port_id, ##args)) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index d126ecfff70..79c9e3ccd34 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -172,7 +172,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, struct fc_rport_priv *rdata, enum fc_rport_event event) { - FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event, + FC_LPORT_DBG(lport, "Received a %d event for port (%6.6x)\n", event, rdata->ids.port_id); mutex_lock(&lport->lp_mutex); @@ -183,7 +183,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, fc_lport_enter_ns(lport, LPORT_ST_RNN_ID); } else { FC_LPORT_DBG(lport, "Received an READY event " - "on port (%6x) for the directory " + "on port (%6.6x) for the directory " "server, but the lport is not " "in the DNS state, it's in the " "%d state", rdata->ids.port_id, @@ -228,9 +228,12 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, u64 remote_wwnn) { mutex_lock(&lport->disc.disc_mutex); - if (lport->ptp_rdata) + if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); + kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); + } lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); + kref_get(&lport->ptp_rdata->kref); lport->ptp_rdata->ids.port_name = remote_wwpn; lport->ptp_rdata->ids.node_name = remote_wwnn; mutex_unlock(&lport->disc.disc_mutex); @@ -241,17 +244,6 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, } /** - * fc_get_host_port_type() - Return the port type of the given Scsi_Host - * @shost: The SCSI host whose port type is to be determined - */ -void fc_get_host_port_type(struct Scsi_Host *shost) -{ - /* TODO - currently just NPORT */ - fc_host_port_type(shost) = FC_PORTTYPE_NPORT; -} -EXPORT_SYMBOL(fc_get_host_port_type); - -/** * fc_get_host_port_state() - Return the port state of the given Scsi_Host * @shost: The SCSI host whose port state is to be determined */ @@ -572,8 +564,8 @@ void __fc_linkup(struct fc_lport *lport) */ void fc_linkup(struct fc_lport *lport) { - printk(KERN_INFO "host%d: libfc: Link up on port (%6x)\n", - lport->host->host_no, fc_host_port_id(lport->host)); + printk(KERN_INFO "host%d: libfc: Link up on port (%6.6x)\n", + lport->host->host_no, lport->port_id); mutex_lock(&lport->lp_mutex); __fc_linkup(lport); @@ -602,8 +594,8 @@ void __fc_linkdown(struct fc_lport *lport) */ void fc_linkdown(struct fc_lport *lport) { - printk(KERN_INFO "host%d: libfc: Link down on port (%6x)\n", - lport->host->host_no, fc_host_port_id(lport->host)); + printk(KERN_INFO "host%d: libfc: Link down on port (%6.6x)\n", + lport->host->host_no, lport->port_id); mutex_lock(&lport->lp_mutex); __fc_linkdown(lport); @@ -704,8 +696,8 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) break; case DISC_EV_FAILED: printk(KERN_ERR "host%d: libfc: " - "Discovery failed for port (%6x)\n", - lport->host->host_no, fc_host_port_id(lport->host)); + "Discovery failed for port (%6.6x)\n", + lport->host->host_no, lport->port_id); mutex_lock(&lport->lp_mutex); fc_lport_enter_reset(lport); mutex_unlock(&lport->lp_mutex); @@ -750,10 +742,14 @@ static void fc_lport_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp) { if (port_id) - printk(KERN_INFO "host%d: Assigned Port ID %6x\n", + printk(KERN_INFO "host%d: Assigned Port ID %6.6x\n", lport->host->host_no, port_id); + lport->port_id = port_id; + + /* Update the fc_host */ fc_host_port_id(lport->host) = port_id; + if (lport->tt.lport_set_port_id) lport->tt.lport_set_port_id(lport, port_id, fp); } @@ -797,11 +793,11 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, remote_wwpn = get_unaligned_be64(&flp->fl_wwpn); if (remote_wwpn == lport->wwpn) { printk(KERN_WARNING "host%d: libfc: Received FLOGI from port " - "with same WWPN %llx\n", + "with same WWPN %16.16llx\n", lport->host->host_no, remote_wwpn); goto out; } - FC_LPORT_DBG(lport, "FLOGI from port WWPN %llx\n", remote_wwpn); + FC_LPORT_DBG(lport, "FLOGI from port WWPN %16.16llx\n", remote_wwpn); /* * XXX what is the right thing to do for FIDs? @@ -832,7 +828,7 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, */ f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; ep = fc_seq_exch(sp); - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, + fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, remote_fid, local_fid, FC_TYPE_ELS, f_ctl, 0); lport->tt.seq_send(lport, sp, fp); @@ -947,14 +943,18 @@ static void fc_lport_reset_locked(struct fc_lport *lport) if (lport->dns_rdata) lport->tt.rport_logoff(lport->dns_rdata); - lport->ptp_rdata = NULL; + if (lport->ptp_rdata) { + lport->tt.rport_logoff(lport->ptp_rdata); + kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); + lport->ptp_rdata = NULL; + } lport->tt.disc_stop(lport); lport->tt.exch_mgr_reset(lport, 0, 0); fc_host_fabric_name(lport->host) = 0; - if (fc_host_port_id(lport->host)) + if (lport->port_id) fc_lport_set_port_id(lport, 0, NULL); } @@ -1492,7 +1492,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, lport->r_a_tov = 2 * e_d_tov; fc_lport_set_port_id(lport, did, fp); printk(KERN_INFO "host%d: libfc: " - "Port (%6x) entered " + "Port (%6.6x) entered " "point-to-point mode\n", lport->host->host_no, did); fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id), @@ -1699,7 +1699,7 @@ static int fc_lport_els_request(struct fc_bsg_job *job, fh = fc_frame_header_get(fp); fh->fh_r_ctl = FC_RCTL_ELS_REQ; hton24(fh->fh_d_id, did); - hton24(fh->fh_s_id, fc_host_port_id(lport->host)); + hton24(fh->fh_s_id, lport->port_id); fh->fh_type = FC_TYPE_ELS; hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT); @@ -1759,7 +1759,7 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, fh = fc_frame_header_get(fp); fh->fh_r_ctl = FC_RCTL_DD_UNSOL_CTL; hton24(fh->fh_d_id, did); - hton24(fh->fh_s_id, fc_host_port_id(lport->host)); + hton24(fh->fh_s_id, lport->port_id); fh->fh_type = FC_TYPE_CT; hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT); diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c index c68f6c7341c..dd2b43bb1c7 100644 --- a/drivers/scsi/libfc/fc_npiv.c +++ b/drivers/scsi/libfc/fc_npiv.c @@ -69,12 +69,15 @@ struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id) struct fc_lport *lport = NULL; struct fc_lport *vn_port; - if (fc_host_port_id(n_port->host) == port_id) + if (n_port->port_id == port_id) return n_port; + if (port_id == FC_FID_FLOGI) + return n_port; /* for point-to-point */ + mutex_lock(&n_port->lp_mutex); list_for_each_entry(vn_port, &n_port->vports, list) { - if (fc_host_port_id(vn_port->host) == port_id) { + if (vn_port->port_id == port_id) { lport = vn_port; break; } diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index b37d0ff28b3..39e440f0f54 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1442,136 +1442,115 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, struct fc_els_spp *spp; /* response spp */ unsigned int len; unsigned int plen; - enum fc_els_rjt_reason reason = ELS_RJT_UNAB; - enum fc_els_rjt_explan explan = ELS_EXPL_NONE; enum fc_els_spp_resp resp; struct fc_seq_els_data rjt_data; u32 f_ctl; u32 fcp_parm; u32 roles = FC_RPORT_ROLE_UNKNOWN; - rjt_data.fp = NULL; + rjt_data.fp = NULL; fh = fc_frame_header_get(rx_fp); FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", fc_rport_state(rdata)); - switch (rdata->rp_state) { - case RPORT_ST_PRLI: - case RPORT_ST_RTV: - case RPORT_ST_READY: - case RPORT_ST_ADISC: - reason = ELS_RJT_NONE; - break; - default: - fc_frame_free(rx_fp); - return; - break; - } len = fr_len(rx_fp) - sizeof(*fh); pp = fc_frame_payload_get(rx_fp, sizeof(*pp)); - if (pp == NULL) { - reason = ELS_RJT_PROT; - explan = ELS_EXPL_INV_LEN; - } else { - plen = ntohs(pp->prli.prli_len); - if ((plen % 4) != 0 || plen > len) { - reason = ELS_RJT_PROT; - explan = ELS_EXPL_INV_LEN; - } else if (plen < len) { - len = plen; - } - plen = pp->prli.prli_spp_len; - if ((plen % 4) != 0 || plen < sizeof(*spp) || - plen > len || len < sizeof(*pp)) { - reason = ELS_RJT_PROT; - explan = ELS_EXPL_INV_LEN; - } - rspp = &pp->spp; + if (!pp) + goto reject_len; + plen = ntohs(pp->prli.prli_len); + if ((plen % 4) != 0 || plen > len || plen < 16) + goto reject_len; + if (plen < len) + len = plen; + plen = pp->prli.prli_spp_len; + if ((plen % 4) != 0 || plen < sizeof(*spp) || + plen > len || len < sizeof(*pp) || plen < 12) + goto reject_len; + rspp = &pp->spp; + + fp = fc_frame_alloc(lport, len); + if (!fp) { + rjt_data.reason = ELS_RJT_UNAB; + rjt_data.explan = ELS_EXPL_INSUF_RES; + goto reject; } - if (reason != ELS_RJT_NONE || - (fp = fc_frame_alloc(lport, len)) == NULL) { - rjt_data.reason = reason; - rjt_data.explan = explan; - lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); - } else { - sp = lport->tt.seq_start_next(sp); - WARN_ON(!sp); - pp = fc_frame_payload_get(fp, len); - WARN_ON(!pp); - memset(pp, 0, len); - pp->prli.prli_cmd = ELS_LS_ACC; - pp->prli.prli_spp_len = plen; - pp->prli.prli_len = htons(len); - len -= sizeof(struct fc_els_prli); - - /* reinitialize remote port roles */ - rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; - - /* - * Go through all the service parameter pages and build - * response. If plen indicates longer SPP than standard, - * use that. The entire response has been pre-cleared above. - */ - spp = &pp->spp; - while (len >= plen) { - spp->spp_type = rspp->spp_type; - spp->spp_type_ext = rspp->spp_type_ext; - spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; - resp = FC_SPP_RESP_ACK; - if (rspp->spp_flags & FC_SPP_RPA_VAL) - resp = FC_SPP_RESP_NO_PA; - switch (rspp->spp_type) { - case 0: /* common to all FC-4 types */ - break; - case FC_TYPE_FCP: - fcp_parm = ntohl(rspp->spp_params); - if (fcp_parm & FCP_SPPF_RETRY) - rdata->flags |= FC_RP_FLAGS_RETRY; - rdata->supported_classes = FC_COS_CLASS3; - if (fcp_parm & FCP_SPPF_INIT_FCN) - roles |= FC_RPORT_ROLE_FCP_INITIATOR; - if (fcp_parm & FCP_SPPF_TARG_FCN) - roles |= FC_RPORT_ROLE_FCP_TARGET; - rdata->ids.roles = roles; - - spp->spp_params = - htonl(lport->service_params); - break; - default: - resp = FC_SPP_RESP_INVL; - break; - } - spp->spp_flags |= resp; - len -= plen; - rspp = (struct fc_els_spp *)((char *)rspp + plen); - spp = (struct fc_els_spp *)((char *)spp + plen); - } + sp = lport->tt.seq_start_next(sp); + WARN_ON(!sp); + pp = fc_frame_payload_get(fp, len); + WARN_ON(!pp); + memset(pp, 0, len); + pp->prli.prli_cmd = ELS_LS_ACC; + pp->prli.prli_spp_len = plen; + pp->prli.prli_len = htons(len); + len -= sizeof(struct fc_els_prli); - /* - * Send LS_ACC. If this fails, the originator should retry. - */ - f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; - f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; - ep = fc_seq_exch(sp); - fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, - FC_TYPE_ELS, f_ctl, 0); - lport->tt.seq_send(lport, sp, fp); + /* reinitialize remote port roles */ + rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN; - /* - * Get lock and re-check state. - */ - switch (rdata->rp_state) { - case RPORT_ST_PRLI: - fc_rport_enter_ready(rdata); + /* + * Go through all the service parameter pages and build + * response. If plen indicates longer SPP than standard, + * use that. The entire response has been pre-cleared above. + */ + spp = &pp->spp; + while (len >= plen) { + spp->spp_type = rspp->spp_type; + spp->spp_type_ext = rspp->spp_type_ext; + spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR; + resp = FC_SPP_RESP_ACK; + + switch (rspp->spp_type) { + case 0: /* common to all FC-4 types */ break; - case RPORT_ST_READY: - case RPORT_ST_ADISC: + case FC_TYPE_FCP: + fcp_parm = ntohl(rspp->spp_params); + if (fcp_parm & FCP_SPPF_RETRY) + rdata->flags |= FC_RP_FLAGS_RETRY; + rdata->supported_classes = FC_COS_CLASS3; + if (fcp_parm & FCP_SPPF_INIT_FCN) + roles |= FC_RPORT_ROLE_FCP_INITIATOR; + if (fcp_parm & FCP_SPPF_TARG_FCN) + roles |= FC_RPORT_ROLE_FCP_TARGET; + rdata->ids.roles = roles; + + spp->spp_params = htonl(lport->service_params); break; default: + resp = FC_SPP_RESP_INVL; break; } + spp->spp_flags |= resp; + len -= plen; + rspp = (struct fc_els_spp *)((char *)rspp + plen); + spp = (struct fc_els_spp *)((char *)spp + plen); + } + + /* + * Send LS_ACC. If this fails, the originator should retry. + */ + f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; + f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; + ep = fc_seq_exch(sp); + fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, + FC_TYPE_ELS, f_ctl, 0); + lport->tt.seq_send(lport, sp, fp); + + switch (rdata->rp_state) { + case RPORT_ST_PRLI: + fc_rport_enter_ready(rdata); + break; + default: + break; } + goto drop; + +reject_len: + rjt_data.reason = ELS_RJT_PROT; + rjt_data.explan = ELS_EXPL_INV_LEN; +reject: + lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); +drop: fc_frame_free(rx_fp); } |