diff options
Diffstat (limited to 'drivers/scsi/fnic')
-rw-r--r-- | drivers/scsi/fnic/fnic.h | 2 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_fcs.c | 5 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_main.c | 18 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_scsi.c | 32 | ||||
-rw-r--r-- | drivers/scsi/fnic/fnic_trace.c | 4 |
5 files changed, 51 insertions, 10 deletions
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index bf8d34c26f13..3b73b96619e2 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.11" +#define DRV_VERSION "1.6.0.16" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index f3984b48f8e9..bf0bbd42efb5 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -135,6 +135,11 @@ void fnic_handle_link(struct work_struct *work) fnic->lport->host->host_no, FNIC_FC_LE, "Link Status: UP_DOWN", strlen("Link Status: UP_DOWN")); + if (fnic->config.flags & VFCF_FIP_CAPABLE) { + FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, + "deleting fip-timer during link-down\n"); + del_timer_sync(&fnic->fip_timer); + } fcoe_ctlr_link_down(&fnic->ctlr); } diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index cf1560c30b7f..0c1f8177b5b7 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -98,7 +98,7 @@ static int fnic_slave_alloc(struct scsi_device *sdev) if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; - scsi_adjust_queue_depth(sdev, fnic_max_qdepth); + scsi_change_queue_depth(sdev, fnic_max_qdepth); return 0; } @@ -110,7 +110,7 @@ static struct scsi_host_template fnic_host_template = { .eh_device_reset_handler = fnic_device_reset, .eh_host_reset_handler = fnic_host_reset, .slave_alloc = fnic_slave_alloc, - .change_queue_depth = fc_change_queue_depth, + .change_queue_depth = scsi_change_queue_depth, .change_queue_type = scsi_change_queue_type, .this_id = -1, .cmd_per_lun = 3, @@ -120,6 +120,7 @@ static struct scsi_host_template fnic_host_template = { .max_sectors = 0xffff, .shost_attrs = fnic_attrs, .use_blk_tags = 1, + .track_queue_depth = 1, }; static void @@ -437,21 +438,30 @@ static int fnic_dev_wait(struct vnic_dev *vdev, unsigned long time; int done; int err; + int count; + + count = 0; err = start(vdev, arg); if (err) return err; - /* Wait for func to complete...2 seconds max */ + /* Wait for func to complete. + * Sometime schedule_timeout_uninterruptible take long time + * to wake up so we do not retry as we are only waiting for + * 2 seconds in while loop. By adding count, we make sure + * we try atleast three times before returning -ETIMEDOUT + */ time = jiffies + (HZ * 2); do { err = finished(vdev, &done); + count++; if (err) return err; if (done) return 0; schedule_timeout_uninterruptible(HZ / 10); - } while (time_after(time, jiffies)); + } while (time_after(time, jiffies) || (count < 3)); return -ETIMEDOUT; } diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 10d5c6bbc9e7..2097de42a147 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -421,8 +421,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ int ret; u64 cmd_trace; int sg_count = 0; - unsigned long flags; + unsigned long flags = 0; unsigned long ptr; + struct fc_rport_priv *rdata; + spinlock_t *io_lock = NULL; if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED))) return SCSI_MLQUEUE_HOST_BUSY; @@ -436,6 +438,16 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ return 0; } + rdata = lp->tt.rport_lookup(lp, rport->port_id); + if (!rdata || (rdata->rp_state == RPORT_ST_DELETE)) { + FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, + "returning IO as rport is removed\n"); + atomic64_inc(&fnic_stats->misc_stats.rport_not_ready); + sc->result = DID_NO_CONNECT; + done(sc); + return 0; + } + if (lp->state != LPORT_ST_READY || !(lp->link_up)) return SCSI_MLQUEUE_HOST_BUSY; @@ -498,6 +510,13 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ } } + /* + * Will acquire lock defore setting to IO initialized. + */ + + io_lock = fnic_io_lock_hash(fnic, sc); + spin_lock_irqsave(io_lock, flags); + /* initialize rest of io_req */ io_req->port_id = rport->port_id; io_req->start_time = jiffies; @@ -514,11 +533,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ * In case another thread cancelled the request, * refetch the pointer under the lock. */ - spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc); FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no, sc->request->tag, sc, 0, 0, 0, (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc))); - spin_lock_irqsave(io_lock, flags); io_req = (struct fnic_io_req *)CMD_SP(sc); CMD_SP(sc) = NULL; CMD_STATE(sc) = FNIC_IOREQ_CMD_COMPLETE; @@ -527,6 +544,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_ fnic_release_ioreq_buf(fnic, io_req, sc); mempool_free(io_req, fnic->io_req_pool); } + atomic_dec(&fnic->in_flight); + /* acquire host lock before returning to SCSI */ + spin_lock(lp->host->host_lock); + return ret; } else { atomic64_inc(&fnic_stats->io_stats.active_ios); atomic64_inc(&fnic_stats->io_stats.num_ios); @@ -548,6 +569,11 @@ out: sc->request->tag, sc, io_req, sg_count, cmd_trace, (((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc))); + + /* if only we issued IO, will we have the io lock */ + if (CMD_FLAGS(sc) & FNIC_IO_INITIALIZED) + spin_unlock_irqrestore(io_lock, flags); + atomic_dec(&fnic->in_flight); /* acquire host lock before returning to SCSI */ spin_lock(lp->host->host_lock); diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c index acf1f95cb5c5..65a9bde26974 100644 --- a/drivers/scsi/fnic/fnic_trace.c +++ b/drivers/scsi/fnic/fnic_trace.c @@ -624,12 +624,12 @@ int fnic_fc_trace_set_data(u32 host_no, u8 frame_type, if (frame_type == FNIC_FC_RECV) { eth_fcoe_hdr_len = sizeof(struct ethhdr) + sizeof(struct fcoe_hdr); - fc_trc_frame_len = fc_trc_frame_len + eth_fcoe_hdr_len; memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len); /* Copy the rest of data frame */ memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame, min_t(u8, fc_trc_frame_len, - (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE))); + (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE + - eth_fcoe_hdr_len))); } else { memcpy((char *)fc_trace, (void *)frame, min_t(u8, fc_trc_frame_len, |