From 09ac46c429464c919d04bb737b27edd84d944f02 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 14 Dec 2011 00:33:38 +0100 Subject: block: misc updates to blk_get_queue() * blk_get_queue() is peculiar in that it returns 0 on success and 1 on failure instead of 0 / -errno or boolean. Update it such that it returns %true on success and %false on failure. * Make sure the caller checks for the return value. * Separate out __blk_get_queue() which doesn't check whether @q is dead and put it in blk.h. This will be used later. This patch doesn't introduce any functional changes. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe --- drivers/scsi/scsi_scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index b3c6d957fbd8..89da43f73c00 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -297,7 +297,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, kfree(sdev); goto out; } - blk_get_queue(sdev->request_queue); + WARN_ON_ONCE(!blk_get_queue(sdev->request_queue)); sdev->request_queue->queuedata = sdev; scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); -- cgit From 4f10143f6e8cd62460920211e1b24b0915d0ab00 Mon Sep 17 00:00:00 2001 From: "Moger, Babu" Date: Thu, 1 Dec 2011 15:01:16 -0500 Subject: [SCSI] scsi_dh_emc: Add a match function for emc device handler This patch introduces the match function for emc device handler. Included check for TPGS bit before proceeding further. The match function was introduced by commit 6c3633d08acf514e2e89aa95d2346ce9d64d719a Signed-off-by: Babu Moger Acked-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_emc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 591186cf1896..e1c8be06de9d 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c @@ -629,6 +629,24 @@ static const struct scsi_dh_devlist clariion_dev_list[] = { {NULL, NULL}, }; +static bool clariion_match(struct scsi_device *sdev) +{ + int i; + + if (scsi_device_tpgs(sdev)) + return false; + + for (i = 0; clariion_dev_list[i].vendor; i++) { + if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor, + strlen(clariion_dev_list[i].vendor)) && + !strncmp(sdev->model, clariion_dev_list[i].model, + strlen(clariion_dev_list[i].model))) { + return true; + } + } + return false; +} + static int clariion_bus_attach(struct scsi_device *sdev); static void clariion_bus_detach(struct scsi_device *sdev); @@ -642,6 +660,7 @@ static struct scsi_device_handler clariion_dh = { .activate = clariion_activate, .prep_fn = clariion_prep_fn, .set_params = clariion_set_params, + .match = clariion_match, }; static int clariion_bus_attach(struct scsi_device *sdev) -- cgit From a315969e8d699682adf449813de84b7f2358f64d Mon Sep 17 00:00:00 2001 From: "Moger, Babu" Date: Thu, 1 Dec 2011 15:01:28 -0500 Subject: [SCSI] scsi_dh_hp_sw: Adding the match function for hp_sw device handler This patch introduces the match function for hp_sw device handler. Included the check for TPGS bit before proceeding further per Hannes comment. The match function was introduced by commit 6c3633d08acf514e2e89aa95d2346ce9d64d719a Signed-off-by: Babu Moger Acked-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_hp_sw.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 0f86a18b157d..084062bb8ee9 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -320,6 +320,24 @@ static const struct scsi_dh_devlist hp_sw_dh_data_list[] = { {NULL, NULL}, }; +static bool hp_sw_match(struct scsi_device *sdev) +{ + int i; + + if (scsi_device_tpgs(sdev)) + return false; + + for (i = 0; hp_sw_dh_data_list[i].vendor; i++) { + if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor, + strlen(hp_sw_dh_data_list[i].vendor)) && + !strncmp(sdev->model, hp_sw_dh_data_list[i].model, + strlen(hp_sw_dh_data_list[i].model))) { + return true; + } + } + return false; +} + static int hp_sw_bus_attach(struct scsi_device *sdev); static void hp_sw_bus_detach(struct scsi_device *sdev); @@ -331,6 +349,7 @@ static struct scsi_device_handler hp_sw_dh = { .detach = hp_sw_bus_detach, .activate = hp_sw_activate, .prep_fn = hp_sw_prep_fn, + .match = hp_sw_match, }; static int hp_sw_bus_attach(struct scsi_device *sdev) -- cgit From bee89eae8de143b1d9f82ab7ab6d9daef8e44760 Mon Sep 17 00:00:00 2001 From: "Moger, Babu" Date: Thu, 1 Dec 2011 15:01:40 -0500 Subject: [SCSI] scsi_dh_rdac: Adding the match function for rdac device handler This patch introduces the match function for rdac device handler. Without this, sometimes handler attach fails during the device_add. Included check for TPGS bit before proceeding further. The match function was introduced by commit 6c3633d08acf514e2e89aa95d2346ce9d64d719a Signed-off-by: Babu Moger Acked-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_rdac.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 1d3127920063..841ebf4a6788 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -820,6 +820,24 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { {NULL, NULL}, }; +static bool rdac_match(struct scsi_device *sdev) +{ + int i; + + if (scsi_device_tpgs(sdev)) + return false; + + for (i = 0; rdac_dev_list[i].vendor; i++) { + if (!strncmp(sdev->vendor, rdac_dev_list[i].vendor, + strlen(rdac_dev_list[i].vendor)) && + !strncmp(sdev->model, rdac_dev_list[i].model, + strlen(rdac_dev_list[i].model))) { + return true; + } + } + return false; +} + static int rdac_bus_attach(struct scsi_device *sdev); static void rdac_bus_detach(struct scsi_device *sdev); @@ -832,6 +850,7 @@ static struct scsi_device_handler rdac_dh = { .attach = rdac_bus_attach, .detach = rdac_bus_detach, .activate = rdac_activate, + .match = rdac_match, }; static int rdac_bus_attach(struct scsi_device *sdev) -- cgit From 2b132577a05ec2970581c99da70825430d5919df Mon Sep 17 00:00:00 2001 From: "Moger, Babu" Date: Thu, 1 Dec 2011 15:03:12 -0500 Subject: [SCSI] scsi_dh: code cleanup and remove the references to scsi_dev_info All the handlers have now implemented the match function so We don't need to use scsi_dev_info any more for matching purposes. Signed-off-by: Babu Moger Acked-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh.c | 58 ----------------------------------- drivers/scsi/scsi_priv.h | 1 - 2 files changed, 59 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index 23149b9e297c..48e46f5b77cc 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c @@ -28,7 +28,6 @@ static DEFINE_SPINLOCK(list_lock); static LIST_HEAD(scsi_dh_list); -static int scsi_dh_list_idx = 1; static struct scsi_device_handler *get_device_handler(const char *name) { @@ -45,21 +44,6 @@ static struct scsi_device_handler *get_device_handler(const char *name) return found; } -static struct scsi_device_handler *get_device_handler_by_idx(int idx) -{ - struct scsi_device_handler *tmp, *found = NULL; - - spin_lock(&list_lock); - list_for_each_entry(tmp, &scsi_dh_list, list) { - if (tmp->idx == idx) { - found = tmp; - break; - } - } - spin_unlock(&list_lock); - return found; -} - /* * device_handler_match_function - Match a device handler to a device * @sdev - SCSI device to be tested @@ -83,23 +67,6 @@ device_handler_match_function(struct scsi_device *sdev) return found_dh; } -/* - * device_handler_match_devlist - Match a device handler to a device - * @sdev - SCSI device to be tested - * - * Tests @sdev against all device_handler registered in the devlist. - * Returns the found device handler or NULL if not found. - */ -static struct scsi_device_handler * -device_handler_match_devlist(struct scsi_device *sdev) -{ - int idx; - - idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model, - SCSI_DEVINFO_DH); - return get_device_handler_by_idx(idx); -} - /* * device_handler_match - Attach a device handler to a device * @scsi_dh - The device handler to match against or NULL @@ -116,8 +83,6 @@ device_handler_match(struct scsi_device_handler *scsi_dh, struct scsi_device_handler *found_dh; found_dh = device_handler_match_function(sdev); - if (!found_dh) - found_dh = device_handler_match_devlist(sdev); if (scsi_dh && found_dh != scsi_dh) found_dh = NULL; @@ -361,25 +326,14 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data) */ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) { - int i; if (get_device_handler(scsi_dh->name)) return -EBUSY; spin_lock(&list_lock); - scsi_dh->idx = scsi_dh_list_idx++; list_add(&scsi_dh->list, &scsi_dh_list); spin_unlock(&list_lock); - for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) { - scsi_dev_info_list_add_keyed(0, - scsi_dh->devlist[i].vendor, - scsi_dh->devlist[i].model, - NULL, - scsi_dh->idx, - SCSI_DEVINFO_DH); - } - bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add); printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); @@ -396,7 +350,6 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler); */ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) { - int i; if (!get_device_handler(scsi_dh->name)) return -ENODEV; @@ -404,12 +357,6 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_remove); - for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) { - scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor, - scsi_dh->devlist[i].model, - SCSI_DEVINFO_DH); - } - spin_lock(&list_lock); list_del(&scsi_dh->list); spin_unlock(&list_lock); @@ -588,10 +535,6 @@ static int __init scsi_dh_init(void) { int r; - r = scsi_dev_info_add_list(SCSI_DEVINFO_DH, "SCSI Device Handler"); - if (r) - return r; - r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb); if (!r) @@ -606,7 +549,6 @@ static void __exit scsi_dh_exit(void) bus_for_each_dev(&scsi_bus_type, NULL, NULL, scsi_dh_sysfs_attr_remove); bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb); - scsi_dev_info_remove_list(SCSI_DEVINFO_DH); } module_init(scsi_dh_init); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 2a588955423a..68eadd1c67fd 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -45,7 +45,6 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) enum { SCSI_DEVINFO_GLOBAL = 0, SCSI_DEVINFO_SPI, - SCSI_DEVINFO_DH, }; extern int scsi_get_device_flags(struct scsi_device *sdev, -- cgit From 275a63acda70dc1fae0ee0cb6032aaec4dc801d2 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Wed, 16 Nov 2011 12:28:49 -0800 Subject: [SCSI] bfa: fix formating and checkpatch issues Fixed code indentation and alignment issues. Fixed all checkpatch warnings. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs_svc.h | 437 ++++++++++++++++++++-------------------- drivers/scsi/bfa/bfad_debugfs.c | 3 +- 2 files changed, 221 insertions(+), 219 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index 863c6ba7d5eb..78963be2c4fb 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -34,22 +34,22 @@ struct bfa_iocfc_intr_attr_s { u8 coalesce; /* enable/disable coalescing */ u8 rsvd[3]; - __be16 latency; /* latency in microseconds */ - __be16 delay; /* delay in microseconds */ + __be16 latency; /* latency in microseconds */ + __be16 delay; /* delay in microseconds */ }; /* * IOC firmware configuraton */ struct bfa_iocfc_fwcfg_s { - u16 num_fabrics; /* number of fabrics */ - u16 num_lports; /* number of local lports */ - u16 num_rports; /* number of remote ports */ - u16 num_ioim_reqs; /* number of IO reqs */ - u16 num_tskim_reqs; /* task management requests */ - u16 num_fwtio_reqs; /* number of TM IO reqs in FW */ - u16 num_fcxp_reqs; /* unassisted FC exchanges */ - u16 num_uf_bufs; /* unsolicited recv buffers */ + u16 num_fabrics; /* number of fabrics */ + u16 num_lports; /* number of local lports */ + u16 num_rports; /* number of remote ports */ + u16 num_ioim_reqs; /* number of IO reqs */ + u16 num_tskim_reqs; /* task management requests */ + u16 num_fwtio_reqs; /* number of TM IO reqs in FW */ + u16 num_fcxp_reqs; /* unassisted FC exchanges */ + u16 num_uf_bufs; /* unsolicited recv buffers */ u8 num_cqs; u8 fw_tick_res; /* FW clock resolution in ms */ u8 rsvd[2]; @@ -57,19 +57,19 @@ struct bfa_iocfc_fwcfg_s { #pragma pack() struct bfa_iocfc_drvcfg_s { - u16 num_reqq_elems; /* number of req queue elements */ - u16 num_rspq_elems; /* number of rsp queue elements */ - u16 num_sgpgs; /* number of total SG pages */ - u16 num_sboot_tgts; /* number of SAN boot targets */ - u16 num_sboot_luns; /* number of SAN boot luns */ - u16 ioc_recover; /* IOC recovery mode */ - u16 min_cfg; /* minimum configuration */ - u16 path_tov; /* device path timeout */ - u16 num_tio_reqs; /*!< number of TM IO reqs */ + u16 num_reqq_elems; /* number of req queue elements */ + u16 num_rspq_elems; /* number of rsp queue elements */ + u16 num_sgpgs; /* number of total SG pages */ + u16 num_sboot_tgts; /* number of SAN boot targets */ + u16 num_sboot_luns; /* number of SAN boot luns */ + u16 ioc_recover; /* IOC recovery mode */ + u16 min_cfg; /* minimum configuration */ + u16 path_tov; /* device path timeout */ + u16 num_tio_reqs; /* number of TM IO reqs */ u8 port_mode; u8 rsvd_a; - bfa_boolean_t delay_comp; /* delay completion of - failed inflight IOs */ + bfa_boolean_t delay_comp; /* delay completion of failed + * inflight IOs */ u16 num_ttsk_reqs; /* TM task management requests */ u32 rsvd; }; @@ -101,8 +101,8 @@ struct bfa_fw_ioim_stats_s { u32 fw_frm_drop; /* f/w drop the frame */ u32 rec_timeout; /* FW rec timed out */ - u32 error_rec; /* FW sending rec on - * an error condition*/ + u32 error_rec; /* FW sending rec on + * an error condition*/ u32 wait_for_si; /* FW wait for SI */ u32 rec_rsp_inval; /* REC rsp invalid */ u32 seqr_io_abort; /* target does not know cmd so abort */ @@ -124,9 +124,9 @@ struct bfa_fw_ioim_stats_s { u32 unexp_fcp_rsp; /* fcp response in wrong state */ u32 fcp_rsp_under_run; /* fcp rsp IO underrun */ - u32 fcp_rsp_under_run_wr; /* fcp rsp IO underrun for write */ + u32 fcp_rsp_under_run_wr; /* fcp rsp IO underrun for write */ u32 fcp_rsp_under_run_err; /* fcp rsp IO underrun error */ - u32 fcp_rsp_resid_inval; /* invalid residue */ + u32 fcp_rsp_resid_inval; /* invalid residue */ u32 fcp_rsp_over_run; /* fcp rsp IO overrun */ u32 fcp_rsp_over_run_err; /* fcp rsp IO overrun error */ u32 fcp_rsp_proto_err; /* protocol error in fcp rsp */ @@ -142,21 +142,20 @@ struct bfa_fw_ioim_stats_s { u32 ioh_hit_class2_event; /* IOH hit class2 */ u32 ioh_miss_other_event; /* IOH miss other */ u32 ioh_seq_cnt_err_event; /* IOH seq cnt error */ - u32 ioh_len_err_event; /* IOH len error - fcp_dl != - * bytes xfered */ + u32 ioh_len_err_event; /* IOH len error - fcp_dl != + * bytes xfered */ u32 ioh_seq_len_err_event; /* IOH seq len error */ u32 ioh_data_oor_event; /* Data out of range */ u32 ioh_ro_ooo_event; /* Relative offset out of range */ u32 ioh_cpu_owned_event; /* IOH hit -iost owned by f/w */ u32 ioh_unexp_frame_event; /* unexpected frame received - * count */ + * count */ u32 ioh_err_int; /* IOH error int during data-phase - * for scsi write - */ + * for scsi write */ }; struct bfa_fw_tio_stats_s { - u32 tio_conf_proc; /* TIO CONF processed */ + u32 tio_conf_proc; /* TIO CONF processed */ u32 tio_conf_drop; /* TIO CONF dropped */ u32 tio_cleanup_req; /* TIO cleanup requested */ u32 tio_cleanup_comp; /* TIO cleanup completed */ @@ -164,34 +163,36 @@ struct bfa_fw_tio_stats_s { u32 tio_abort_rsp_comp; /* TIO abort rsp completed */ u32 tio_abts_req; /* TIO ABTS requested */ u32 tio_abts_ack; /* TIO ABTS ack-ed */ - u32 tio_abts_ack_nocomp; /* TIO ABTS ack-ed but not completed */ + u32 tio_abts_ack_nocomp;/* TIO ABTS ack-ed but not completed */ u32 tio_abts_tmo; /* TIO ABTS timeout */ u32 tio_snsdata_dma; /* TIO sense data DMA */ - u32 tio_rxwchan_wait; /* TIO waiting for RX wait channel */ - u32 tio_rxwchan_avail; /* TIO RX wait channel available */ + u32 tio_rxwchan_wait; /* TIO waiting for RX wait channel */ + u32 tio_rxwchan_avail; /* TIO RX wait channel available */ u32 tio_hit_bls; /* TIO IOH BLS event */ u32 tio_uf_recv; /* TIO received UF */ - u32 tio_rd_invalid_sm; /* TIO read reqst in wrong state machine */ - u32 tio_wr_invalid_sm;/* TIO write reqst in wrong state machine */ + u32 tio_rd_invalid_sm; /* TIO read reqst in wrong state machine */ + u32 tio_wr_invalid_sm; /* TIO write reqst in wrong state machine */ - u32 ds_rxwchan_wait; /* DS waiting for RX wait channel */ - u32 ds_rxwchan_avail; /* DS RX wait channel available */ + u32 ds_rxwchan_wait; /* DS waiting for RX wait channel */ + u32 ds_rxwchan_avail; /* DS RX wait channel available */ u32 ds_unaligned_rd; /* DS unaligned read */ - u32 ds_rdcomp_invalid_sm; /* DS read completed in wrong state machine */ - u32 ds_wrcomp_invalid_sm; /* DS write completed in wrong state machine */ + u32 ds_rdcomp_invalid_sm; /* DS read completed in wrong state + * machine */ + u32 ds_wrcomp_invalid_sm; /* DS write completed in wrong state + * machine */ u32 ds_flush_req; /* DS flush requested */ u32 ds_flush_comp; /* DS flush completed */ u32 ds_xfrdy_exp; /* DS XFER_RDY expired */ u32 ds_seq_cnt_err; /* DS seq cnt error */ u32 ds_seq_len_err; /* DS seq len error */ u32 ds_data_oor; /* DS data out of order */ - u32 ds_hit_bls; /* DS hit BLS */ + u32 ds_hit_bls; /* DS hit BLS */ u32 ds_edtov_timer_exp; /* DS edtov expired */ u32 ds_cpu_owned; /* DS cpu owned */ u32 ds_hit_class2; /* DS hit class2 */ u32 ds_length_err; /* DS length error */ u32 ds_ro_ooo_err; /* DS relative offset out-of-order error */ - u32 ds_rectov_timer_exp; /* DS rectov expired */ + u32 ds_rectov_timer_exp;/* DS rectov expired */ u32 ds_unexp_fr_err; /* DS unexp frame error */ }; @@ -208,119 +209,119 @@ struct bfa_fw_io_stats_s { */ struct bfa_fw_port_fpg_stats_s { - u32 intr_evt; - u32 intr; - u32 intr_excess; - u32 intr_cause0; - u32 intr_other; - u32 intr_other_ign; - u32 sig_lost; - u32 sig_regained; - u32 sync_lost; - u32 sync_to; - u32 sync_regained; - u32 div2_overflow; - u32 div2_underflow; - u32 efifo_overflow; - u32 efifo_underflow; - u32 idle_rx; - u32 lrr_rx; - u32 lr_rx; - u32 ols_rx; - u32 nos_rx; - u32 lip_rx; - u32 arbf0_rx; - u32 arb_rx; - u32 mrk_rx; - u32 const_mrk_rx; - u32 prim_unknown; + u32 intr_evt; + u32 intr; + u32 intr_excess; + u32 intr_cause0; + u32 intr_other; + u32 intr_other_ign; + u32 sig_lost; + u32 sig_regained; + u32 sync_lost; + u32 sync_to; + u32 sync_regained; + u32 div2_overflow; + u32 div2_underflow; + u32 efifo_overflow; + u32 efifo_underflow; + u32 idle_rx; + u32 lrr_rx; + u32 lr_rx; + u32 ols_rx; + u32 nos_rx; + u32 lip_rx; + u32 arbf0_rx; + u32 arb_rx; + u32 mrk_rx; + u32 const_mrk_rx; + u32 prim_unknown; }; struct bfa_fw_port_lksm_stats_s { - u32 hwsm_success; /* hwsm state machine success */ - u32 hwsm_fails; /* hwsm fails */ - u32 hwsm_wdtov; /* hwsm timed out */ - u32 swsm_success; /* swsm success */ - u32 swsm_fails; /* swsm fails */ - u32 swsm_wdtov; /* swsm timed out */ - u32 busybufs; /* link init failed due to busybuf */ - u32 buf_waits; /* bufwait state entries */ - u32 link_fails; /* link failures */ - u32 psp_errors; /* primitive sequence protocol errors */ - u32 lr_unexp; /* No. of times LR rx-ed unexpectedly */ - u32 lrr_unexp; /* No. of times LRR rx-ed unexpectedly */ - u32 lr_tx; /* No. of times LR tx started */ - u32 lrr_tx; /* No. of times LRR tx started */ - u32 ols_tx; /* No. of times OLS tx started */ - u32 nos_tx; /* No. of times NOS tx started */ - u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */ - u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */ - u32 bbsc_lr; /* LKSM LR tx for credit recovery */ + u32 hwsm_success; /* hwsm state machine success */ + u32 hwsm_fails; /* hwsm fails */ + u32 hwsm_wdtov; /* hwsm timed out */ + u32 swsm_success; /* swsm success */ + u32 swsm_fails; /* swsm fails */ + u32 swsm_wdtov; /* swsm timed out */ + u32 busybufs; /* link init failed due to busybuf */ + u32 buf_waits; /* bufwait state entries */ + u32 link_fails; /* link failures */ + u32 psp_errors; /* primitive sequence protocol errors */ + u32 lr_unexp; /* No. of times LR rx-ed unexpectedly */ + u32 lrr_unexp; /* No. of times LRR rx-ed unexpectedly */ + u32 lr_tx; /* No. of times LR tx started */ + u32 lrr_tx; /* No. of times LRR tx started */ + u32 ols_tx; /* No. of times OLS tx started */ + u32 nos_tx; /* No. of times NOS tx started */ + u32 hwsm_lrr_rx; /* No. of times LRR rx-ed by HWSM */ + u32 hwsm_lr_rx; /* No. of times LR rx-ed by HWSM */ + u32 bbsc_lr; /* LKSM LR tx for credit recovery */ }; struct bfa_fw_port_snsm_stats_s { - u32 hwsm_success; /* Successful hwsm terminations */ - u32 hwsm_fails; /* hwsm fail count */ - u32 hwsm_wdtov; /* hwsm timed out */ - u32 swsm_success; /* swsm success */ - u32 swsm_wdtov; /* swsm timed out */ - u32 error_resets; /* error resets initiated by upsm */ - u32 sync_lost; /* Sync loss count */ - u32 sig_lost; /* Signal loss count */ - u32 asn8g_attempts; /* SNSM HWSM at 8Gbps attempts */ + u32 hwsm_success; /* Successful hwsm terminations */ + u32 hwsm_fails; /* hwsm fail count */ + u32 hwsm_wdtov; /* hwsm timed out */ + u32 swsm_success; /* swsm success */ + u32 swsm_wdtov; /* swsm timed out */ + u32 error_resets; /* error resets initiated by upsm */ + u32 sync_lost; /* Sync loss count */ + u32 sig_lost; /* Signal loss count */ + u32 asn8g_attempts; /* SNSM HWSM at 8Gbps attempts */ }; struct bfa_fw_port_physm_stats_s { - u32 module_inserts; /* Module insert count */ - u32 module_xtracts; /* Module extracts count */ - u32 module_invalids; /* Invalid module inserted count */ - u32 module_read_ign; /* Module validation status ignored */ - u32 laser_faults; /* Laser fault count */ - u32 rsvd; + u32 module_inserts; /* Module insert count */ + u32 module_xtracts; /* Module extracts count */ + u32 module_invalids; /* Invalid module inserted count */ + u32 module_read_ign; /* Module validation status ignored */ + u32 laser_faults; /* Laser fault count */ + u32 rsvd; }; struct bfa_fw_fip_stats_s { - u32 vlan_req; /* vlan discovery requests */ - u32 vlan_notify; /* vlan notifications */ - u32 vlan_err; /* vlan response error */ - u32 vlan_timeouts; /* vlan disvoery timeouts */ - u32 vlan_invalids; /* invalid vlan in discovery advert. */ - u32 disc_req; /* Discovery solicit requests */ - u32 disc_rsp; /* Discovery solicit response */ - u32 disc_err; /* Discovery advt. parse errors */ - u32 disc_unsol; /* Discovery unsolicited */ - u32 disc_timeouts; /* Discovery timeouts */ - u32 disc_fcf_unavail; /* Discovery FCF Not Avail. */ - u32 linksvc_unsupp; /* Unsupported link service req */ - u32 linksvc_err; /* Parse error in link service req */ - u32 logo_req; /* FIP logos received */ - u32 clrvlink_req; /* Clear virtual link req */ - u32 op_unsupp; /* Unsupported FIP operation */ - u32 untagged; /* Untagged frames (ignored) */ - u32 invalid_version; /* Invalid FIP version */ + u32 vlan_req; /* vlan discovery requests */ + u32 vlan_notify; /* vlan notifications */ + u32 vlan_err; /* vlan response error */ + u32 vlan_timeouts; /* vlan disvoery timeouts */ + u32 vlan_invalids; /* invalid vlan in discovery advert. */ + u32 disc_req; /* Discovery solicit requests */ + u32 disc_rsp; /* Discovery solicit response */ + u32 disc_err; /* Discovery advt. parse errors */ + u32 disc_unsol; /* Discovery unsolicited */ + u32 disc_timeouts; /* Discovery timeouts */ + u32 disc_fcf_unavail; /* Discovery FCF Not Avail. */ + u32 linksvc_unsupp; /* Unsupported link service req */ + u32 linksvc_err; /* Parse error in link service req */ + u32 logo_req; /* FIP logos received */ + u32 clrvlink_req; /* Clear virtual link req */ + u32 op_unsupp; /* Unsupported FIP operation */ + u32 untagged; /* Untagged frames (ignored) */ + u32 invalid_version; /* Invalid FIP version */ }; struct bfa_fw_lps_stats_s { - u32 mac_invalids; /* Invalid mac assigned */ - u32 rsvd; + u32 mac_invalids; /* Invalid mac assigned */ + u32 rsvd; }; struct bfa_fw_fcoe_stats_s { - u32 cee_linkups; /* CEE link up count */ - u32 cee_linkdns; /* CEE link down count */ - u32 fip_linkups; /* FIP link up count */ - u32 fip_linkdns; /* FIP link up count */ - u32 fip_fails; /* FIP fail count */ - u32 mac_invalids; /* Invalid mac assigned */ + u32 cee_linkups; /* CEE link up count */ + u32 cee_linkdns; /* CEE link down count */ + u32 fip_linkups; /* FIP link up count */ + u32 fip_linkdns; /* FIP link up count */ + u32 fip_fails; /* FIP fail count */ + u32 mac_invalids; /* Invalid mac assigned */ }; /* * IOC firmware FCoE port stats */ struct bfa_fw_fcoe_port_stats_s { - struct bfa_fw_fcoe_stats_s fcoe_stats; - struct bfa_fw_fip_stats_s fip_stats; + struct bfa_fw_fcoe_stats_s fcoe_stats; + struct bfa_fw_fip_stats_s fip_stats; }; /* @@ -335,8 +336,8 @@ struct bfa_fw_fc_uport_stats_s { * IOC firmware FC port stats */ union bfa_fw_fc_port_stats_s { - struct bfa_fw_fc_uport_stats_s fc_stats; - struct bfa_fw_fcoe_port_stats_s fcoe_stats; + struct bfa_fw_fc_uport_stats_s fc_stats; + struct bfa_fw_fcoe_port_stats_s fcoe_stats; }; /* @@ -366,25 +367,25 @@ struct bfa_fw_lpsm_stats_s { */ struct bfa_fw_trunk_stats_s { u32 emt_recvd; /* Trunk EMT received */ - u32 emt_accepted; /* Trunk EMT Accepted */ - u32 emt_rejected; /* Trunk EMT rejected */ + u32 emt_accepted; /* Trunk EMT Accepted */ + u32 emt_rejected; /* Trunk EMT rejected */ u32 etp_recvd; /* Trunk ETP received */ - u32 etp_accepted; /* Trunk ETP Accepted */ - u32 etp_rejected; /* Trunk ETP rejected */ + u32 etp_accepted; /* Trunk ETP Accepted */ + u32 etp_rejected; /* Trunk ETP rejected */ u32 lr_recvd; /* Trunk LR received */ - u32 rsvd; /* padding for 64 bit alignment */ + u32 rsvd; /* padding for 64 bit alignment */ }; struct bfa_fw_advsm_stats_s { u32 flogi_sent; /* Flogi sent */ u32 flogi_acc_recvd; /* Flogi Acc received */ u32 flogi_rjt_recvd; /* Flogi rejects received */ - u32 flogi_retries; /* Flogi retries */ + u32 flogi_retries; /* Flogi retries */ u32 elp_recvd; /* ELP received */ - u32 elp_accepted; /* ELP Accepted */ - u32 elp_rejected; /* ELP rejected */ - u32 elp_dropped; /* ELP dropped */ + u32 elp_accepted; /* ELP Accepted */ + u32 elp_rejected; /* ELP rejected */ + u32 elp_dropped; /* ELP dropped */ }; /* @@ -521,7 +522,7 @@ struct bfa_qos_vc_attr_s { u16 total_vc_count; /* Total VC Count */ u16 shared_credit; u32 elp_opmode_flags; - struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC]; /* as many as + struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC]; /* as many as * total_vc_count */ }; @@ -531,16 +532,16 @@ struct bfa_qos_vc_attr_s { struct bfa_qos_stats_s { u32 flogi_sent; /* QoS Flogi sent */ u32 flogi_acc_recvd; /* QoS Flogi Acc received */ - u32 flogi_rjt_recvd; /* QoS Flogi rejects received */ + u32 flogi_rjt_recvd; /* QoS Flogi rejects received */ u32 flogi_retries; /* QoS Flogi retries */ u32 elp_recvd; /* QoS ELP received */ u32 elp_accepted; /* QoS ELP Accepted */ - u32 elp_rejected; /* QoS ELP rejected */ - u32 elp_dropped; /* QoS ELP dropped */ + u32 elp_rejected; /* QoS ELP rejected */ + u32 elp_dropped; /* QoS ELP dropped */ - u32 qos_rscn_recvd; /* QoS RSCN received */ - u32 rsvd; /* padding for 64 bit alignment */ + u32 qos_rscn_recvd; /* QoS RSCN received */ + u32 rsvd; /* padding for 64 bit alignment */ }; /* @@ -548,9 +549,9 @@ struct bfa_qos_stats_s { */ struct bfa_fcoe_stats_s { u64 secs_reset; /* Seconds since stats reset */ - u64 cee_linkups; /* CEE link up */ + u64 cee_linkups; /* CEE link up */ u64 cee_linkdns; /* CEE link down */ - u64 fip_linkups; /* FIP link up */ + u64 fip_linkups; /* FIP link up */ u64 fip_linkdns; /* FIP link down */ u64 fip_fails; /* FIP failures */ u64 mac_invalids; /* Invalid mac assignments */ @@ -560,38 +561,38 @@ struct bfa_fcoe_stats_s { u64 vlan_timeouts; /* Vlan request timeouts */ u64 vlan_invalids; /* Vlan invalids */ u64 disc_req; /* Discovery requests */ - u64 disc_rsp; /* Discovery responses */ + u64 disc_rsp; /* Discovery responses */ u64 disc_err; /* Discovery error frames */ u64 disc_unsol; /* Discovery unsolicited */ u64 disc_timeouts; /* Discovery timeouts */ u64 disc_fcf_unavail; /* Discovery FCF not avail */ - u64 linksvc_unsupp; /* FIP link service req unsupp. */ - u64 linksvc_err; /* FIP link service req errors */ + u64 linksvc_unsupp; /* FIP link service req unsupp */ + u64 linksvc_err; /* FIP link service req errors */ u64 logo_req; /* FIP logos received */ - u64 clrvlink_req; /* Clear virtual link requests */ + u64 clrvlink_req; /* Clear virtual link requests */ u64 op_unsupp; /* FIP operation unsupp. */ - u64 untagged; /* FIP untagged frames */ + u64 untagged; /* FIP untagged frames */ u64 txf_ucast; /* Tx FCoE unicast frames */ - u64 txf_ucast_vlan; /* Tx FCoE unicast vlan frames */ + u64 txf_ucast_vlan; /* Tx FCoE unicast vlan frames */ u64 txf_ucast_octets; /* Tx FCoE unicast octets */ u64 txf_mcast; /* Tx FCoE multicast frames */ - u64 txf_mcast_vlan; /* Tx FCoE multicast vlan frames */ + u64 txf_mcast_vlan; /* Tx FCoE multicast vlan frames */ u64 txf_mcast_octets; /* Tx FCoE multicast octets */ u64 txf_bcast; /* Tx FCoE broadcast frames */ - u64 txf_bcast_vlan; /* Tx FCoE broadcast vlan frames */ + u64 txf_bcast_vlan; /* Tx FCoE broadcast vlan frames */ u64 txf_bcast_octets; /* Tx FCoE broadcast octets */ - u64 txf_timeout; /* Tx timeouts */ + u64 txf_timeout; /* Tx timeouts */ u64 txf_parity_errors; /* Transmit parity err */ - u64 txf_fid_parity_errors; /* Transmit FID parity err */ + u64 txf_fid_parity_errors; /* Transmit FID parity err */ u64 rxf_ucast_octets; /* Rx FCoE unicast octets */ u64 rxf_ucast; /* Rx FCoE unicast frames */ - u64 rxf_ucast_vlan; /* Rx FCoE unicast vlan frames */ + u64 rxf_ucast_vlan; /* Rx FCoE unicast vlan frames */ u64 rxf_mcast_octets; /* Rx FCoE multicast octets */ u64 rxf_mcast; /* Rx FCoE multicast frames */ - u64 rxf_mcast_vlan; /* Rx FCoE multicast vlan frames */ + u64 rxf_mcast_vlan; /* Rx FCoE multicast vlan frames */ u64 rxf_bcast_octets; /* Rx FCoE broadcast octets */ u64 rxf_bcast; /* Rx FCoE broadcast frames */ - u64 rxf_bcast_vlan; /* Rx FCoE broadcast vlan frames */ + u64 rxf_bcast_vlan; /* Rx FCoE broadcast vlan frames */ }; /* @@ -852,12 +853,12 @@ struct bfa_port_cfg_s { u8 tx_bbcredit; /* transmit buffer credits */ u8 ratelimit; /* ratelimit enabled or not */ u8 trl_def_speed; /* ratelimit default speed */ - u8 bb_scn; /* BB_SCN value from FLOGI Exchg */ - u8 bb_scn_state; /* Config state of BB_SCN */ - u8 faa_state; /* FAA enabled/disabled */ - u8 rsvd[1]; - u16 path_tov; /* device path timeout */ - u16 q_depth; /* SCSI Queue depth */ + u8 bb_scn; /* BB_SCN value from FLOGI Exchg */ + u8 bb_scn_state; /* Config state of BB_SCN */ + u8 faa_state; /* FAA enabled/disabled */ + u8 rsvd[1]; + u16 path_tov; /* device path timeout */ + u16 q_depth; /* SCSI Queue depth */ }; #pragma pack() @@ -868,20 +869,21 @@ struct bfa_port_attr_s { /* * Static fields */ - wwn_t nwwn; /* node wwn */ - wwn_t pwwn; /* port wwn */ - wwn_t factorynwwn; /* factory node wwn */ - wwn_t factorypwwn; /* factory port wwn */ - enum fc_cos cos_supported; /* supported class of services */ - u32 rsvd; + wwn_t nwwn; /* node wwn */ + wwn_t pwwn; /* port wwn */ + wwn_t factorynwwn; /* factory node wwn */ + wwn_t factorypwwn; /* factory port wwn */ + enum fc_cos cos_supported; /* supported class of + * services */ + u32 rsvd; struct fc_symname_s port_symname; /* port symbolic name */ - enum bfa_port_speed speed_supported; /* supported speeds */ - bfa_boolean_t pbind_enabled; + enum bfa_port_speed speed_supported; /* supported speeds */ + bfa_boolean_t pbind_enabled; /* * Configured values */ - struct bfa_port_cfg_s pport_cfg; /* pport cfg */ + struct bfa_port_cfg_s pport_cfg; /* pport cfg */ /* * Dynamic field - info from BFA @@ -890,19 +892,20 @@ struct bfa_port_attr_s { enum bfa_port_speed speed; /* current speed */ enum bfa_port_topology topology; /* current topology */ bfa_boolean_t beacon; /* current beacon status */ - bfa_boolean_t link_e2e_beacon; /* link beacon is on */ - bfa_boolean_t bbsc_op_status; /* fc credit recovery oper state */ + bfa_boolean_t link_e2e_beacon; /* link beacon is on */ + bfa_boolean_t bbsc_op_status; /* fc credit recovery oper + * state */ /* * Dynamic field - info from FCS */ - u32 pid; /* port ID */ + u32 pid; /* port ID */ enum bfa_port_type port_type; /* current topology */ - u32 loopback; /* external loopback */ - u32 authfail; /* auth fail state */ + u32 loopback; /* external loopback */ + u32 authfail; /* auth fail state */ /* FCoE specific */ - u16 fcoe_vlan; + u16 fcoe_vlan; u8 rsvd1[2]; }; @@ -910,48 +913,48 @@ struct bfa_port_attr_s { * Port FCP mappings. */ struct bfa_port_fcpmap_s { - char osdevname[256]; + char osdevname[256]; u32 bus; u32 target; u32 oslun; u32 fcid; - wwn_t nwwn; - wwn_t pwwn; + wwn_t nwwn; + wwn_t pwwn; u64 fcplun; - char luid[256]; + char luid[256]; }; /* * Port RNID info. */ struct bfa_port_rnid_s { - wwn_t wwn; + wwn_t wwn; u32 unittype; u32 portid; u32 attached_nodes_num; u16 ip_version; u16 udp_port; - u8 ipaddr[16]; + u8 ipaddr[16]; u16 rsvd; u16 topologydiscoveryflags; }; #pragma pack(1) struct bfa_fcport_fcf_s { - wwn_t name; /* FCF name */ - wwn_t fabric_name; /* Fabric Name */ - u8 fipenabled; /* FIP enabled or not */ - u8 fipfailed; /* FIP failed or not */ - u8 resv[2]; - u8 pri; /* FCF priority */ - u8 version; /* FIP version used */ - u8 available; /* Available for login */ - u8 fka_disabled; /* FKA is disabled */ - u8 maxsz_verified; /* FCoE max size verified */ - u8 fc_map[3]; /* FC map */ - __be16 vlan; /* FCoE vlan tag/priority */ - u32 fka_adv_per; /* FIP ka advert. period */ - mac_t mac; /* FCF mac */ + wwn_t name; /* FCF name */ + wwn_t fabric_name; /* Fabric Name */ + u8 fipenabled; /* FIP enabled or not */ + u8 fipfailed; /* FIP failed or not */ + u8 resv[2]; + u8 pri; /* FCF priority */ + u8 version; /* FIP version used */ + u8 available; /* Available for login */ + u8 fka_disabled; /* FKA is disabled */ + u8 maxsz_verified; /* FCoE max size verified */ + u8 fc_map[3]; /* FC map */ + __be16 vlan; /* FCoE vlan tag/priority */ + u32 fka_adv_per; /* FIP ka advert. period */ + mac_t mac; /* FCF mac */ }; /* @@ -981,7 +984,7 @@ struct bfa_port_link_s { u8 linkstate_rsn; /* bfa_port_linkstate_rsn_t */ u8 topology; /* P2P/LOOP bfa_port_topology */ u8 speed; /* Link speed (1/2/4/8 G) */ - u32 linkstate_opt; /* Linkstate optional data (debug) */ + u32 linkstate_opt; /* Linkstate optional data (debug) */ u8 trunked; /* Trunked or not (1 or 0) */ u8 resvd[3]; struct bfa_qos_attr_s qos_attr; /* QoS Attributes */ @@ -1035,7 +1038,7 @@ struct bfa_rport_hal_stats_s { u32 sm_fwc_del; /* fw create: delete events */ u32 sm_fwc_off; /* fw create: offline events */ u32 sm_fwc_hwf; /* fw create: IOC down */ - u32 sm_fwc_unexp; /* fw create: exception events*/ + u32 sm_fwc_unexp; /* fw create: exception events*/ u32 sm_on_off; /* online: offline events */ u32 sm_on_del; /* online: delete events */ u32 sm_on_hwf; /* online: IOC down events */ @@ -1043,25 +1046,25 @@ struct bfa_rport_hal_stats_s { u32 sm_fwd_rsp; /* fw delete: fw responses */ u32 sm_fwd_del; /* fw delete: delete events */ u32 sm_fwd_hwf; /* fw delete: IOC down events */ - u32 sm_fwd_unexp; /* fw delete: exception events*/ + u32 sm_fwd_unexp; /* fw delete: exception events*/ u32 sm_off_del; /* offline: delete events */ u32 sm_off_on; /* offline: online events */ u32 sm_off_hwf; /* offline: IOC down events */ - u32 sm_off_unexp; /* offline: exception events */ - u32 sm_del_fwrsp; /* delete: fw responses */ + u32 sm_off_unexp; /* offline: exception events */ + u32 sm_del_fwrsp; /* delete: fw responses */ u32 sm_del_hwf; /* delete: IOC down events */ - u32 sm_del_unexp; /* delete: exception events */ - u32 sm_delp_fwrsp; /* delete pend: fw responses */ + u32 sm_del_unexp; /* delete: exception events */ + u32 sm_delp_fwrsp; /* delete pend: fw responses */ u32 sm_delp_hwf; /* delete pend: IOC downs */ - u32 sm_delp_unexp; /* delete pend: exceptions */ - u32 sm_offp_fwrsp; /* off-pending: fw responses */ + u32 sm_delp_unexp; /* delete pend: exceptions */ + u32 sm_offp_fwrsp; /* off-pending: fw responses */ u32 sm_offp_del; /* off-pending: deletes */ u32 sm_offp_hwf; /* off-pending: IOC downs */ - u32 sm_offp_unexp; /* off-pending: exceptions */ + u32 sm_offp_unexp; /* off-pending: exceptions */ u32 sm_iocd_off; /* IOC down: offline events */ u32 sm_iocd_del; /* IOC down: delete events */ u32 sm_iocd_on; /* IOC down: online events */ - u32 sm_iocd_unexp; /* IOC down: exceptions */ + u32 sm_iocd_unexp; /* IOC down: exceptions */ u32 rsvd; }; #pragma pack(1) @@ -1069,9 +1072,9 @@ struct bfa_rport_hal_stats_s { * Rport's QoS attributes */ struct bfa_rport_qos_attr_s { - u8 qos_priority; /* rport's QoS priority */ - u8 rsvd[3]; - u32 qos_flow_id; /* QoS flow Id */ + u8 qos_priority; /* rport's QoS priority */ + u8 rsvd[3]; + u32 qos_flow_id; /* QoS flow Id */ }; #pragma pack() diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c index dee1a094c2c2..53b60d85a319 100644 --- a/drivers/scsi/bfa/bfad_debugfs.c +++ b/drivers/scsi/bfa/bfad_debugfs.c @@ -557,8 +557,7 @@ bfad_debugfs_exit(struct bfad_port_s *port) } } - /* - * Remove the pci_dev debugfs directory for the port */ + /* Remove the pci_dev debugfs directory for the port */ if (port->port_debugfs_root) { debugfs_remove(port->port_debugfs_root); port->port_debugfs_root = NULL; -- cgit From 98cdfb4347f5d38b97de2045d688e44e2a26ea42 Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Wed, 16 Nov 2011 12:29:26 -0800 Subject: [SCSI] bfa: fix endian and bit field check bug Fix some endian issue. __BIGENDIAN is not defined and it needs to be replaced with __BIG_ENDIAN. Also fixed a bug in bit field access. These two issues were reported by Dan Carpenter. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs.h | 4 ++-- drivers/scsi/bfa/bfa_ioc.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index 7b3d235d20b4..b5a1595cc0a5 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -902,7 +902,7 @@ struct sfp_mem_s { union sfp_xcvr_e10g_code_u { u8 b; struct { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u8 e10g_unall:1; /* 10G Ethernet compliance */ u8 e10g_lrm:1; u8 e10g_lr:1; @@ -982,7 +982,7 @@ union sfp_xcvr_fc2_code_u { union sfp_xcvr_fc3_code_u { u8 b; struct { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u8 rsv4:1; u8 mb800:1; /* 800 Mbytes/sec */ u8 mb1600:1; /* 1600 Mbytes/sec */ diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 1ac5aecf25a6..eca7ab78085b 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -3727,11 +3727,11 @@ bfa_sfp_media_get(struct bfa_sfp_s *sfp) (xmtr_tech & SFP_XMTR_TECH_SA)) *media = BFA_SFP_MEDIA_SW; /* Check 10G Ethernet Compilance code */ - else if (e10g.b & 0x10) + else if (e10g.r.e10g_sr) *media = BFA_SFP_MEDIA_SW; - else if (e10g.b & 0x60) + else if (e10g.r.e10g_lrm && e10g.r.e10g_lr) *media = BFA_SFP_MEDIA_LW; - else if (e10g.r.e10g_unall & 0x80) + else if (e10g.r.e10g_unall) *media = BFA_SFP_MEDIA_UNKNOWN; else bfa_trc(sfp, 0); -- cgit From 086b3e8a399ecd089534280597cfba45b2b55887 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 18 Nov 2011 09:03:05 -0800 Subject: [SCSI] qla2xxx: Use less stack to emit logging messages. Return early when logging level too low. Use normal kernel codeing style for function braces. Add const where appropriate to logging functions. Remove now unused #define QL_DBG_BUF_LEN. Signed-off-by: Joe Perches Signed-off-by: Saurav Kashyap Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 212 ++++++++++++++++++++--------------------- drivers/scsi/qla2xxx/qla_dbg.h | 10 +- 2 files changed, 107 insertions(+), 115 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index f3cddd5800c3..6db16af1a446 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -1664,34 +1664,31 @@ qla81xx_fw_dump_failed: * msg: The message to be displayed. */ void -ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) { +ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) +{ + va_list va; + struct va_format vaf; - char pbuf[QL_DBG_BUF_LEN]; - va_list ap; - uint32_t len; - struct pci_dev *pdev = NULL; + if ((level & ql2xextended_error_logging) != level) + return; - memset(pbuf, 0, QL_DBG_BUF_LEN); + va_start(va, fmt); - va_start(ap, msg); + vaf.fmt = fmt; + vaf.va = &va; - if ((level & ql2xextended_error_logging) == level) { - if (vha != NULL) { - pdev = vha->hw->pdev; - /* : Message */ - sprintf(pbuf, "%s [%s]-%04x:%ld: ", QL_MSGHDR, - dev_name(&(pdev->dev)), id + ql_dbg_offset, - vha->host_no); - } else - sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR, - "0000:00:00.0", id + ql_dbg_offset); - - len = strlen(pbuf); - vsprintf(pbuf+len, msg, ap); - pr_warning("%s", pbuf); + if (vha != NULL) { + const struct pci_dev *pdev = vha->hw->pdev; + /* : Message */ + pr_warn("%s [%s]-%04x:%ld: %pV", + QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, + vha->host_no, &vaf); + } else { + pr_warn("%s [%s]-%04x: : %pV", + QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf); } - va_end(ap); + va_end(va); } @@ -1710,31 +1707,27 @@ ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) { * msg: The message to be displayed. */ void -ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) { - - char pbuf[QL_DBG_BUF_LEN]; - va_list ap; - uint32_t len; +ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, + const char *fmt, ...) +{ + va_list va; + struct va_format vaf; if (pdev == NULL) return; + if ((level & ql2xextended_error_logging) != level) + return; - memset(pbuf, 0, QL_DBG_BUF_LEN); - - va_start(ap, msg); - - if ((level & ql2xextended_error_logging) == level) { - /* : Message */ - sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR, - dev_name(&(pdev->dev)), id + ql_dbg_offset); + va_start(va, fmt); - len = strlen(pbuf); - vsprintf(pbuf+len, msg, ap); - pr_warning("%s", pbuf); - } + vaf.fmt = fmt; + vaf.va = &va; - va_end(ap); + /* : Message */ + pr_warn("%s [%s]-%04x: : %pV", + QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, &vaf); + va_end(va); } /* @@ -1751,47 +1744,47 @@ ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) { * msg: The message to be displayed. */ void -ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) { - - char pbuf[QL_DBG_BUF_LEN]; - va_list ap; - uint32_t len; - struct pci_dev *pdev = NULL; - - memset(pbuf, 0, QL_DBG_BUF_LEN); - - va_start(ap, msg); - - if (level <= ql_errlev) { - if (vha != NULL) { - pdev = vha->hw->pdev; - /* : Message */ - sprintf(pbuf, "%s [%s]-%04x:%ld: ", QL_MSGHDR, - dev_name(&(pdev->dev)), id, vha->host_no); - } else - sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR, - "0000:00:00.0", id); +ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) +{ + va_list va; + struct va_format vaf; + char pbuf[128]; - len = strlen(pbuf); - vsprintf(pbuf+len, msg, ap); + if (level > ql_errlev) + return; - switch (level) { - case 0: /* FATAL LOG */ - pr_crit("%s", pbuf); - break; - case 1: - pr_err("%s", pbuf); - break; - case 2: - pr_warn("%s", pbuf); - break; - default: - pr_info("%s", pbuf); - break; - } + if (vha != NULL) { + const struct pci_dev *pdev = vha->hw->pdev; + /* : Message */ + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ", + QL_MSGHDR, dev_name(&(pdev->dev)), id, vha->host_no); + } else { + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", + QL_MSGHDR, "0000:00:00.0", id); + } + pbuf[sizeof(pbuf) - 1] = 0; + + va_start(va, fmt); + + vaf.fmt = fmt; + vaf.va = &va; + + switch (level) { + case 0: /* FATAL LOG */ + pr_crit("%s%pV", pbuf, &vaf); + break; + case 1: + pr_err("%s%pV", pbuf, &vaf); + break; + case 2: + pr_warn("%s%pV", pbuf, &vaf); + break; + default: + pr_info("%s%pV", pbuf, &vaf); + break; } - va_end(ap); + va_end(va); } /* @@ -1809,43 +1802,44 @@ ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, char *msg, ...) { * msg: The message to be displayed. */ void -ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, char *msg, ...) { - - char pbuf[QL_DBG_BUF_LEN]; - va_list ap; - uint32_t len; +ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id, + const char *fmt, ...) +{ + va_list va; + struct va_format vaf; + char pbuf[128]; if (pdev == NULL) return; + if (level > ql_errlev) + return; - memset(pbuf, 0, QL_DBG_BUF_LEN); - - va_start(ap, msg); - - if (level <= ql_errlev) { - /* : Message */ - sprintf(pbuf, "%s [%s]-%04x: : ", QL_MSGHDR, - dev_name(&(pdev->dev)), id); - - len = strlen(pbuf); - vsprintf(pbuf+len, msg, ap); - switch (level) { - case 0: /* FATAL LOG */ - pr_crit("%s", pbuf); - break; - case 1: - pr_err("%s", pbuf); - break; - case 2: - pr_warn("%s", pbuf); - break; - default: - pr_info("%s", pbuf); - break; - } + /* : Message */ + snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ", + QL_MSGHDR, dev_name(&(pdev->dev)), id); + pbuf[sizeof(pbuf) - 1] = 0; + + va_start(va, fmt); + + vaf.fmt = fmt; + vaf.va = &va; + + switch (level) { + case 0: /* FATAL LOG */ + pr_crit("%s%pV", pbuf, &vaf); + break; + case 1: + pr_err("%s%pV", pbuf, &vaf); + break; + case 2: + pr_warn("%s%pV", pbuf, &vaf); + break; + default: + pr_info("%s%pV", pbuf, &vaf); + break; } - va_end(ap); + va_end(va); } void @@ -1888,7 +1882,7 @@ ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id, ql_dbg(level, vha, id, "----------------------------------" "----------------------------\n"); - ql_dbg(level, vha, id, ""); + ql_dbg(level, vha, id, " "); for (cnt = 0; cnt < size;) { c = *b++; printk("%02x", (uint32_t) c); diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 98a377b99017..06928141cf64 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -245,14 +245,14 @@ struct qla2xxx_fw_dump { extern int ql_errlev; void -ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, char *, ...); +ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...); void -ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, char *, ...); +ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); void -ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, char *, ...); +ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...); void -ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, char *, ...); +ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); /* Debug Levels */ /* The 0x40000000 is the max value any debug level can have @@ -275,5 +275,3 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, char *, ...); #define ql_dbg_misc 0x00010000 /* For dumping everything that is not * not covered by upper categories */ - -#define QL_DBG_BUF_LEN 512 -- cgit From d8424f68c0160c45c446e56cb586fd8b9c538a1a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 18 Nov 2011 09:03:06 -0800 Subject: [SCSI] qla2xxx: Make the logging functions verify their arguments and fixed the current broken uses as appropriate. Signed-off-by: Joe Perches Signed-off-by: Saurav Kashyap Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 4 ++-- drivers/scsi/qla2xxx/qla_dbg.h | 8 ++++---- drivers/scsi/qla2xxx/qla_init.c | 3 ++- drivers/scsi/qla2xxx/qla_iocb.c | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 2 +- drivers/scsi/qla2xxx/qla_nx.c | 15 +++++++-------- drivers/scsi/qla2xxx/qla_os.c | 12 ++++++------ drivers/scsi/qla2xxx/qla_sup.c | 5 +++-- 8 files changed, 26 insertions(+), 25 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 6465dae5883a..9298649514a5 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -667,7 +667,7 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj, dev, adr, len, opt); if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x7074, - "Unable to write EDC (%x) %02x:%04x:%02x:%02hhx\n", + "Unable to write EDC (%x) %02x:%04x:%02x:%02x:%02hhx\n", rval, dev, adr, opt, len, buf[8]); return -EIO; } @@ -724,7 +724,7 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj, dev, adr, len, opt); if (rval != QLA_SUCCESS) { ql_log(ql_log_info, vha, 0x7075, - "Unable to write EDC status (%x) %02x:%04x:%02x.\n", + "Unable to write EDC status (%x) %02x:%04x:%02x:%02x.\n", rval, dev, adr, opt, len); return -EIO; } diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 06928141cf64..29a7822848ae 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -244,14 +244,14 @@ struct qla2xxx_fw_dump { extern int ql_errlev; -void +void __attribute__((format (printf, 4, 5))) ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...); -void +void __attribute__((format (printf, 4, 5))) ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); -void +void __attribute__((format (printf, 4, 5))) ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...); -void +void __attribute__((format (printf, 4, 5))) ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); /* Debug Levels */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 54ea68cec4c5..68cd0dd528df 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -4188,7 +4188,8 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) spin_unlock_irqrestore(&ha->vport_slock, flags); } else { - ql_log(ql_log_warn, vha, 0x8023, "%s **** FAILED ****.\n"); + ql_log(ql_log_warn, vha, 0x8023, "%s **** FAILED ****.\n", + __func__); } return(status); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index a4b267e60a35..d63132536c88 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1004,7 +1004,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, sle_dma = sg_dma_address(sg); ql_dbg(ql_dbg_io, vha, 0x300a, "sg entry %d - addr=0x%x 0x%x, " "len=%d for cmd=%p.\n", - cur_dsd, i, LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg), + i, LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg), sp->cmd); *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 7b91b290ffd6..53d83d66a015 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -298,7 +298,7 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) return; ql_dbg(ql_dbg_async, vha, 0x5022, - "Inter-Driver Commucation %s -- ACK timeout=%d.\n", + "%lu Inter-Driver Communication %s -- ACK timeout=%d.\n", vha->host_no, event[aen & 0xff], timeout); rval = qla2x00_post_idc_ack_work(vha, mb); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 03554934b0a5..360b9cb7153f 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -369,7 +369,7 @@ qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off) ql_dbg(ql_dbg_p3p, vha, 0xb000, "%s: Written crbwin (0x%x) " "!= Read crbwin (0x%x), off=0x%lx.\n", - ha->crb_win, win_read, *off); + __func__, ha->crb_win, win_read, *off); } *off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase; } @@ -409,7 +409,7 @@ qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off) } /* strange address given */ ql_dbg(ql_dbg_p3p, vha, 0xb001, - "%x: Warning: unm_nic_pci_set_crbwindow " + "%s: Warning: unm_nic_pci_set_crbwindow " "called with an unknown address(%llx).\n", QLA2XXX_DRIVER_NAME, off); return off; @@ -1711,12 +1711,12 @@ qla82xx_iospace_config(struct qla_hw_data *ha) ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc006, "nx_pci_base=%p iobase=%p " "max_req_queues=%d msix_count=%d.\n", - ha->nx_pcibase, ha->iobase, + (void *)ha->nx_pcibase, ha->iobase, ha->max_req_queues, ha->msix_count); ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0010, "nx_pci_base=%p iobase=%p " "max_req_queues=%d msix_count=%d.\n", - ha->nx_pcibase, ha->iobase, + (void *)ha->nx_pcibase, ha->iobase, ha->max_req_queues, ha->msix_count); return 0; @@ -1744,7 +1744,7 @@ qla82xx_pci_config(scsi_qla_host_t *vha) ret = pci_set_mwi(ha->pdev); ha->chip_revision = ha->pdev->revision; ql_dbg(ql_dbg_init, vha, 0x0043, - "Chip revision:%ld.\n", + "Chip revision:%d.\n", ha->chip_revision); return 0; } @@ -3661,8 +3661,7 @@ qla82xx_check_md_needed(scsi_qla_host_t *vha) qla82xx_md_prep(vha); } else ql_log(ql_log_info, vha, 0xb02e, - "Firmware dump available to retrieve\n", - vha->host_no); + "Firmware dump available to retrieve\n"); } } return rval; @@ -4067,7 +4066,7 @@ int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha) } } ql_dbg(ql_dbg_p3p, vha, 0xb027, - "%s status=%d.\n", status); + "%s: status=%d.\n", __func__, status); return status; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f9e5b85e84d8..8b4214502e45 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1017,7 +1017,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, eh_reset_failed: ql_log(ql_log_info, vha, 0x800f, "%s RESET FAILED: %s for id %d lun %d cmd=%p.\n", name, - reset_errors[err], cmd->device->id, cmd->device->lun); + reset_errors[err], cmd->device->id, cmd->device->lun, cmd); return FAILED; } @@ -1819,7 +1819,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) else ha->flags.port0 = 0; ql_dbg_pci(ql_dbg_init, ha->pdev, 0x000b, - "device_type=0x%x port=%d fw_srisc_address=%p.\n", + "device_type=0x%x port=%d fw_srisc_address=0x%x.\n", ha->device_type, ha->flags.port0, ha->fw_srisc_address); } @@ -1860,8 +1860,8 @@ qla2x00_iospace_config(struct qla_hw_data *ha) } ha->pio_address = pio; ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0014, - "PIO address=%p.\n", - ha->pio_address); + "PIO address=%llu.\n", + (unsigned long long)ha->pio_address); skip_pio: /* Use MMIO operations for all accesses. */ @@ -2227,7 +2227,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql_dbg(ql_dbg_init, base_vha, 0x0033, "max_id=%d this_id=%d " "cmd_per_len=%d unique_id=%d max_cmd_len=%d max_channel=%d " - "max_lun=%d transportt=%p, vendor_id=%d.\n", host->max_id, + "max_lun=%d transportt=%p, vendor_id=%llu.\n", host->max_id, host->this_id, host->cmd_per_lun, host->unique_id, host->max_cmd_len, host->max_channel, host->max_lun, host->transportt, sht->vendor_id); @@ -2833,7 +2833,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, if (!ha->sns_cmd) goto fail_dma_pool; ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0026, - "sns_cmd.\n", ha->sns_cmd); + "sns_cmd: %p.\n", ha->sns_cmd); } else { /* Get consistent memory allocated for MS IOCB */ ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index eff13563c82d..16bc72844a97 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -904,8 +904,9 @@ no_flash_data: } done: ql_dbg(ql_dbg_init, vha, 0x004d, - "FDT[%x]: (0x%x/0x%x) erase=0x%x " - "pr=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid, + "FDT[%s]: (0x%x/0x%x) erase=0x%x " + "pr=%x wrtd=0x%x blk=0x%x.\n", + loc, mid, fid, ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, ha->fdt_wrt_disable, ha->fdt_block_size); -- cgit From cfb0919c12a33132f75fb91971bbd8bdd44ebb90 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 18 Nov 2011 09:03:07 -0800 Subject: [SCSI] qla2xxx: Update to dynamic logging. This patch contains minor fixes to our new logging infrastructure: - Remove extranous messages. - Re-add 'nexus' and 'hdl' information. - Adjusted the message ids to fill up the holes. - Display FCP_CMND priority on update. - Log only mail box error conditions. - Do not print "Firmware ready **** FAILED ****" if cable is unplugged. - Drop noisy 'fw_state...curr time...' message. - Correct nexus display during abort. - Add a special case error-logging set to '1'. - Catagorize I/O exception display handling. - Correct the bsg msg code printing. - Dont use dynamic logging after host is removed. Signed-off-by: Saurav Kashyap Signed-off-by: Andrew Vasquez Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 2 +- drivers/scsi/qla2xxx/qla_bsg.c | 2 +- drivers/scsi/qla2xxx/qla_dbg.c | 93 +++++++++++++----------- drivers/scsi/qla2xxx/qla_dbg.h | 1 + drivers/scsi/qla2xxx/qla_def.h | 4 -- drivers/scsi/qla2xxx/qla_gs.c | 2 +- drivers/scsi/qla2xxx/qla_init.c | 84 +++++++++++----------- drivers/scsi/qla2xxx/qla_isr.c | 152 ++++++++++++++++++---------------------- drivers/scsi/qla2xxx/qla_nx.c | 6 +- drivers/scsi/qla2xxx/qla_os.c | 69 +++++++----------- 10 files changed, 199 insertions(+), 216 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 9298649514a5..efab503fc866 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1971,8 +1971,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) "Queue delete failed.\n"); } - scsi_host_put(vha->host); ql_log(ql_log_info, vha, 0x7088, "VP[%d] deleted.\n", id); + scsi_host_put(vha->host); return 0; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 8b641a8a0c74..371d0de7e30b 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1653,7 +1653,7 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job) } ql_dbg(ql_dbg_user, vha, 0x7000, - "Entered %s msgcode=%d.\n", __func__, bsg_job->request->msgcode); + "Entered %s msgcode=0x%x.\n", __func__, bsg_job->request->msgcode); switch (bsg_job->request->msgcode) { case FC_BSG_RPT_ELS: diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 6db16af1a446..58e0bfbfcd33 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -11,15 +11,16 @@ * ---------------------------------------------------------------------- * | Level | Last Value Used | Holes | * ---------------------------------------------------------------------- - * | Module Init and Probe | 0x0116 | | + * | Module Init and Probe | 0x0116 | 0xfa | * | Mailbox commands | 0x112b | | - * | Device Discovery | 0x2083 | | - * | Queue Command and IO tracing | 0x302e | 0x3008 | + * | Device Discovery | 0x2084 | | + * | Queue Command and IO tracing | 0x302f | 0x3008 | * | DPC Thread | 0x401c | | - * | Async Events | 0x5059 | | - * | Timer Routines | 0x6010 | 0x600e,0x600f | - * | User Space Interactions | 0x709d | | - * | Task Management | 0x8041 | 0x800b | + * | Async Events | 0x5057 | 0x5052 | + * | Timer Routines | 0x6011 | 0x600e,0x600f | + * | User Space Interactions | 0x709e | | + * | Task Management | 0x803c | 0x8025-0x8026 | + * | | | 0x800b,0x8039 | * | AER/EEH | 0x900f | | * | Virtual Port | 0xa007 | | * | ISP82XX Specific | 0xb052 | | @@ -1650,6 +1651,15 @@ qla81xx_fw_dump_failed: /****************************************************************************/ /* Driver Debug Functions. */ /****************************************************************************/ + +static inline int +ql_mask_match(uint32_t level) +{ + if (ql2xextended_error_logging == 1) + ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK; + return (level & ql2xextended_error_logging) == level; +} + /* * This function is for formatting and logging debug information. * It is to be used when vha is available. It formats the message @@ -1669,7 +1679,7 @@ ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...) va_list va; struct va_format vaf; - if ((level & ql2xextended_error_logging) != level) + if (!ql_mask_match(level)) return; va_start(va, fmt); @@ -1715,7 +1725,7 @@ ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id, if (pdev == NULL) return; - if ((level & ql2xextended_error_logging) != level) + if (!ql_mask_match(level)) return; va_start(va, fmt); @@ -1852,20 +1862,20 @@ ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id) struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82; uint16_t __iomem *mbx_reg; - if ((level & ql2xextended_error_logging) == level) { - - if (IS_QLA82XX(ha)) - mbx_reg = ®82->mailbox_in[0]; - else if (IS_FWI2_CAPABLE(ha)) - mbx_reg = ®24->mailbox0; - else - mbx_reg = MAILBOX_REG(ha, reg, 0); + if (!ql_mask_match(level)) + return; - ql_dbg(level, vha, id, "Mailbox registers:\n"); - for (i = 0; i < 6; i++) - ql_dbg(level, vha, id, - "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++)); - } + if (IS_QLA82XX(ha)) + mbx_reg = ®82->mailbox_in[0]; + else if (IS_FWI2_CAPABLE(ha)) + mbx_reg = ®24->mailbox0; + else + mbx_reg = MAILBOX_REG(ha, reg, 0); + + ql_dbg(level, vha, id, "Mailbox registers:\n"); + for (i = 0; i < 6; i++) + ql_dbg(level, vha, id, + "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++)); } @@ -1875,24 +1885,25 @@ ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id, { uint32_t cnt; uint8_t c; - if ((level & ql2xextended_error_logging) == level) { - - ql_dbg(level, vha, id, " 0 1 2 3 4 5 6 7 8 " - "9 Ah Bh Ch Dh Eh Fh\n"); - ql_dbg(level, vha, id, "----------------------------------" - "----------------------------\n"); - - ql_dbg(level, vha, id, " "); - for (cnt = 0; cnt < size;) { - c = *b++; - printk("%02x", (uint32_t) c); - cnt++; - if (!(cnt % 16)) - printk("\n"); - else - printk(" "); - } - if (cnt % 16) - ql_dbg(level, vha, id, "\n"); + + if (!ql_mask_match(level)) + return; + + ql_dbg(level, vha, id, " 0 1 2 3 4 5 6 7 8 " + "9 Ah Bh Ch Dh Eh Fh\n"); + ql_dbg(level, vha, id, "----------------------------------" + "----------------------------\n"); + + ql_dbg(level, vha, id, " "); + for (cnt = 0; cnt < size;) { + c = *b++; + printk("%02x", (uint32_t) c); + cnt++; + if (!(cnt % 16)) + printk("\n"); + else + printk(" "); } + if (cnt % 16) + ql_dbg(level, vha, id, "\n"); } diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 29a7822848ae..5f1b6d9c3dcb 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -232,6 +232,7 @@ struct qla2xxx_fw_dump { }; #define QL_MSGHDR "qla2xxx" +#define QL_DBG_DEFAULT1_MASK 0x1e400000 #define ql_log_fatal 0 /* display fatal errors */ #define ql_log_warn 1 /* display critical errors */ diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index fcf052c50bf5..964e2886311b 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2978,10 +2978,6 @@ typedef struct scsi_qla_host { atomic_dec(&__vha->vref_count); \ } while (0) - -#define qla_printk(level, ha, format, arg...) \ - dev_printk(level , &((ha)->pdev->dev) , format , ## arg) - /* * qla2x00 local function return status codes */ diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 37937aa3c3b8..4aea4ae23300 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -758,7 +758,7 @@ qla2x00_sns_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport) "GA_NXT Send SNS failed (%d).\n", rval); } else if (sns_cmd->p.gan_data[8] != 0x80 || sns_cmd->p.gan_data[9] != 0x02) { - ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x207d, + ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x2084, "GA_NXT failed, rejected request ga_nxt_rsp:\n"); ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2074, sns_cmd->p.gan_data, 16); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 68cd0dd528df..ec73cc191273 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -154,8 +154,8 @@ qla2x00_async_iocb_timeout(srb_t *sp) struct srb_ctx *ctx = sp->ctx; ql_dbg(ql_dbg_disc, fcport->vha, 0x2071, - "Async-%s timeout - portid=%02x%02x%02x.\n", - ctx->name, fcport->d_id.b.domain, fcport->d_id.b.area, + "Async-%s timeout - hdl=%x portid=%02x%02x%02x.\n", + ctx->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); fcport->flags &= ~FCF_ASYNC_SENT; @@ -211,9 +211,10 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, goto done_free_sp; ql_dbg(ql_dbg_disc, vha, 0x2072, - "Async-login - loopid=%x portid=%02x%02x%02x retries=%d.\n", - fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa, fcport->login_retry); + "Async-login - hdl=%x, loopid=%x portid=%02x%02x%02x " + "retries=%d.\n", sp->handle, fcport->loop_id, + fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, + fcport->login_retry); return rval; done_free_sp: @@ -258,9 +259,9 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) goto done_free_sp; ql_dbg(ql_dbg_disc, vha, 0x2070, - "Async-logout - loop-id=%x portid=%02x%02x%02x.\n", - fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa); + "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x.\n", + sp->handle, fcport->loop_id, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa); return rval; done_free_sp: @@ -308,9 +309,9 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport, goto done_free_sp; ql_dbg(ql_dbg_disc, vha, 0x206f, - "Async-adisc - loopid=%x portid=%02x%02x%02x.\n", - fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa); + "Async-adisc - hdl=%x loopid=%x portid=%02x%02x%02x.\n", + sp->handle, fcport->loop_id, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa); return rval; done_free_sp: @@ -360,9 +361,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, goto done_free_sp; ql_dbg(ql_dbg_taskm, vha, 0x802f, - "Async-tmf loop-id=%x portid=%02x%02x%02x.\n", - fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa); + "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", + sp->handle, fcport->loop_id, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa); return rval; done_free_sp: @@ -514,7 +515,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) set_bit(0, ha->req_qid_map); set_bit(0, ha->rsp_qid_map); - ql_log(ql_log_info, vha, 0x0040, + ql_dbg(ql_dbg_init, vha, 0x0040, "Configuring PCI space...\n"); rval = ha->isp_ops->pci_config(vha); if (rval) { @@ -533,7 +534,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) } ha->isp_ops->get_flash_version(vha, req->ring); - ql_log(ql_log_info, vha, 0x0061, + ql_dbg(ql_dbg_init, vha, 0x0061, "Configure NVRAM parameters...\n"); ha->isp_ops->nvram_config(vha); @@ -550,7 +551,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) return QLA_FUNCTION_FAILED; } - ql_log(ql_log_info, vha, 0x0078, + ql_dbg(ql_dbg_init, vha, 0x0078, "Verifying loaded RISC code...\n"); if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) { @@ -1294,7 +1295,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) ha->flags.fce_enabled = 0; goto try_eft; } - ql_log(ql_log_info, vha, 0x00c0, + ql_dbg(ql_dbg_init, vha, 0x00c0, "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024); fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE; @@ -1321,7 +1322,7 @@ try_eft: tc_dma); goto cont_alloc; } - ql_log(ql_log_info, vha, 0x00c3, + ql_dbg(ql_dbg_init, vha, 0x00c3, "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024); eft_size = EFT_SIZE; @@ -1358,7 +1359,7 @@ cont_alloc: } return; } - ql_log(ql_log_info, vha, 0x00c5, + ql_dbg(ql_dbg_init, vha, 0x00c5, "Allocated (%d KB) for firmware dump.\n", dump_size / 1024); ha->fw_dump_len = dump_size; @@ -1929,7 +1930,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha) rval = qla84xx_init_chip(vha); if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, - vha, 0x8026, + vha, 0x8007, "Init chip failed.\n"); break; } @@ -1938,7 +1939,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha) cs84xx_time = jiffies - cs84xx_time; wtime += cs84xx_time; mtime += cs84xx_time; - ql_dbg(ql_dbg_taskm, vha, 0x8025, + ql_dbg(ql_dbg_taskm, vha, 0x8008, "Increasing wait time by %ld. " "New time %ld.\n", cs84xx_time, wtime); @@ -1981,16 +1982,13 @@ qla2x00_fw_ready(scsi_qla_host_t *vha) /* Delay for a while */ msleep(500); - - ql_dbg(ql_dbg_taskm, vha, 0x8039, - "fw_state=%x curr time=%lx.\n", state[0], jiffies); } while (1); ql_dbg(ql_dbg_taskm, vha, 0x803a, "fw_state=%x (%x, %x, %x, %x) " "curr time=%lx.\n", state[0], state[1], state[2], state[3], state[4], jiffies); - if (rval) { + if (rval && !(vha->device_flags & DFLG_NO_CABLE)) { ql_log(ql_log_warn, vha, 0x803b, "Firmware ready **** FAILED ****.\n"); } @@ -2386,7 +2384,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) * internal driver logging. */ if (nv->host_p[0] & BIT_7) - ql2xextended_error_logging = 0x7fffffff; + ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK; ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0); /* Always load RISC code on non ISP2[12]00 chips. */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) @@ -4639,7 +4637,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, struct req_que *req = ha->req_q_map[0]; ql_dbg(ql_dbg_init, vha, 0x008b, - "Loading firmware from flash (%x).\n", faddr); + "FW: Loading firmware from flash (%x).\n", faddr); rval = QLA_SUCCESS; @@ -4837,8 +4835,8 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) return QLA_FUNCTION_FAILED; } - ql_log(ql_log_info, vha, 0x0092, - "Loading via request-firmware.\n"); + ql_dbg(ql_dbg_init, vha, 0x0092, + "FW: Loading via request-firmware.\n"); rval = QLA_SUCCESS; @@ -5426,7 +5424,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) if ((vha->device_flags & DFLG_NO_CABLE)) status = 0; - ql_log(ql_log_info, vha, 0x803d, + ql_log(ql_log_info, vha, 0x8000, "Configure loop done, status = 0x%x.\n", status); } @@ -5459,7 +5457,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) ha->fce_dma, ha->fce_bufs, ha->fce_mb, &ha->fce_bufs); if (rval) { - ql_log(ql_log_warn, vha, 0x803e, + ql_log(ql_log_warn, vha, 0x8001, "Unable to reinitialize FCE (%d).\n", rval); ha->flags.fce_enabled = 0; @@ -5471,7 +5469,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) rval = qla2x00_enable_eft_trace(vha, ha->eft_dma, EFT_NUM_BUFFERS); if (rval) { - ql_log(ql_log_warn, vha, 0x803f, + ql_log(ql_log_warn, vha, 0x8010, "Unable to reinitialize EFT (%d).\n", rval); } @@ -5479,7 +5477,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) } if (!status) { - ql_dbg(ql_dbg_taskm, vha, 0x8040, + ql_dbg(ql_dbg_taskm, vha, 0x8011, "qla82xx_restart_isp succeeded.\n"); spin_lock_irqsave(&ha->vport_slock, flags); @@ -5497,7 +5495,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) spin_unlock_irqrestore(&ha->vport_slock, flags); } else { - ql_log(ql_log_warn, vha, 0x8041, + ql_log(ql_log_warn, vha, 0x8016, "qla82xx_restart_isp **** FAILED ****.\n"); } @@ -5645,12 +5643,20 @@ qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport) return QLA_FUNCTION_FAILED; ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb); - if (ret == QLA_SUCCESS) + if (ret == QLA_SUCCESS) { + if (fcport->fcp_prio != priority) + ql_dbg(ql_dbg_user, vha, 0x709e, + "Updated FCP_CMND priority - value=%d loop_id=%d " + "port_id=%02x%02x%02x.\n", priority, + fcport->loop_id, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa); fcport->fcp_prio = priority; - else + } else ql_dbg(ql_dbg_user, vha, 0x704f, - "Unable to activate fcp priority, ret=0x%x.\n", ret); - + "Unable to update FCP_CMND priority - ret=0x%x for " + "loop_id=%d port_id=%02x%02x%02x.\n", ret, fcport->loop_id, + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa); return ret; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 53d83d66a015..b6023e9636ea 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -262,13 +262,8 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) wptr++; } - if (ha->mcp) { - ql_dbg(ql_dbg_async, vha, 0x5000, - "Got mbx completion. cmd=%x.\n", ha->mcp->mb[0]); - } else { - ql_dbg(ql_dbg_async, vha, 0x5001, - "MBX pointer ERROR.\n"); - } + if (!ha->mcp) + ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n"); } static void @@ -453,7 +448,7 @@ skip_rio: break; case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ - ql_log(ql_log_info, vha, 0x5009, + ql_dbg(ql_dbg_async, vha, 0x5009, "LIP occurred (%x).\n", mb[1]); if (atomic_read(&vha->loop_state) != LOOP_DOWN) { @@ -487,7 +482,7 @@ skip_rio: ha->link_data_rate = mb[1]; } - ql_log(ql_log_info, vha, 0x500a, + ql_dbg(ql_dbg_async, vha, 0x500a, "LOOP UP detected (%s Gbps).\n", link_speed); vha->flags.management_server_logged_in = 0; @@ -497,7 +492,7 @@ skip_rio: case MBA_LOOP_DOWN: /* Loop Down Event */ mbx = IS_QLA81XX(ha) ? RD_REG_WORD(®24->mailbox4) : 0; mbx = IS_QLA82XX(ha) ? RD_REG_WORD(®82->mailbox_out[4]) : mbx; - ql_log(ql_log_info, vha, 0x500b, + ql_dbg(ql_dbg_async, vha, 0x500b, "LOOP DOWN detected (%x %x %x %x).\n", mb[1], mb[2], mb[3], mbx); @@ -519,7 +514,7 @@ skip_rio: break; case MBA_LIP_RESET: /* LIP reset occurred */ - ql_log(ql_log_info, vha, 0x500c, + ql_dbg(ql_dbg_async, vha, 0x500c, "LIP reset occurred (%x).\n", mb[1]); if (atomic_read(&vha->loop_state) != LOOP_DOWN) { @@ -587,7 +582,7 @@ skip_rio: if (IS_QLA2100(ha)) break; - ql_log(ql_log_info, vha, 0x500f, + ql_dbg(ql_dbg_async, vha, 0x500f, "Configuration change detected: value=%x.\n", mb[1]); if (atomic_read(&vha->loop_state) != LOOP_DOWN) { @@ -920,15 +915,15 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, QLA_LOGIO_LOGIN_RETRIED : 0; if (mbx->entry_status) { ql_dbg(ql_dbg_async, vha, 0x5043, - "Async-%s error entry - portid=%02x%02x%02x " + "Async-%s error entry - hdl=%x portid=%02x%02x%02x " "entry-status=%x status=%x state-flag=%x " - "status-flags=%x.\n", - type, fcport->d_id.b.domain, fcport->d_id.b.area, + "status-flags=%x.\n", type, sp->handle, + fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, mbx->entry_status, le16_to_cpu(mbx->status), le16_to_cpu(mbx->state_flags), le16_to_cpu(mbx->status_flags)); - ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5057, + ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5029, (uint8_t *)mbx, sizeof(*mbx)); goto logio_done; @@ -940,9 +935,10 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, status = 0; if (!status && le16_to_cpu(mbx->mb0) == MBS_COMMAND_COMPLETE) { ql_dbg(ql_dbg_async, vha, 0x5045, - "Async-%s complete - portid=%02x%02x%02x mbx1=%x.\n", - type, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa, le16_to_cpu(mbx->mb1)); + "Async-%s complete - hdl=%x portid=%02x%02x%02x mbx1=%x.\n", + type, sp->handle, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa, + le16_to_cpu(mbx->mb1)); data[0] = MBS_COMMAND_COMPLETE; if (ctx->type == SRB_LOGIN_CMD) { @@ -968,11 +964,10 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, } ql_log(ql_log_warn, vha, 0x5046, - "Async-%s failed - portid=%02x%02x%02x status=%x " - "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", - type, fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa, status, - le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1), + "Async-%s failed - hdl=%x portid=%02x%02x%02x status=%x " + "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", type, sp->handle, + fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, + status, le16_to_cpu(mbx->mb0), le16_to_cpu(mbx->mb1), le16_to_cpu(mbx->mb2), le16_to_cpu(mbx->mb6), le16_to_cpu(mbx->mb7)); @@ -1036,7 +1031,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, bsg_job->reply->result = DID_ERROR << 16; bsg_job->reply->reply_payload_rcv_len = 0; } - ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5058, + ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035, (uint8_t *)pkt, sizeof(*pkt)); } else { bsg_job->reply->result = DID_OK << 16; @@ -1111,9 +1106,9 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count); ql_log(ql_log_info, vha, 0x503f, - "ELS-CT pass-through-%s error comp_status-status=0x%x " + "ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x " "error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n", - type, comp_status, fw_status[1], fw_status[2], + type, sp->handle, comp_status, fw_status[1], fw_status[2], le16_to_cpu(((struct els_sts_entry_24xx *) pkt)->total_byte_count)); fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); @@ -1121,9 +1116,9 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, } else { ql_log(ql_log_info, vha, 0x5040, - "ELS-CT pass-through-%s error comp_status-status=0x%x " + "ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x " "error subcode 1=0x%x error subcode 2=0x%x.\n", - type, comp_status, + type, sp->handle, comp_status, le16_to_cpu(((struct els_sts_entry_24xx *) pkt)->error_subcode_1), le16_to_cpu(((struct els_sts_entry_24xx *) @@ -1184,11 +1179,12 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, QLA_LOGIO_LOGIN_RETRIED : 0; if (logio->entry_status) { ql_log(ql_log_warn, vha, 0x5034, - "Async-%s error entry - " + "Async-%s error entry - hdl=%x" "portid=%02x%02x%02x entry-status=%x.\n", - type, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa, logio->entry_status); - ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5059, + type, sp->handle, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa, + logio->entry_status); + ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d, (uint8_t *)logio, sizeof(*logio)); goto logio_done; @@ -1196,10 +1192,9 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) { ql_dbg(ql_dbg_async, vha, 0x5036, - "Async-%s complete - portid=%02x%02x%02x " - "iop0=%x.\n", - type, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa, + "Async-%s complete - hdl=%x portid=%02x%02x%02x " + "iop0=%x.\n", type, sp->handle, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa, le32_to_cpu(logio->io_parameter[0])); data[0] = MBS_COMMAND_COMPLETE; @@ -1238,9 +1233,8 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, } ql_dbg(ql_dbg_async, vha, 0x5037, - "Async-%s failed - portid=%02x%02x%02x comp=%x " - "iop0=%x iop1=%x.\n", - type, fcport->d_id.b.domain, + "Async-%s failed - hdl=%x portid=%02x%02x%02x comp=%x " + "iop0=%x iop1=%x.\n", type, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, le16_to_cpu(logio->comp_status), le32_to_cpu(logio->io_parameter[0]), @@ -1274,25 +1268,25 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, if (sts->entry_status) { ql_log(ql_log_warn, vha, 0x5038, - "Async-%s error - entry-status(%x).\n", - type, sts->entry_status); + "Async-%s error - hdl=%x entry-status(%x).\n", + type, sp->handle, sts->entry_status); } else if (sts->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { ql_log(ql_log_warn, vha, 0x5039, - "Async-%s error - completion status(%x).\n", - type, sts->comp_status); + "Async-%s error - hdl=%x completion status(%x).\n", + type, sp->handle, sts->comp_status); } else if (!(le16_to_cpu(sts->scsi_status) & SS_RESPONSE_INFO_LEN_VALID)) { ql_log(ql_log_warn, vha, 0x503a, - "Async-%s error - no response info(%x).\n", - type, sts->scsi_status); + "Async-%s error - hdl=%x no response info(%x).\n", + type, sp->handle, sts->scsi_status); } else if (le32_to_cpu(sts->rsp_data_len) < 4) { ql_log(ql_log_warn, vha, 0x503b, - "Async-%s error - not enough response(%d).\n", - type, sts->rsp_data_len); + "Async-%s error - hdl=%x not enough response(%d).\n", + type, sp->handle, sts->rsp_data_len); } else if (sts->data[3]) { ql_log(ql_log_warn, vha, 0x503c, - "Async-%s error - response(%x).\n", - type, sts->data[3]); + "Async-%s error - hdl=%x response(%x).\n", + type, sp->handle, sts->data[3]); } else { error = 0; } @@ -1337,9 +1331,6 @@ qla2x00_process_response_queue(struct rsp_que *rsp) } if (pkt->entry_status != 0) { - ql_log(ql_log_warn, vha, 0x5035, - "Process error entry.\n"); - qla2x00_error_entry(vha, rsp, pkt); ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); @@ -1391,7 +1382,6 @@ qla2x00_process_response_queue(struct rsp_que *rsp) } static inline void - qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, uint32_t sense_len, struct rsp_que *rsp) { @@ -1413,13 +1403,14 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, if (sp->request_sense_length != 0) rsp->status_srb = sp; - ql_dbg(ql_dbg_io, vha, 0x301c, - "Check condition Sense data, scsi(%ld:%d:%d:%d) cmd=%p.\n", - sp->fcport->vha->host_no, cp->device->channel, cp->device->id, - cp->device->lun, cp); - if (sense_len) + if (sense_len) { + ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x301c, + "Check condition Sense data, nexus%ld:%d:%d cmd=%p.\n", + sp->fcport->vha->host_no, cp->device->id, cp->device->lun, + cp); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b, cp->sense_buffer, sense_len); + } } struct scsi_dif_tuple { @@ -1506,7 +1497,7 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) } if (k != blocks_done) { - qla_printk(KERN_WARNING, sp->fcport->vha->hw, + ql_log(ql_log_warn, vha, 0x302f, "unexpected tag values tag:lba=%x:%llx)\n", e_ref_tag, (unsigned long long)lba_s); return 1; @@ -1611,7 +1602,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) sp = NULL; if (sp == NULL) { - ql_log(ql_log_warn, vha, 0x3017, + ql_dbg(ql_dbg_io, vha, 0x3017, "Invalid status handle (0x%x).\n", sts->handle); if (IS_QLA82XX(ha)) @@ -1623,7 +1614,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) } cp = sp->cmd; if (cp == NULL) { - ql_log(ql_log_warn, vha, 0x3018, + ql_dbg(ql_dbg_io, vha, 0x3018, "Command already returned (0x%x/%p).\n", sts->handle, sp); @@ -1670,7 +1661,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) par_sense_len -= rsp_info_len; } if (rsp_info_len > 3 && rsp_info[3]) { - ql_log(ql_log_warn, vha, 0x3019, + ql_dbg(ql_dbg_io, vha, 0x3019, "FCP I/O protocol failure (0x%x/0x%x).\n", rsp_info_len, rsp_info[3]); @@ -1701,7 +1692,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) if (!lscsi_status && ((unsigned)(scsi_bufflen(cp) - resid) < cp->underflow)) { - ql_log(ql_log_warn, vha, 0x301a, + ql_dbg(ql_dbg_io, vha, 0x301a, "Mid-layer underflow " "detected (0x%x of 0x%x bytes).\n", resid, scsi_bufflen(cp)); @@ -1713,7 +1704,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) cp->result = DID_OK << 16 | lscsi_status; if (lscsi_status == SAM_STAT_TASK_SET_FULL) { - ql_log(ql_log_warn, vha, 0x301b, + ql_dbg(ql_dbg_io, vha, 0x301b, "QUEUE FULL detected.\n"); break; } @@ -1735,7 +1726,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) scsi_set_resid(cp, resid); if (scsi_status & SS_RESIDUAL_UNDER) { if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) { - ql_log(ql_log_warn, vha, 0x301d, + ql_dbg(ql_dbg_io, vha, 0x301d, "Dropped frame(s) detected " "(0x%x of 0x%x bytes).\n", resid, scsi_bufflen(cp)); @@ -1747,7 +1738,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) if (!lscsi_status && ((unsigned)(scsi_bufflen(cp) - resid) < cp->underflow)) { - ql_log(ql_log_warn, vha, 0x301e, + ql_dbg(ql_dbg_io, vha, 0x301e, "Mid-layer underflow " "detected (0x%x of 0x%x bytes).\n", resid, scsi_bufflen(cp)); @@ -1756,7 +1747,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) break; } } else { - ql_log(ql_log_warn, vha, 0x301f, + ql_dbg(ql_dbg_io, vha, 0x301f, "Dropped frame(s) detected (0x%x " "of 0x%x bytes).\n", resid, scsi_bufflen(cp)); @@ -1774,7 +1765,7 @@ check_scsi_status: */ if (lscsi_status != 0) { if (lscsi_status == SAM_STAT_TASK_SET_FULL) { - ql_log(ql_log_warn, vha, 0x3020, + ql_dbg(ql_dbg_io, vha, 0x3020, "QUEUE FULL detected.\n"); logit = 1; break; @@ -1838,10 +1829,15 @@ out: if (logit) ql_dbg(ql_dbg_io, vha, 0x3022, "FCP command status: 0x%x-0x%x (0x%x) " - "oxid=0x%x cdb=%02x%02x%02x len=0x%x " + "nexus=%ld:%d:%d portid=%02x%02x%02x oxid=0x%x " + "cdb=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x len=0x%x " "rsp_info=0x%x resid=0x%x fw_resid=0x%x.\n", - comp_status, scsi_status, cp->result, ox_id, cp->cmnd[0], - cp->cmnd[1], cp->cmnd[2], scsi_bufflen(cp), rsp_info_len, + comp_status, scsi_status, cp->result, vha->host_no, + cp->device->id, cp->device->lun, fcport->d_id.b.domain, + fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id, + cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3], + cp->cmnd[4], cp->cmnd[5], cp->cmnd[6], cp->cmnd[7], + cp->cmnd[8], cp->cmnd[9], scsi_bufflen(cp), rsp_info_len, resid_len, fw_resid_len); if (rsp->status_srb == NULL) @@ -1991,13 +1987,8 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) wptr++; } - if (ha->mcp) { - ql_dbg(ql_dbg_async, vha, 0x504d, - "Got mailbox completion. cmd=%x.\n", ha->mcp->mb[0]); - } else { - ql_dbg(ql_dbg_async, vha, 0x504e, - "MBX pointer ERROR.\n"); - } + if (!ha->mcp) + ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERRROR.\n"); } /** @@ -2025,9 +2016,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, } if (pkt->entry_status != 0) { - ql_dbg(ql_dbg_async, vha, 0x5029, - "Process error entry.\n"); - qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt); ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 360b9cb7153f..b37c5599674b 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2023,13 +2023,9 @@ qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) wptr++; } - if (ha->mcp) { - ql_dbg(ql_dbg_async, vha, 0x5052, - "Got mailbox completion. cmd=%x.\n", ha->mcp->mb[0]); - } else { + if (!ha->mcp) ql_dbg(ql_dbg_async, vha, 0x5053, "MBX pointer ERROR.\n"); - } } /* diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 8b4214502e45..ae1699f6854d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -83,6 +83,9 @@ MODULE_PARM_DESC(ql2xextended_error_logging, "\t\t0x00080000 - P3P Specific. 0x00040000 - Virtual Port.\n" "\t\t0x00020000 - Buffer Dump. 0x00010000 - Misc.\n" "\t\t0x7fffffff - For enabling all logs, can be too many logs.\n" + "\t\t0x1e400000 - Preferred value for capturing essential " + "debug information (equivalent to old " + "ql2xextended_error_logging=1).\n" "\t\tDo LOGICAL OR of the value to enable more than one level"); int ql2xshiftctondsd = 6; @@ -847,14 +850,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) int wait = 0; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_taskm, vha, 0x8000, - "Entered %s for cmd=%p.\n", __func__, cmd); if (!CMD_SP(cmd)) return SUCCESS; ret = fc_block_scsi_eh(cmd); - ql_dbg(ql_dbg_taskm, vha, 0x8001, - "Return value of fc_block_scsi_eh=%d.\n", ret); if (ret != 0) return ret; ret = SUCCESS; @@ -870,7 +869,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } ql_dbg(ql_dbg_taskm, vha, 0x8002, - "Aborting sp=%p cmd=%p from RISC ", sp, cmd); + "Aborting from RISC nexus=%ld:%d:%d sp=%p cmd=%p\n", + vha->host_no, id, lun, sp, cmd); /* Get a reference to the sp and drop the lock.*/ sp_get(sp); @@ -878,10 +878,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) spin_unlock_irqrestore(&ha->hardware_lock, flags); if (ha->isp_ops->abort_command(sp)) { ql_dbg(ql_dbg_taskm, vha, 0x8003, - "Abort command mbx failed for cmd=%p.\n", cmd); + "Abort command mbx failed cmd=%p.\n", cmd); } else { ql_dbg(ql_dbg_taskm, vha, 0x8004, - "Abort command mbx success.\n"); + "Abort command mbx success cmd=%p.\n", cmd); wait = 1; } @@ -897,13 +897,14 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) if (wait) { if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x8006, - "Abort handler timed out for cmd=%p.\n", cmd); + "Abort handler timed out cmd=%p.\n", cmd); ret = FAILED; } } ql_log(ql_log_info, vha, 0x801c, - "Abort command issued -- %d %x.\n", wait, ret); + "Abort command issued nexus=%ld:%d:%d -- %d %x.\n", + vha->host_no, id, lun, wait, ret); return ret; } @@ -972,19 +973,15 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, int err; if (!fcport) { - ql_log(ql_log_warn, vha, 0x8007, - "fcport is NULL.\n"); return FAILED; } err = fc_block_scsi_eh(cmd); - ql_dbg(ql_dbg_taskm, vha, 0x8008, - "fc_block_scsi_eh ret=%d.\n", err); if (err != 0) return err; ql_log(ql_log_info, vha, 0x8009, - "%s RESET ISSUED for id %d lun %d cmd=%p.\n", name, + "%s RESET ISSUED nexus=%ld:%d:%d cmd=%p.\n", name, vha->host_no, cmd->device->id, cmd->device->lun, cmd); err = 0; @@ -1009,15 +1006,16 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, } ql_log(ql_log_info, vha, 0x800e, - "%s RESET SUCCEEDED for id %d lun %d cmd=%p.\n", name, - cmd->device->id, cmd->device->lun, cmd); + "%s RESET SUCCEEDED nexus:%ld:%d:%d cmd=%p.\n", name, + vha->host_no, cmd->device->id, cmd->device->lun, cmd); return SUCCESS; eh_reset_failed: ql_log(ql_log_info, vha, 0x800f, - "%s RESET FAILED: %s for id %d lun %d cmd=%p.\n", name, - reset_errors[err], cmd->device->id, cmd->device->lun, cmd); + "%s RESET FAILED: %s nexus=%ld:%d:%d cmd=%p.\n", name, + reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun, + cmd); return FAILED; } @@ -1068,20 +1066,16 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) lun = cmd->device->lun; if (!fcport) { - ql_log(ql_log_warn, vha, 0x8010, - "fcport is NULL.\n"); return ret; } ret = fc_block_scsi_eh(cmd); - ql_dbg(ql_dbg_taskm, vha, 0x8011, - "fc_block_scsi_eh ret=%d.\n", ret); if (ret != 0) return ret; ret = FAILED; ql_log(ql_log_info, vha, 0x8012, - "BUS RESET ISSUED for id %d lun %d.\n", id, lun); + "BUS RESET ISSUED nexus=%ld:%d%d.\n", vha->host_no, id, lun); if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { ql_log(ql_log_fatal, vha, 0x8013, @@ -1105,7 +1099,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) eh_bus_reset_done: ql_log(ql_log_warn, vha, 0x802b, - "BUS RESET %s.\n", (ret == FAILED) ? "FAILED" : "SUCCEDED"); + "BUS RESET %s nexus=%ld:%d:%d.\n", + (ret == FAILED) ? "FAILED" : "SUCCEDED", vha->host_no, id, lun); return ret; } @@ -1139,20 +1134,16 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) lun = cmd->device->lun; if (!fcport) { - ql_log(ql_log_warn, vha, 0x8016, - "fcport is NULL.\n"); return ret; } ret = fc_block_scsi_eh(cmd); - ql_dbg(ql_dbg_taskm, vha, 0x8017, - "fc_block_scsi_eh ret=%d.\n", ret); if (ret != 0) return ret; ret = FAILED; ql_log(ql_log_info, vha, 0x8018, - "ADAPTER RESET ISSUED for id %d lun %d.\n", id, lun); + "ADAPTER RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun); if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS) goto eh_host_reset_lock; @@ -1193,8 +1184,9 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) ret = SUCCESS; eh_host_reset_lock: - qla_printk(KERN_INFO, ha, "%s: reset %s.\n", __func__, - (ret == FAILED) ? "failed" : "succeeded"); + ql_log(ql_log_info, vha, 0x8017, + "ADAPTER RESET %s nexus=%ld:%d:%d.\n", + (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun); return ret; } @@ -1344,10 +1336,8 @@ static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth) return; ql_dbg(ql_dbg_io, fcport->vha, 0x3029, - "Queue depth adjusted-down " - "to %d for scsi(%ld:%d:%d:%d).\n", - sdev->queue_depth, fcport->vha->host_no, - sdev->channel, sdev->id, sdev->lun); + "Queue depth adjusted-down to %d for nexus=%ld:%d:%d.\n", + sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun); } static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth) @@ -1369,10 +1359,8 @@ static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth) scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth); ql_dbg(ql_dbg_io, vha, 0x302a, - "Queue depth adjusted-up to %d for " - "scsi(%ld:%d:%d:%d).\n", - sdev->queue_depth, fcport->vha->host_no, - sdev->channel, sdev->id, sdev->lun); + "Queue depth adjusted-up to %d for nexus=%ld:%d:%d.\n", + sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun); } static int @@ -2382,9 +2370,6 @@ skip_dpc: qla2x00_dfs_setup(base_vha); - ql_log(ql_log_info, base_vha, 0x00fa, - "QLogic Fibre Channed HBA Driver: %s.\n", - qla2x00_version_str); ql_log(ql_log_info, base_vha, 0x00fb, "QLogic %s - %s.\n", ha->model_number, ha->model_desc ? ha->model_desc : ""); -- cgit From c4631191c44de9567ac5376e6a7f4a244c2283bc Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:03:08 -0800 Subject: [SCSI] qla2xxx: Proper cleanup of pass through commands when firmware returns error. [jejb: fixed up checkpatch and casting errors] Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 73 ++++++++++++++++++++++++++++++------------ drivers/scsi/qla2xxx/qla_os.c | 19 ++++++----- 2 files changed, 61 insertions(+), 31 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index b6023e9636ea..6426c7ed9ccc 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1895,6 +1895,45 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) } } +static int +qla2x00_free_sp_ctx(scsi_qla_host_t *vha, srb_t *sp) +{ + struct qla_hw_data *ha = vha->hw; + struct srb_ctx *ctx; + + if (!sp->ctx) + return 1; + + ctx = sp->ctx; + + if (ctx->type == SRB_LOGIN_CMD || + ctx->type == SRB_LOGOUT_CMD || + ctx->type == SRB_TM_CMD) { + ctx->u.iocb_cmd->done(sp); + return 0; + } else if (ctx->type == SRB_ADISC_CMD) { + ctx->u.iocb_cmd->free(sp); + return 0; + } else { + struct fc_bsg_job *bsg_job; + + bsg_job = ctx->u.bsg_job; + if (ctx->type == SRB_ELS_CMD_HST || + ctx->type == SRB_CT_CMD) + kfree(sp->fcport); + + bsg_job->reply->reply_data.ctels_reply.status = + FC_CTELS_STATUS_OK; + bsg_job->reply->result = DID_ERROR << 16; + bsg_job->reply->reply_payload_rcv_len = 0; + kfree(sp->ctx); + mempool_free(sp, ha->srb_mempool); + bsg_job->job_done(bsg_job); + return 0; + } + return 1; +} + /** * qla2x00_error_entry() - Process an error entry. * @ha: SCSI driver HA context @@ -1905,7 +1944,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) { srb_t *sp; struct qla_hw_data *ha = vha->hw; - uint32_t handle = LSW(pkt->handle); + const char func[] = "ERROR-IOCB"; uint16_t que = MSW(pkt->handle); struct req_que *req = ha->req_q_map[que]; @@ -1928,28 +1967,20 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) ql_dbg(ql_dbg_async, vha, 0x502f, "UNKNOWN flag error.\n"); - /* Validate handle. */ - if (handle < MAX_OUTSTANDING_COMMANDS) - sp = req->outstanding_cmds[handle]; - else - sp = NULL; - + sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); if (sp) { - /* Free outstanding command slot. */ - req->outstanding_cmds[handle] = NULL; - - /* Bad payload or header */ - if (pkt->entry_status & - (RF_INV_E_ORDER | RF_INV_E_COUNT | - RF_INV_E_PARAM | RF_INV_E_TYPE)) { - sp->cmd->result = DID_ERROR << 16; - } else if (pkt->entry_status & RF_BUSY) { - sp->cmd->result = DID_BUS_BUSY << 16; - } else { - sp->cmd->result = DID_ERROR << 16; + if (qla2x00_free_sp_ctx(vha, sp)) { + if (pkt->entry_status & + (RF_INV_E_ORDER | RF_INV_E_COUNT | + RF_INV_E_PARAM | RF_INV_E_TYPE)) { + sp->cmd->result = DID_ERROR << 16; + } else if (pkt->entry_status & RF_BUSY) { + sp->cmd->result = DID_BUS_BUSY << 16; + } else { + sp->cmd->result = DID_ERROR << 16; + } + qla2x00_sp_compl(ha, sp); } - qla2x00_sp_compl(ha, sp); - } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type == COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7 || pkt->entry_type == COMMAND_TYPE_6) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ae1699f6854d..c9a74521b402 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3690,16 +3690,6 @@ qla2x00_sp_free_dma(srb_t *sp) sp->flags &= ~SRB_CRC_CTX_DMA_VALID; } - CMD_SP(cmd) = NULL; -} - -static void -qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp) -{ - struct scsi_cmnd *cmd = sp->cmd; - - qla2x00_sp_free_dma(sp); - if (sp->flags & SRB_FCP_CMND_DMA_VALID) { struct ct6_dsd *ctx = sp->ctx; dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, @@ -3711,6 +3701,15 @@ qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp) sp->ctx = NULL; } + CMD_SP(cmd) = NULL; +} + +static void +qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp) +{ + struct scsi_cmnd *cmd = sp->cmd; + + qla2x00_sp_free_dma(sp); mempool_free(sp, ha->srb_mempool); cmd->scsi_done(cmd); } -- cgit From 4fa94f83ff12979cb7396908ddc8ad13430649ed Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 18 Nov 2011 09:03:09 -0800 Subject: [SCSI] qla2xxx: Only read requested mailbox registers. When reading the incoming mailbox registers, read only the specified ones. Signed-off-by: Andrew Vasquez Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6426c7ed9ccc..e804585cc59c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -242,28 +242,35 @@ static void qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) { uint16_t cnt; + uint32_t mboxes; uint16_t __iomem *wptr; struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + /* Read all mbox registers? */ + mboxes = (1 << ha->mbx_count) - 1; + if (!ha->mcp) + ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERRROR.\n"); + else + mboxes = ha->mcp->in_mb; + /* Load return mailbox registers. */ ha->flags.mbox_int = 1; ha->mailbox_out[0] = mb0; + mboxes >>= 1; wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1); for (cnt = 1; cnt < ha->mbx_count; cnt++) { if (IS_QLA2200(ha) && cnt == 8) wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8); - if (cnt == 4 || cnt == 5) + if ((cnt == 4 || cnt == 5) && (mboxes & BIT_0)) ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr); - else + else if (mboxes & BIT_0) ha->mailbox_out[cnt] = RD_REG_WORD(wptr); wptr++; + mboxes >>= 1; } - - if (!ha->mcp) - ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n"); } static void @@ -2004,22 +2011,31 @@ static void qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) { uint16_t cnt; + uint32_t mboxes; uint16_t __iomem *wptr; struct qla_hw_data *ha = vha->hw; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + /* Read all mbox registers? */ + mboxes = (1 << ha->mbx_count) - 1; + if (!ha->mcp) + ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERRROR.\n"); + else + mboxes = ha->mcp->in_mb; + /* Load return mailbox registers. */ ha->flags.mbox_int = 1; ha->mailbox_out[0] = mb0; + mboxes >>= 1; wptr = (uint16_t __iomem *)®->mailbox1; for (cnt = 1; cnt < ha->mbx_count; cnt++) { - ha->mailbox_out[cnt] = RD_REG_WORD(wptr); + if (mboxes & BIT_0) + ha->mailbox_out[cnt] = RD_REG_WORD(wptr); + + mboxes >>= 1; wptr++; } - - if (!ha->mcp) - ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERRROR.\n"); } /** -- cgit From c142caf0ab21fb57240b09138a95def1ca20ca0f Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 18 Nov 2011 09:03:10 -0800 Subject: [SCSI] qla2xxx: Limit excessive DPC cycles. The 'continue' cases neglected to place the thread in an interruptible state, causing the DPC routine to wake immediately. Signed-off-by: Andrew Vasquez Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c9a74521b402..51c465542092 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3445,27 +3445,21 @@ qla2x00_do_dpc(void *data) schedule(); __set_current_state(TASK_RUNNING); - ql_dbg(ql_dbg_dpc, base_vha, 0x4001, - "DPC handler waking up.\n"); - ql_dbg(ql_dbg_dpc, base_vha, 0x4002, - "dpc_flags=0x%lx.\n", base_vha->dpc_flags); - - /* Initialization not yet finished. Don't do anything yet. */ - if (!base_vha->flags.init_done) - continue; + if (!base_vha->flags.init_done || ha->flags.mbox_busy) + goto end_loop; if (ha->flags.eeh_busy) { ql_dbg(ql_dbg_dpc, base_vha, 0x4003, "eeh_busy=%d.\n", ha->flags.eeh_busy); - continue; + goto end_loop; } ha->dpc_active = 1; - if (ha->flags.mbox_busy) { - ha->dpc_active = 0; - continue; - } + ql_dbg(ql_dbg_dpc, base_vha, 0x4001, + "DPC handler waking up.\n"); + ql_dbg(ql_dbg_dpc, base_vha, 0x4002, + "dpc_flags=0x%lx.\n", base_vha->dpc_flags); qla2x00_do_work(base_vha); @@ -3607,6 +3601,7 @@ qla2x00_do_dpc(void *data) qla2x00_do_dpc_all_vps(base_vha); ha->dpc_active = 0; +end_loop: set_current_state(TASK_INTERRUPTIBLE); } /* End of while(1) */ __set_current_state(TASK_RUNNING); -- cgit From 3cb0a67d6d0f5af55ab9673893cd8e8148025331 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:03:11 -0800 Subject: [SCSI] qla2xxx: Fix to include FCE data as part of dump. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 58e0bfbfcd33..dc454628f0a1 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -369,7 +369,7 @@ qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) memcpy(iter_reg, ha->fce, ntohl(fcec->size)); - return iter_reg; + return (char *)iter_reg + ntohl(fcec->size); } static inline void * -- cgit From 882a917bfc638c8eac58677b9bf0c18663222078 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:03:12 -0800 Subject: [SCSI] qla2xxx: Correct report-id acquisition check Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 82a33533ed26..34344d3f8658 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2887,7 +2887,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, if (vp_idx == 0 && (MSB(stat) != 1)) goto reg_needed; - if (MSB(stat) == 1) { + if (MSB(stat) != 0) { ql_dbg(ql_dbg_mbx, vha, 0x10ba, "Could not acquire ID for VP[%d].\n", vp_idx); return; -- cgit From 71dfe9e776878d9583d004edade55edc2bdac5eb Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Fri, 18 Nov 2011 09:03:13 -0800 Subject: [SCSI] qla2xxx: Corrections to returned sysfs error codes. Correct the erroneous return codes introduced by the following patch: "Return sysfs error codes appropriate to conditions". Signed-off-by: Joe Carnuccio Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index efab503fc866..a2f1b3043dfb 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -107,7 +107,7 @@ qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj, set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); break; } - return -EINVAL; + return count; } static struct bin_attribute sysfs_fw_dump_attr = { @@ -387,7 +387,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, break; case 3: if (ha->optrom_state != QLA_SWRITING) - return -ENOMEM; + return -EINVAL; if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x7068, -- cgit From 6e96fa7b8bd8de5a9641aa100af960903244a6e6 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:03:14 -0800 Subject: [SCSI] qla2xxx: Corrected the default setting of the help text of Minidump capture mask. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 51c465542092..b3028f546848 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -202,7 +202,7 @@ int ql2xmdcapmask = 0x1F; module_param(ql2xmdcapmask, int, S_IRUGO); MODULE_PARM_DESC(ql2xmdcapmask, "Set the Minidump driver capture mask level. " - "Default is 0x7F - Can be set to 0x3, 0x7, 0xF, 0x1F, 0x7F."); + "Default is 0x1F - Can be set to 0x3, 0x7, 0xF, 0x1F, 0x7F."); int ql2xmdenable = 1; module_param(ql2xmdenable, int, S_IRUGO); -- cgit From 2e26426917ae5b093d355abe1fc1a7b89492f0e6 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:03:15 -0800 Subject: [SCSI] qla2xxx: Corrected the display of firmware dump availability for ISP82xx. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index b37c5599674b..805b4b734754 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3655,10 +3655,10 @@ qla82xx_check_md_needed(scsi_qla_host_t *vha) qla82xx_md_free(vha); /* ALlocate MiniDump resources */ qla82xx_md_prep(vha); - } else - ql_log(ql_log_info, vha, 0xb02e, - "Firmware dump available to retrieve\n"); - } + } + } else + ql_log(ql_log_info, vha, 0xb02e, + "Firmware dump available to retrieve\n"); } return rval; } -- cgit From 706f457d000c8f334a1af37508d946a561d5929a Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:03:16 -0800 Subject: [SCSI] qla2xxx: Added a new entry to ISP specific function pointers structure. Add a new function to ISP specific pointers structure to take care of ISP specific PCI IO space configuration. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_os.c | 256 +++++++++++++++++++++-------------------- 2 files changed, 133 insertions(+), 124 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 964e2886311b..d046db1a2ded 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2244,6 +2244,7 @@ struct isp_operations { int (*get_flash_version) (struct scsi_qla_host *, void *); int (*start_scsi) (srb_t *); int (*abort_isp) (struct scsi_qla_host *); + int (*iospace_config)(struct qla_hw_data*); }; /* MSI-X Support *************************************************************/ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b3028f546848..d713bc387790 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1484,6 +1484,118 @@ qla24xx_disable_intrs(struct qla_hw_data *ha) spin_unlock_irqrestore(&ha->hardware_lock, flags); } +static int +qla2x00_iospace_config(struct qla_hw_data *ha) +{ + resource_size_t pio; + uint16_t msix; + int cpus; + + if (IS_QLA82XX(ha)) + return qla82xx_iospace_config(ha); + + if (pci_request_selected_regions(ha->pdev, ha->bars, + QLA2XXX_DRIVER_NAME)) { + ql_log_pci(ql_log_fatal, ha->pdev, 0x0011, + "Failed to reserve PIO/MMIO regions (%s), aborting.\n", + pci_name(ha->pdev)); + goto iospace_error_exit; + } + if (!(ha->bars & 1)) + goto skip_pio; + + /* We only need PIO for Flash operations on ISP2312 v2 chips. */ + pio = pci_resource_start(ha->pdev, 0); + if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) { + if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) { + ql_log_pci(ql_log_warn, ha->pdev, 0x0012, + "Invalid pci I/O region size (%s).\n", + pci_name(ha->pdev)); + pio = 0; + } + } else { + ql_log_pci(ql_log_warn, ha->pdev, 0x0013, + "Region #0 no a PIO resource (%s).\n", + pci_name(ha->pdev)); + pio = 0; + } + ha->pio_address = pio; + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0014, + "PIO address=%llu.\n", + (unsigned long long)ha->pio_address); + +skip_pio: + /* Use MMIO operations for all accesses. */ + if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) { + ql_log_pci(ql_log_fatal, ha->pdev, 0x0015, + "Region #1 not an MMIO resource (%s), aborting.\n", + pci_name(ha->pdev)); + goto iospace_error_exit; + } + if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) { + ql_log_pci(ql_log_fatal, ha->pdev, 0x0016, + "Invalid PCI mem region size (%s), aborting.\n", + pci_name(ha->pdev)); + goto iospace_error_exit; + } + + ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN); + if (!ha->iobase) { + ql_log_pci(ql_log_fatal, ha->pdev, 0x0017, + "Cannot remap MMIO (%s), aborting.\n", + pci_name(ha->pdev)); + goto iospace_error_exit; + } + + /* Determine queue resources */ + ha->max_req_queues = ha->max_rsp_queues = 1; + if ((ql2xmaxqueues <= 1 && !ql2xmultique_tag) || + (ql2xmaxqueues > 1 && ql2xmultique_tag) || + (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))) + goto mqiobase_exit; + + ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), + pci_resource_len(ha->pdev, 3)); + if (ha->mqiobase) { + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0018, + "MQIO Base=%p.\n", ha->mqiobase); + /* Read MSIX vector size of the board */ + pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix); + ha->msix_count = msix; + /* Max queues are bounded by available msix vectors */ + /* queue 0 uses two msix vectors */ + if (ql2xmultique_tag) { + cpus = num_online_cpus(); + ha->max_rsp_queues = (ha->msix_count - 1 > cpus) ? + (cpus + 1) : (ha->msix_count - 1); + ha->max_req_queues = 2; + } else if (ql2xmaxqueues > 1) { + ha->max_req_queues = ql2xmaxqueues > QLA_MQ_SIZE ? + QLA_MQ_SIZE : ql2xmaxqueues; + ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc008, + "QoS mode set, max no of request queues:%d.\n", + ha->max_req_queues); + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0019, + "QoS mode set, max no of request queues:%d.\n", + ha->max_req_queues); + } + ql_log_pci(ql_log_info, ha->pdev, 0x001a, + "MSI-X vector count: %d.\n", msix); + } else + ql_log_pci(ql_log_info, ha->pdev, 0x001b, + "BAR 3 not enabled.\n"); + +mqiobase_exit: + ha->msix_count = ha->max_rsp_queues + 1; + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x001c, + "MSIX Count:%d.\n", ha->msix_count); + return (0); + +iospace_error_exit: + return (-ENOMEM); +} + + static struct isp_operations qla2100_isp_ops = { .pci_config = qla2100_pci_config, .reset_chip = qla2x00_reset_chip, @@ -1518,6 +1630,7 @@ static struct isp_operations qla2100_isp_ops = { .get_flash_version = qla2x00_get_flash_version, .start_scsi = qla2x00_start_scsi, .abort_isp = qla2x00_abort_isp, + .iospace_config = qla2x00_iospace_config, }; static struct isp_operations qla2300_isp_ops = { @@ -1554,6 +1667,7 @@ static struct isp_operations qla2300_isp_ops = { .get_flash_version = qla2x00_get_flash_version, .start_scsi = qla2x00_start_scsi, .abort_isp = qla2x00_abort_isp, + .iospace_config = qla2x00_iospace_config, }; static struct isp_operations qla24xx_isp_ops = { @@ -1590,6 +1704,7 @@ static struct isp_operations qla24xx_isp_ops = { .get_flash_version = qla24xx_get_flash_version, .start_scsi = qla24xx_start_scsi, .abort_isp = qla2x00_abort_isp, + .iospace_config = qla2x00_iospace_config, }; static struct isp_operations qla25xx_isp_ops = { @@ -1626,6 +1741,7 @@ static struct isp_operations qla25xx_isp_ops = { .get_flash_version = qla24xx_get_flash_version, .start_scsi = qla24xx_dif_start_scsi, .abort_isp = qla2x00_abort_isp, + .iospace_config = qla2x00_iospace_config, }; static struct isp_operations qla81xx_isp_ops = { @@ -1662,6 +1778,7 @@ static struct isp_operations qla81xx_isp_ops = { .get_flash_version = qla24xx_get_flash_version, .start_scsi = qla24xx_dif_start_scsi, .abort_isp = qla2x00_abort_isp, + .iospace_config = qla2x00_iospace_config, }; static struct isp_operations qla82xx_isp_ops = { @@ -1698,6 +1815,7 @@ static struct isp_operations qla82xx_isp_ops = { .get_flash_version = qla24xx_get_flash_version, .start_scsi = qla82xx_start_scsi, .abort_isp = qla82xx_abort_isp, + .iospace_config = qla82xx_iospace_config, }; static inline void @@ -1811,117 +1929,6 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha) ha->device_type, ha->flags.port0, ha->fw_srisc_address); } -static int -qla2x00_iospace_config(struct qla_hw_data *ha) -{ - resource_size_t pio; - uint16_t msix; - int cpus; - - if (IS_QLA82XX(ha)) - return qla82xx_iospace_config(ha); - - if (pci_request_selected_regions(ha->pdev, ha->bars, - QLA2XXX_DRIVER_NAME)) { - ql_log_pci(ql_log_fatal, ha->pdev, 0x0011, - "Failed to reserve PIO/MMIO regions (%s), aborting.\n", - pci_name(ha->pdev)); - goto iospace_error_exit; - } - if (!(ha->bars & 1)) - goto skip_pio; - - /* We only need PIO for Flash operations on ISP2312 v2 chips. */ - pio = pci_resource_start(ha->pdev, 0); - if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) { - if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) { - ql_log_pci(ql_log_warn, ha->pdev, 0x0012, - "Invalid pci I/O region size (%s).\n", - pci_name(ha->pdev)); - pio = 0; - } - } else { - ql_log_pci(ql_log_warn, ha->pdev, 0x0013, - "Region #0 no a PIO resource (%s).\n", - pci_name(ha->pdev)); - pio = 0; - } - ha->pio_address = pio; - ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0014, - "PIO address=%llu.\n", - (unsigned long long)ha->pio_address); - -skip_pio: - /* Use MMIO operations for all accesses. */ - if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) { - ql_log_pci(ql_log_fatal, ha->pdev, 0x0015, - "Region #1 not an MMIO resource (%s), aborting.\n", - pci_name(ha->pdev)); - goto iospace_error_exit; - } - if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) { - ql_log_pci(ql_log_fatal, ha->pdev, 0x0016, - "Invalid PCI mem region size (%s), aborting.\n", - pci_name(ha->pdev)); - goto iospace_error_exit; - } - - ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN); - if (!ha->iobase) { - ql_log_pci(ql_log_fatal, ha->pdev, 0x0017, - "Cannot remap MMIO (%s), aborting.\n", - pci_name(ha->pdev)); - goto iospace_error_exit; - } - - /* Determine queue resources */ - ha->max_req_queues = ha->max_rsp_queues = 1; - if ((ql2xmaxqueues <= 1 && !ql2xmultique_tag) || - (ql2xmaxqueues > 1 && ql2xmultique_tag) || - (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))) - goto mqiobase_exit; - - ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), - pci_resource_len(ha->pdev, 3)); - if (ha->mqiobase) { - ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0018, - "MQIO Base=%p.\n", ha->mqiobase); - /* Read MSIX vector size of the board */ - pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix); - ha->msix_count = msix; - /* Max queues are bounded by available msix vectors */ - /* queue 0 uses two msix vectors */ - if (ql2xmultique_tag) { - cpus = num_online_cpus(); - ha->max_rsp_queues = (ha->msix_count - 1 > cpus) ? - (cpus + 1) : (ha->msix_count - 1); - ha->max_req_queues = 2; - } else if (ql2xmaxqueues > 1) { - ha->max_req_queues = ql2xmaxqueues > QLA_MQ_SIZE ? - QLA_MQ_SIZE : ql2xmaxqueues; - ql_dbg_pci(ql_dbg_multiq, ha->pdev, 0xc008, - "QoS mode set, max no of request queues:%d.\n", - ha->max_req_queues); - ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0019, - "QoS mode set, max no of request queues:%d.\n", - ha->max_req_queues); - } - ql_log_pci(ql_log_info, ha->pdev, 0x001a, - "MSI-X vector count: %d.\n", msix); - } else - ql_log_pci(ql_log_info, ha->pdev, 0x001b, - "BAR 3 not enabled.\n"); - -mqiobase_exit: - ha->msix_count = ha->max_rsp_queues + 1; - ql_dbg_pci(ql_dbg_init, ha->pdev, 0x001c, - "MSIX Count:%d.\n", ha->msix_count); - return (0); - -iospace_error_exit: - return (-ENOMEM); -} - static void qla2xxx_scan_start(struct Scsi_Host *shost) { @@ -2020,19 +2027,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pdev->needs_freset = 1; } - /* Configure PCI I/O space */ - ret = qla2x00_iospace_config(ha); - if (ret) - goto probe_hw_failed; - - ql_log_pci(ql_log_info, pdev, 0x001d, - "Found an ISP%04X irq %d iobase 0x%p.\n", - pdev->device, pdev->irq, ha->iobase); - ha->prev_topology = 0; - ha->init_cb_size = sizeof(init_cb_t); - ha->link_data_rate = PORT_SPEED_UNKNOWN; - ha->optrom_size = OPTROM_SIZE_2300; - /* Assign ISP specific operations. */ max_id = MAX_TARGETS_2200; if (IS_QLA2100(ha)) { @@ -2140,6 +2134,20 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) "flash_data_off=%d, nvram_conf_off=%d, nvram_data_off=%d.\n", ha->isp_ops, ha->flash_conf_off, ha->flash_data_off, ha->nvram_conf_off, ha->nvram_data_off); + + /* Configure PCI I/O space */ + ret = ha->isp_ops->iospace_config(ha); + if (ret) + goto probe_hw_failed; + + ql_log_pci(ql_log_info, pdev, 0x001d, + "Found an ISP%04X irq %d iobase 0x%p.\n", + pdev->device, pdev->irq, ha->iobase); + ha->prev_topology = 0; + ha->init_cb_size = sizeof(init_cb_t); + ha->link_data_rate = PORT_SPEED_UNKNOWN; + ha->optrom_size = OPTROM_SIZE_2300; + mutex_init(&ha->vport_lock); init_completion(&ha->mbx_cmd_comp); complete(&ha->mbx_cmd_comp); -- cgit From 99b8212c491913bd077063c138676ad5af8c6d3d Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:03:17 -0800 Subject: [SCSI] qla2xxx: Process marker IOCB request on request queue 0. When multiple request queues are created process the marker IOCB request on request queue 0. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_iocb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d63132536c88..64a3075c3b47 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -489,6 +489,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); mrk24 = NULL; + req = ha->req_q_map[0]; mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, 0); if (mrk == NULL) { ql_log(ql_log_warn, base_vha, 0x3026, -- cgit From 5162cf0c4e3962b28a9c8bc1ce89d266db67aa55 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 18 Nov 2011 09:03:18 -0800 Subject: [SCSI] qla2xxx: Consolidated IOCB processing routines. Signed-off-by: Giridhar Malavali Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 3 +- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 618 +++++++++++++++++++++++++++++++++------- drivers/scsi/qla2xxx/qla_nx.c | 482 +------------------------------ 4 files changed, 522 insertions(+), 583 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index dc454628f0a1..7c54624b5b13 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -14,7 +14,8 @@ * | Module Init and Probe | 0x0116 | 0xfa | * | Mailbox commands | 0x112b | | * | Device Discovery | 0x2084 | | - * | Queue Command and IO tracing | 0x302f | 0x3008 | + * | Queue Command and IO tracing | 0x302f | 0x3008,0x302d, | + * | | | 0x302e | * | DPC Thread | 0x401c | | * | Async Events | 0x5057 | 0x5052 | * | Timer Routines | 0x6011 | 0x600e,0x600f | diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index c0c11afb685c..408679be8fdf 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -572,7 +572,7 @@ extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *, size_t, char *); extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *); extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *); -extern void qla82xx_start_iocbs(srb_t *); +extern void qla82xx_start_iocbs(scsi_qla_host_t *); extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *); extern int qla82xx_check_md_needed(scsi_qla_host_t *); extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 64a3075c3b47..d2cc0ccfc202 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -11,8 +11,6 @@ #include -static void qla2x00_isp_cmd(struct scsi_qla_host *, struct req_que *); - static void qla25xx_set_que(srb_t *, struct rsp_que **); /** * qla2x00_get_cmd_direction() - Determine control_flag data direction. @@ -467,6 +465,42 @@ queuing_error: return (QLA_FUNCTION_FAILED); } +/** + * qla2x00_start_iocbs() - Execute the IOCB command + */ +static void +qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) +{ + struct qla_hw_data *ha = vha->hw; + device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); + struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; + + if (IS_QLA82XX(ha)) { + qla82xx_start_iocbs(vha); + } else { + /* Adjust ring index. */ + req->ring_index++; + if (req->ring_index == req->length) { + req->ring_index = 0; + req->ring_ptr = req->ring; + } else + req->ring_ptr++; + + /* Set chip new ring index. */ + if (ha->mqenable) { + WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); + RD_REG_DWORD(&ioreg->hccr); + } else if (IS_FWI2_CAPABLE(ha)) { + WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); + RD_REG_DWORD_RELAXED(®->isp24.req_q_in); + } else { + WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), + req->ring_index); + RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); + } + } +} + /** * qla2x00_marker() - Send a marker IOCB to the firmware. * @ha: HA context @@ -516,7 +550,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, } wmb(); - qla2x00_isp_cmd(vha, req); + qla2x00_start_iocbs(vha, req); return (QLA_SUCCESS); } @@ -537,89 +571,140 @@ qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, } /** - * qla2x00_isp_cmd() - Modify the request ring pointer. - * @ha: HA context + * qla24xx_calc_iocbs() - Determine number of Command Type 3 and + * Continuation Type 1 IOCBs to allocate. * - * Note: The caller must hold the hardware lock before calling this routine. + * @dsds: number of data segment decriptors needed + * + * Returns the number of IOCB entries needed to store @dsds. */ -static void -qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req) +inline uint16_t +qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds) { - struct qla_hw_data *ha = vha->hw; - device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); - struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; + uint16_t iocbs; - ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x302d, - "IOCB data:\n"); - ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e, - (uint8_t *)req->ring_ptr, REQUEST_ENTRY_SIZE); + iocbs = 1; + if (dsds > 1) { + iocbs += (dsds - 1) / 5; + if ((dsds - 1) % 5) + iocbs++; + } + return iocbs; +} - /* Adjust ring index. */ - req->ring_index++; - if (req->ring_index == req->length) { - req->ring_index = 0; - req->ring_ptr = req->ring; - } else - req->ring_ptr++; +static inline int +qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, + uint16_t tot_dsds) +{ + uint32_t *cur_dsd = NULL; + scsi_qla_host_t *vha; + struct qla_hw_data *ha; + struct scsi_cmnd *cmd; + struct scatterlist *cur_seg; + uint32_t *dsd_seg; + void *next_dsd; + uint8_t avail_dsds; + uint8_t first_iocb = 1; + uint32_t dsd_list_len; + struct dsd_dma *dsd_ptr; + struct ct6_dsd *ctx; - /* Set chip new ring index. */ - if (IS_QLA82XX(ha)) { - uint32_t dbval = 0x04 | (ha->portnum << 5); + cmd = sp->cmd; - /* write, read and verify logic */ - dbval = dbval | (req->id << 8) | (req->ring_index << 16); - if (ql2xdbwr) - qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); - else { - WRT_REG_DWORD( - (unsigned long __iomem *)ha->nxdb_wr_ptr, - dbval); - wmb(); - while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { - WRT_REG_DWORD((unsigned long __iomem *) - ha->nxdb_wr_ptr, dbval); - wmb(); - } - } - } else if (ha->mqenable) { - /* Set chip new ring index. */ - WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); - RD_REG_DWORD(&ioreg->hccr); - } else { - if (IS_FWI2_CAPABLE(ha)) { - WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); - RD_REG_DWORD_RELAXED(®->isp24.req_q_in); + /* Update entry type to indicate Command Type 3 IOCB */ + *((uint32_t *)(&cmd_pkt->entry_type)) = + __constant_cpu_to_le32(COMMAND_TYPE_6); + + /* No data transfer */ + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { + cmd_pkt->byte_count = __constant_cpu_to_le32(0); + return 0; + } + + vha = sp->fcport->vha; + ha = vha->hw; + + /* Set transfer direction */ + if (cmd->sc_data_direction == DMA_TO_DEVICE) { + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_WRITE_DATA); + ha->qla_stats.output_bytes += scsi_bufflen(cmd); + } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { + cmd_pkt->control_flags = + __constant_cpu_to_le16(CF_READ_DATA); + ha->qla_stats.input_bytes += scsi_bufflen(cmd); + } + + cur_seg = scsi_sglist(cmd); + ctx = sp->ctx; + + while (tot_dsds) { + avail_dsds = (tot_dsds > QLA_DSDS_PER_IOCB) ? + QLA_DSDS_PER_IOCB : tot_dsds; + tot_dsds -= avail_dsds; + dsd_list_len = (avail_dsds + 1) * QLA_DSD_SIZE; + + dsd_ptr = list_first_entry(&ha->gbl_dsd_list, + struct dsd_dma, list); + next_dsd = dsd_ptr->dsd_addr; + list_del(&dsd_ptr->list); + ha->gbl_dsd_avail--; + list_add_tail(&dsd_ptr->list, &ctx->dsd_list); + ctx->dsd_use_cnt++; + ha->gbl_dsd_inuse++; + + if (first_iocb) { + first_iocb = 0; + dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address; + *dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); + *dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); + cmd_pkt->fcp_data_dseg_len = cpu_to_le32(dsd_list_len); } else { - WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), - req->ring_index); - RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); + *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); + *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); + *cur_dsd++ = cpu_to_le32(dsd_list_len); + } + cur_dsd = (uint32_t *)next_dsd; + while (avail_dsds) { + dma_addr_t sle_dma; + + sle_dma = sg_dma_address(cur_seg); + *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); + *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg)); + cur_seg = sg_next(cur_seg); + avail_dsds--; } } + /* Null termination */ + *cur_dsd++ = 0; + *cur_dsd++ = 0; + *cur_dsd++ = 0; + cmd_pkt->control_flags |= CF_DATA_SEG_DESCR_ENABLE; + return 0; } -/** - * qla24xx_calc_iocbs() - Determine number of Command Type 3 and - * Continuation Type 1 IOCBs to allocate. +/* + * qla24xx_calc_dsd_lists() - Determine number of DSD list required + * for Command Type 6. * * @dsds: number of data segment decriptors needed * - * Returns the number of IOCB entries needed to store @dsds. + * Returns the number of dsd list needed to store @dsds. */ inline uint16_t -qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds) +qla24xx_calc_dsd_lists(uint16_t dsds) { - uint16_t iocbs; + uint16_t dsd_lists = 0; - iocbs = 1; - if (dsds > 1) { - iocbs += (dsds - 1) / 5; - if ((dsds - 1) % 5) - iocbs++; - } - return iocbs; + dsd_lists = (dsds/QLA_DSDS_PER_IOCB); + if (dsds % QLA_DSDS_PER_IOCB) + dsd_lists++; + return dsd_lists; } + /** * qla24xx_build_scsi_iocbs() - Build IOCB command utilizing Command Type 7 * IOCB types. @@ -946,6 +1031,7 @@ alloc_and_fill: *cur_dsd++ = 0; return 0; } + static int qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, uint16_t tot_dsds) @@ -1793,42 +1879,6 @@ queuing_error: return pkt; } -static void -qla2x00_start_iocbs(srb_t *sp) -{ - struct qla_hw_data *ha = sp->fcport->vha->hw; - struct req_que *req = ha->req_q_map[0]; - device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); - struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; - - if (IS_QLA82XX(ha)) { - qla82xx_start_iocbs(sp); - } else { - /* Adjust ring index. */ - req->ring_index++; - if (req->ring_index == req->length) { - req->ring_index = 0; - req->ring_ptr = req->ring; - } else - req->ring_ptr++; - - /* Set chip new ring index. */ - if (ha->mqenable) { - WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); - RD_REG_DWORD(&ioreg->hccr); - } else if (IS_QLA82XX(ha)) { - qla82xx_start_iocbs(sp); - } else if (IS_FWI2_CAPABLE(ha)) { - WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); - RD_REG_DWORD_RELAXED(®->isp24.req_q_in); - } else { - WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), - req->ring_index); - RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); - } - } -} - static void qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) { @@ -2161,6 +2211,372 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) ct_iocb->entry_count = entry_count; } +/* + * qla82xx_start_scsi() - Send a SCSI command to the ISP + * @sp: command to send to the ISP + * + * Returns non-zero if a failure occurred, else zero. + */ +int +qla82xx_start_scsi(srb_t *sp) +{ + int ret, nseg; + unsigned long flags; + struct scsi_cmnd *cmd; + uint32_t *clr_ptr; + uint32_t index; + uint32_t handle; + uint16_t cnt; + uint16_t req_cnt; + uint16_t tot_dsds; + struct device_reg_82xx __iomem *reg; + uint32_t dbval; + uint32_t *fcp_dl; + uint8_t additional_cdb_len; + struct ct6_dsd *ctx; + struct scsi_qla_host *vha = sp->fcport->vha; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = NULL; + struct rsp_que *rsp = NULL; + char tag[2]; + + /* Setup device pointers. */ + ret = 0; + reg = &ha->iobase->isp82; + cmd = sp->cmd; + req = vha->req; + rsp = ha->rsp_q_map[0]; + + /* So we know we haven't pci_map'ed anything yet */ + tot_dsds = 0; + + dbval = 0x04 | (ha->portnum << 5); + + /* Send marker if required */ + if (vha->marker_needed != 0) { + if (qla2x00_marker(vha, req, + rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x300c, + "qla2x00_marker failed for cmd=%p.\n", cmd); + return QLA_FUNCTION_FAILED; + } + vha->marker_needed = 0; + } + + /* Acquire ring specific lock */ + spin_lock_irqsave(&ha->hardware_lock, flags); + + /* Check for room in outstanding command list. */ + handle = req->current_outstanding_cmd; + for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { + handle++; + if (handle == MAX_OUTSTANDING_COMMANDS) + handle = 1; + if (!req->outstanding_cmds[handle]) + break; + } + if (index == MAX_OUTSTANDING_COMMANDS) + goto queuing_error; + + /* Map the sg table so we have an accurate count of sg entries needed */ + if (scsi_sg_count(cmd)) { + nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), + scsi_sg_count(cmd), cmd->sc_data_direction); + if (unlikely(!nseg)) + goto queuing_error; + } else + nseg = 0; + + tot_dsds = nseg; + + if (tot_dsds > ql2xshiftctondsd) { + struct cmd_type_6 *cmd_pkt; + uint16_t more_dsd_lists = 0; + struct dsd_dma *dsd_ptr; + uint16_t i; + + more_dsd_lists = qla24xx_calc_dsd_lists(tot_dsds); + if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN) { + ql_dbg(ql_dbg_io, vha, 0x300d, + "Num of DSD list %d is than %d for cmd=%p.\n", + more_dsd_lists + ha->gbl_dsd_inuse, NUM_DSD_CHAIN, + cmd); + goto queuing_error; + } + + if (more_dsd_lists <= ha->gbl_dsd_avail) + goto sufficient_dsds; + else + more_dsd_lists -= ha->gbl_dsd_avail; + + for (i = 0; i < more_dsd_lists; i++) { + dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); + if (!dsd_ptr) { + ql_log(ql_log_fatal, vha, 0x300e, + "Failed to allocate memory for dsd_dma " + "for cmd=%p.\n", cmd); + goto queuing_error; + } + + dsd_ptr->dsd_addr = dma_pool_alloc(ha->dl_dma_pool, + GFP_ATOMIC, &dsd_ptr->dsd_list_dma); + if (!dsd_ptr->dsd_addr) { + kfree(dsd_ptr); + ql_log(ql_log_fatal, vha, 0x300f, + "Failed to allocate memory for dsd_addr " + "for cmd=%p.\n", cmd); + goto queuing_error; + } + list_add_tail(&dsd_ptr->list, &ha->gbl_dsd_list); + ha->gbl_dsd_avail++; + } + +sufficient_dsds: + req_cnt = 1; + + if (req->cnt < (req_cnt + 2)) { + cnt = (uint16_t)RD_REG_DWORD_RELAXED( + ®->req_q_out[0]); + if (req->ring_index < cnt) + req->cnt = cnt - req->ring_index; + else + req->cnt = req->length - + (req->ring_index - cnt); + } + + if (req->cnt < (req_cnt + 2)) + goto queuing_error; + + ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); + if (!sp->ctx) { + ql_log(ql_log_fatal, vha, 0x3010, + "Failed to allocate ctx for cmd=%p.\n", cmd); + goto queuing_error; + } + memset(ctx, 0, sizeof(struct ct6_dsd)); + ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool, + GFP_ATOMIC, &ctx->fcp_cmnd_dma); + if (!ctx->fcp_cmnd) { + ql_log(ql_log_fatal, vha, 0x3011, + "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd); + goto queuing_error_fcp_cmnd; + } + + /* Initialize the DSD list and dma handle */ + INIT_LIST_HEAD(&ctx->dsd_list); + ctx->dsd_use_cnt = 0; + + if (cmd->cmd_len > 16) { + additional_cdb_len = cmd->cmd_len - 16; + if ((cmd->cmd_len % 4) != 0) { + /* SCSI command bigger than 16 bytes must be + * multiple of 4 + */ + ql_log(ql_log_warn, vha, 0x3012, + "scsi cmd len %d not multiple of 4 " + "for cmd=%p.\n", cmd->cmd_len, cmd); + goto queuing_error_fcp_cmnd; + } + ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4; + } else { + additional_cdb_len = 0; + ctx->fcp_cmnd_len = 12 + 16 + 4; + } + + cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; + cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + + /* Zero out remaining portion of packet. */ + /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ + clr_ptr = (uint32_t *)cmd_pkt + 2; + memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); + cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); + + /* Set NPORT-ID and LUN number*/ + cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); + cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; + cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; + cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; + cmd_pkt->vp_index = sp->fcport->vp_idx; + + /* Build IOCB segments */ + if (qla24xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds)) + goto queuing_error_fcp_cmnd; + + int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); + host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); + + /* build FCP_CMND IU */ + memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd)); + int_to_scsilun(sp->cmd->device->lun, &ctx->fcp_cmnd->lun); + ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len; + + if (cmd->sc_data_direction == DMA_TO_DEVICE) + ctx->fcp_cmnd->additional_cdb_len |= 1; + else if (cmd->sc_data_direction == DMA_FROM_DEVICE) + ctx->fcp_cmnd->additional_cdb_len |= 2; + + /* + * Update tagged queuing modifier -- default is TSK_SIMPLE (0). + */ + if (scsi_populate_tag_msg(cmd, tag)) { + switch (tag[0]) { + case HEAD_OF_QUEUE_TAG: + ctx->fcp_cmnd->task_attribute = + TSK_HEAD_OF_QUEUE; + break; + case ORDERED_QUEUE_TAG: + ctx->fcp_cmnd->task_attribute = + TSK_ORDERED; + break; + } + } + + memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); + + fcp_dl = (uint32_t *)(ctx->fcp_cmnd->cdb + 16 + + additional_cdb_len); + *fcp_dl = htonl((uint32_t)scsi_bufflen(cmd)); + + cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len); + cmd_pkt->fcp_cmnd_dseg_address[0] = + cpu_to_le32(LSD(ctx->fcp_cmnd_dma)); + cmd_pkt->fcp_cmnd_dseg_address[1] = + cpu_to_le32(MSD(ctx->fcp_cmnd_dma)); + + sp->flags |= SRB_FCP_CMND_DMA_VALID; + cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); + /* Set total data segment count. */ + cmd_pkt->entry_count = (uint8_t)req_cnt; + /* Specify response queue number where + * completion should happen + */ + cmd_pkt->entry_status = (uint8_t) rsp->id; + } else { + struct cmd_type_7 *cmd_pkt; + req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + if (req->cnt < (req_cnt + 2)) { + cnt = (uint16_t)RD_REG_DWORD_RELAXED( + ®->req_q_out[0]); + if (req->ring_index < cnt) + req->cnt = cnt - req->ring_index; + else + req->cnt = req->length - + (req->ring_index - cnt); + } + if (req->cnt < (req_cnt + 2)) + goto queuing_error; + + cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; + cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + + /* Zero out remaining portion of packet. */ + /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ + clr_ptr = (uint32_t *)cmd_pkt + 2; + memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); + cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); + + /* Set NPORT-ID and LUN number*/ + cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); + cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; + cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; + cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; + cmd_pkt->vp_index = sp->fcport->vp_idx; + + int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); + host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, + sizeof(cmd_pkt->lun)); + + /* + * Update tagged queuing modifier -- default is TSK_SIMPLE (0). + */ + if (scsi_populate_tag_msg(cmd, tag)) { + switch (tag[0]) { + case HEAD_OF_QUEUE_TAG: + cmd_pkt->task = TSK_HEAD_OF_QUEUE; + break; + case ORDERED_QUEUE_TAG: + cmd_pkt->task = TSK_ORDERED; + break; + } + } + + /* Load SCSI command packet. */ + memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len); + host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb)); + + cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); + + /* Build IOCB segments */ + qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds); + + /* Set total data segment count. */ + cmd_pkt->entry_count = (uint8_t)req_cnt; + /* Specify response queue number where + * completion should happen. + */ + cmd_pkt->entry_status = (uint8_t) rsp->id; + + } + /* Build command packet. */ + req->current_outstanding_cmd = handle; + req->outstanding_cmds[handle] = sp; + sp->handle = handle; + sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; + req->cnt -= req_cnt; + wmb(); + + /* Adjust ring index. */ + req->ring_index++; + if (req->ring_index == req->length) { + req->ring_index = 0; + req->ring_ptr = req->ring; + } else + req->ring_ptr++; + + sp->flags |= SRB_DMA_VALID; + + /* Set chip new ring index. */ + /* write, read and verify logic */ + dbval = dbval | (req->id << 8) | (req->ring_index << 16); + if (ql2xdbwr) + qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); + else { + WRT_REG_DWORD( + (unsigned long __iomem *)ha->nxdb_wr_ptr, + dbval); + wmb(); + while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { + WRT_REG_DWORD( + (unsigned long __iomem *)ha->nxdb_wr_ptr, + dbval); + wmb(); + } + } + + /* Manage unprocessed RIO/ZIO commands in response queue. */ + if (vha->flags.process_response_queue && + rsp->ring_ptr->signature != RESPONSE_PROCESSED) + qla24xx_process_response_queue(vha, rsp); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return QLA_SUCCESS; + +queuing_error_fcp_cmnd: + dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, ctx->fcp_cmnd_dma); +queuing_error: + if (tot_dsds) + scsi_dma_unmap(cmd); + + if (sp->ctx) { + mempool_free(sp->ctx, ha->ctx_mempool); + sp->ctx = NULL; + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return QLA_FUNCTION_FAILED; +} + int qla2x00_start_sp(srb_t *sp) { @@ -2213,7 +2629,7 @@ qla2x00_start_sp(srb_t *sp) } wmb(); - qla2x00_start_iocbs(sp); + qla2x00_start_iocbs(sp->fcport->vha, ha->req_q_map[0]); done: spin_unlock_irqrestore(&ha->hardware_lock, flags); return rval; diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 805b4b734754..24447ddb4b66 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2539,484 +2539,6 @@ qla82xx_start_firmware(scsi_qla_host_t *vha) return qla82xx_check_rcvpeg_state(ha); } -static inline int -qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, - uint16_t tot_dsds) -{ - uint32_t *cur_dsd = NULL; - scsi_qla_host_t *vha; - struct qla_hw_data *ha; - struct scsi_cmnd *cmd; - struct scatterlist *cur_seg; - uint32_t *dsd_seg; - void *next_dsd; - uint8_t avail_dsds; - uint8_t first_iocb = 1; - uint32_t dsd_list_len; - struct dsd_dma *dsd_ptr; - struct ct6_dsd *ctx; - - cmd = sp->cmd; - - /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&cmd_pkt->entry_type)) = - __constant_cpu_to_le32(COMMAND_TYPE_6); - - /* No data transfer */ - if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { - cmd_pkt->byte_count = __constant_cpu_to_le32(0); - return 0; - } - - vha = sp->fcport->vha; - ha = vha->hw; - - /* Set transfer direction */ - if (cmd->sc_data_direction == DMA_TO_DEVICE) { - cmd_pkt->control_flags = - __constant_cpu_to_le16(CF_WRITE_DATA); - ha->qla_stats.output_bytes += scsi_bufflen(cmd); - } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { - cmd_pkt->control_flags = - __constant_cpu_to_le16(CF_READ_DATA); - ha->qla_stats.input_bytes += scsi_bufflen(cmd); - } - - cur_seg = scsi_sglist(cmd); - ctx = sp->ctx; - - while (tot_dsds) { - avail_dsds = (tot_dsds > QLA_DSDS_PER_IOCB) ? - QLA_DSDS_PER_IOCB : tot_dsds; - tot_dsds -= avail_dsds; - dsd_list_len = (avail_dsds + 1) * QLA_DSD_SIZE; - - dsd_ptr = list_first_entry(&ha->gbl_dsd_list, - struct dsd_dma, list); - next_dsd = dsd_ptr->dsd_addr; - list_del(&dsd_ptr->list); - ha->gbl_dsd_avail--; - list_add_tail(&dsd_ptr->list, &ctx->dsd_list); - ctx->dsd_use_cnt++; - ha->gbl_dsd_inuse++; - - if (first_iocb) { - first_iocb = 0; - dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address; - *dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); - *dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); - cmd_pkt->fcp_data_dseg_len = cpu_to_le32(dsd_list_len); - } else { - *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); - *cur_dsd++ = cpu_to_le32(dsd_list_len); - } - cur_dsd = (uint32_t *)next_dsd; - while (avail_dsds) { - dma_addr_t sle_dma; - - sle_dma = sg_dma_address(cur_seg); - *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); - *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg)); - cur_seg = sg_next(cur_seg); - avail_dsds--; - } - } - - /* Null termination */ - *cur_dsd++ = 0; - *cur_dsd++ = 0; - *cur_dsd++ = 0; - cmd_pkt->control_flags |= CF_DATA_SEG_DESCR_ENABLE; - return 0; -} - -/* - * qla82xx_calc_dsd_lists() - Determine number of DSD list required - * for Command Type 6. - * - * @dsds: number of data segment decriptors needed - * - * Returns the number of dsd list needed to store @dsds. - */ -inline uint16_t -qla82xx_calc_dsd_lists(uint16_t dsds) -{ - uint16_t dsd_lists = 0; - - dsd_lists = (dsds/QLA_DSDS_PER_IOCB); - if (dsds % QLA_DSDS_PER_IOCB) - dsd_lists++; - return dsd_lists; -} - -/* - * qla82xx_start_scsi() - Send a SCSI command to the ISP - * @sp: command to send to the ISP - * - * Returns non-zero if a failure occurred, else zero. - */ -int -qla82xx_start_scsi(srb_t *sp) -{ - int ret, nseg; - unsigned long flags; - struct scsi_cmnd *cmd; - uint32_t *clr_ptr; - uint32_t index; - uint32_t handle; - uint16_t cnt; - uint16_t req_cnt; - uint16_t tot_dsds; - struct device_reg_82xx __iomem *reg; - uint32_t dbval; - uint32_t *fcp_dl; - uint8_t additional_cdb_len; - struct ct6_dsd *ctx; - struct scsi_qla_host *vha = sp->fcport->vha; - struct qla_hw_data *ha = vha->hw; - struct req_que *req = NULL; - struct rsp_que *rsp = NULL; - char tag[2]; - - /* Setup device pointers. */ - ret = 0; - reg = &ha->iobase->isp82; - cmd = sp->cmd; - req = vha->req; - rsp = ha->rsp_q_map[0]; - - /* So we know we haven't pci_map'ed anything yet */ - tot_dsds = 0; - - dbval = 0x04 | (ha->portnum << 5); - - /* Send marker if required */ - if (vha->marker_needed != 0) { - if (qla2x00_marker(vha, req, - rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x300c, - "qla2x00_marker failed for cmd=%p.\n", cmd); - return QLA_FUNCTION_FAILED; - } - vha->marker_needed = 0; - } - - /* Acquire ring specific lock */ - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Check for room in outstanding command list. */ - handle = req->current_outstanding_cmd; - for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { - handle++; - if (handle == MAX_OUTSTANDING_COMMANDS) - handle = 1; - if (!req->outstanding_cmds[handle]) - break; - } - if (index == MAX_OUTSTANDING_COMMANDS) - goto queuing_error; - - /* Map the sg table so we have an accurate count of sg entries needed */ - if (scsi_sg_count(cmd)) { - nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), - scsi_sg_count(cmd), cmd->sc_data_direction); - if (unlikely(!nseg)) - goto queuing_error; - } else - nseg = 0; - - tot_dsds = nseg; - - if (tot_dsds > ql2xshiftctondsd) { - struct cmd_type_6 *cmd_pkt; - uint16_t more_dsd_lists = 0; - struct dsd_dma *dsd_ptr; - uint16_t i; - - more_dsd_lists = qla82xx_calc_dsd_lists(tot_dsds); - if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN) { - ql_dbg(ql_dbg_io, vha, 0x300d, - "Num of DSD list %d is than %d for cmd=%p.\n", - more_dsd_lists + ha->gbl_dsd_inuse, NUM_DSD_CHAIN, - cmd); - goto queuing_error; - } - - if (more_dsd_lists <= ha->gbl_dsd_avail) - goto sufficient_dsds; - else - more_dsd_lists -= ha->gbl_dsd_avail; - - for (i = 0; i < more_dsd_lists; i++) { - dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); - if (!dsd_ptr) { - ql_log(ql_log_fatal, vha, 0x300e, - "Failed to allocate memory for dsd_dma " - "for cmd=%p.\n", cmd); - goto queuing_error; - } - - dsd_ptr->dsd_addr = dma_pool_alloc(ha->dl_dma_pool, - GFP_ATOMIC, &dsd_ptr->dsd_list_dma); - if (!dsd_ptr->dsd_addr) { - kfree(dsd_ptr); - ql_log(ql_log_fatal, vha, 0x300f, - "Failed to allocate memory for dsd_addr " - "for cmd=%p.\n", cmd); - goto queuing_error; - } - list_add_tail(&dsd_ptr->list, &ha->gbl_dsd_list); - ha->gbl_dsd_avail++; - } - -sufficient_dsds: - req_cnt = 1; - - if (req->cnt < (req_cnt + 2)) { - cnt = (uint16_t)RD_REG_DWORD_RELAXED( - ®->req_q_out[0]); - if (req->ring_index < cnt) - req->cnt = cnt - req->ring_index; - else - req->cnt = req->length - - (req->ring_index - cnt); - } - - if (req->cnt < (req_cnt + 2)) - goto queuing_error; - - ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); - if (!sp->ctx) { - ql_log(ql_log_fatal, vha, 0x3010, - "Failed to allocate ctx for cmd=%p.\n", cmd); - goto queuing_error; - } - memset(ctx, 0, sizeof(struct ct6_dsd)); - ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool, - GFP_ATOMIC, &ctx->fcp_cmnd_dma); - if (!ctx->fcp_cmnd) { - ql_log(ql_log_fatal, vha, 0x3011, - "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd); - goto queuing_error_fcp_cmnd; - } - - /* Initialize the DSD list and dma handle */ - INIT_LIST_HEAD(&ctx->dsd_list); - ctx->dsd_use_cnt = 0; - - if (cmd->cmd_len > 16) { - additional_cdb_len = cmd->cmd_len - 16; - if ((cmd->cmd_len % 4) != 0) { - /* SCSI command bigger than 16 bytes must be - * multiple of 4 - */ - ql_log(ql_log_warn, vha, 0x3012, - "scsi cmd len %d not multiple of 4 " - "for cmd=%p.\n", cmd->cmd_len, cmd); - goto queuing_error_fcp_cmnd; - } - ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4; - } else { - additional_cdb_len = 0; - ctx->fcp_cmnd_len = 12 + 16 + 4; - } - - cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); - - /* Zero out remaining portion of packet. */ - /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ - clr_ptr = (uint32_t *)cmd_pkt + 2; - memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); - cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); - - /* Set NPORT-ID and LUN number*/ - cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); - cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; - cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; - cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; - cmd_pkt->vp_index = sp->fcport->vp_idx; - - /* Build IOCB segments */ - if (qla2xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds)) - goto queuing_error_fcp_cmnd; - - int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); - host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); - - /* build FCP_CMND IU */ - memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd)); - int_to_scsilun(sp->cmd->device->lun, &ctx->fcp_cmnd->lun); - ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len; - - if (cmd->sc_data_direction == DMA_TO_DEVICE) - ctx->fcp_cmnd->additional_cdb_len |= 1; - else if (cmd->sc_data_direction == DMA_FROM_DEVICE) - ctx->fcp_cmnd->additional_cdb_len |= 2; - - /* - * Update tagged queuing modifier -- default is TSK_SIMPLE (0). - */ - if (scsi_populate_tag_msg(cmd, tag)) { - switch (tag[0]) { - case HEAD_OF_QUEUE_TAG: - ctx->fcp_cmnd->task_attribute = - TSK_HEAD_OF_QUEUE; - break; - case ORDERED_QUEUE_TAG: - ctx->fcp_cmnd->task_attribute = - TSK_ORDERED; - break; - } - } - - memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); - - fcp_dl = (uint32_t *)(ctx->fcp_cmnd->cdb + 16 + - additional_cdb_len); - *fcp_dl = htonl((uint32_t)scsi_bufflen(cmd)); - - cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len); - cmd_pkt->fcp_cmnd_dseg_address[0] = - cpu_to_le32(LSD(ctx->fcp_cmnd_dma)); - cmd_pkt->fcp_cmnd_dseg_address[1] = - cpu_to_le32(MSD(ctx->fcp_cmnd_dma)); - - sp->flags |= SRB_FCP_CMND_DMA_VALID; - cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); - /* Set total data segment count. */ - cmd_pkt->entry_count = (uint8_t)req_cnt; - /* Specify response queue number where - * completion should happen - */ - cmd_pkt->entry_status = (uint8_t) rsp->id; - } else { - struct cmd_type_7 *cmd_pkt; - req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); - if (req->cnt < (req_cnt + 2)) { - cnt = (uint16_t)RD_REG_DWORD_RELAXED( - ®->req_q_out[0]); - if (req->ring_index < cnt) - req->cnt = cnt - req->ring_index; - else - req->cnt = req->length - - (req->ring_index - cnt); - } - if (req->cnt < (req_cnt + 2)) - goto queuing_error; - - cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); - - /* Zero out remaining portion of packet. */ - /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ - clr_ptr = (uint32_t *)cmd_pkt + 2; - memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); - cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); - - /* Set NPORT-ID and LUN number*/ - cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); - cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; - cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; - cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; - cmd_pkt->vp_index = sp->fcport->vp_idx; - - int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); - host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, - sizeof(cmd_pkt->lun)); - - /* - * Update tagged queuing modifier -- default is TSK_SIMPLE (0). - */ - if (scsi_populate_tag_msg(cmd, tag)) { - switch (tag[0]) { - case HEAD_OF_QUEUE_TAG: - cmd_pkt->task = TSK_HEAD_OF_QUEUE; - break; - case ORDERED_QUEUE_TAG: - cmd_pkt->task = TSK_ORDERED; - break; - } - } - - /* Load SCSI command packet. */ - memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len); - host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb)); - - cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); - - /* Build IOCB segments */ - qla24xx_build_scsi_iocbs(sp, cmd_pkt, tot_dsds); - - /* Set total data segment count. */ - cmd_pkt->entry_count = (uint8_t)req_cnt; - /* Specify response queue number where - * completion should happen. - */ - cmd_pkt->entry_status = (uint8_t) rsp->id; - - } - /* Build command packet. */ - req->current_outstanding_cmd = handle; - req->outstanding_cmds[handle] = sp; - sp->handle = handle; - sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; - req->cnt -= req_cnt; - wmb(); - - /* Adjust ring index. */ - req->ring_index++; - if (req->ring_index == req->length) { - req->ring_index = 0; - req->ring_ptr = req->ring; - } else - req->ring_ptr++; - - sp->flags |= SRB_DMA_VALID; - - /* Set chip new ring index. */ - /* write, read and verify logic */ - dbval = dbval | (req->id << 8) | (req->ring_index << 16); - if (ql2xdbwr) - qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); - else { - WRT_REG_DWORD( - (unsigned long __iomem *)ha->nxdb_wr_ptr, - dbval); - wmb(); - while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { - WRT_REG_DWORD( - (unsigned long __iomem *)ha->nxdb_wr_ptr, - dbval); - wmb(); - } - } - - /* Manage unprocessed RIO/ZIO commands in response queue. */ - if (vha->flags.process_response_queue && - rsp->ring_ptr->signature != RESPONSE_PROCESSED) - qla24xx_process_response_queue(vha, rsp); - - spin_unlock_irqrestore(&ha->hardware_lock, flags); - return QLA_SUCCESS; - -queuing_error_fcp_cmnd: - dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, ctx->fcp_cmnd_dma); -queuing_error: - if (tot_dsds) - scsi_dma_unmap(cmd); - - if (sp->ctx) { - mempool_free(sp->ctx, ha->ctx_mempool); - sp->ctx = NULL; - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return QLA_FUNCTION_FAILED; -} - static uint32_t * qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, uint32_t length) @@ -3268,9 +2790,9 @@ qla82xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, } void -qla82xx_start_iocbs(srb_t *sp) +qla82xx_start_iocbs(scsi_qla_host_t *vha) { - struct qla_hw_data *ha = sp->fcport->vha->hw; + struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; struct device_reg_82xx __iomem *reg; uint32_t dbval; -- cgit From a00f6296aaf92ebe89c72eb98c440410992a33c4 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 18 Nov 2011 09:03:19 -0800 Subject: [SCSI] qla2xxx: Implement FCP priority tagging for 82xx adapters. This provides a capability to set a priority in the FCP packet. Signed-off-by: Saurav Kashyap Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 2 +- drivers/scsi/qla2xxx/qla_init.c | 7 ++++++- drivers/scsi/qla2xxx/qla_iocb.c | 9 +++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 371d0de7e30b..c0bc0c6f084d 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -102,7 +102,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) bsg_job->reply->reply_payload_rcv_len = 0; - if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))) { + if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA82XX(ha))) { ret = -EINVAL; goto exit_fcp_prio_cfg; } diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ec73cc191273..05931e6469aa 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5642,6 +5642,11 @@ qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport) if (priority < 0) return QLA_FUNCTION_FAILED; + if (IS_QLA82XX(vha->hw)) { + fcport->fcp_prio = priority & 0xf; + return QLA_SUCCESS; + } + ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb); if (ret == QLA_SUCCESS) { if (fcport->fcp_prio != priority) @@ -5650,7 +5655,7 @@ qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport) "port_id=%02x%02x%02x.\n", priority, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); - fcport->fcp_prio = priority; + fcport->fcp_prio = priority & 0xf; } else ql_dbg(ql_dbg_user, vha, 0x704f, "Unable to update FCP_CMND priority - ret=0x%x for " diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d2cc0ccfc202..841ffb34d416 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2432,6 +2432,11 @@ sufficient_dsds: } } + /* Populate the FCP_PRIO. */ + if (ha->flags.fcp_prio_enabled) + ctx->fcp_cmnd->task_attribute |= + sp->fcport->fcp_prio << 3; + memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); fcp_dl = (uint32_t *)(ctx->fcp_cmnd->cdb + 16 + @@ -2501,6 +2506,10 @@ sufficient_dsds: } } + /* Populate the FCP_PRIO. */ + if (ha->flags.fcp_prio_enabled) + cmd_pkt->task |= sp->fcport->fcp_prio << 3; + /* Load SCSI command packet. */ memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len); host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb)); -- cgit From 5780790ee6836ad64648c0905fcf15e073aad19b Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 18 Nov 2011 09:03:20 -0800 Subject: [SCSI] qla2xxx: Ensure there's enough request-queue space for passthru IOCBs. The driver should ensure there's a sufficient number of IOCBs to satisfy the number of scatter-gather entries specified in the command. Add a 'count' to the control structure, srb_ctx, to use in qla2x00_alloc_iocbs(). Signed-off-by: Andrew Vasquez Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 16 ++++++++++++++++ drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 1 + drivers/scsi/qla2xxx/qla_iocb.c | 11 +++++++++-- 4 files changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index c0bc0c6f084d..b1d0f936bf2d 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -31,6 +31,7 @@ qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size) memset(sp, 0, sizeof(*sp)); sp->fcport = fcport; sp->ctx = ctx; + ctx->iocbs = 1; done: return sp; } @@ -389,6 +390,20 @@ done: return rval; } +inline uint16_t +qla24xx_calc_ct_iocbs(uint16_t dsds) +{ + uint16_t iocbs; + + iocbs = 1; + if (dsds > 2) { + iocbs += (dsds - 2) / 5; + if ((dsds - 2) % 5) + iocbs++; + } + return iocbs; +} + static int qla2x00_process_ct(struct fc_bsg_job *bsg_job) { @@ -489,6 +504,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) ct = sp->ctx; ct->type = SRB_CT_CMD; ct->name = "bsg_ct"; + ct->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt); ct->u.bsg_job = bsg_job; ql_dbg(ql_dbg_user, vha, 0x7016, diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index d046db1a2ded..a6a4eebce4a8 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -271,6 +271,7 @@ struct srb_iocb { struct srb_ctx { uint16_t type; char *name; + int iocbs; union { struct srb_iocb *iocb_cmd; struct fc_bsg_job *bsg_job; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 05931e6469aa..1fa067e053d2 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -111,6 +111,7 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, memset(sp, 0, sizeof(*sp)); sp->fcport = fcport; sp->ctx = ctx; + ctx->iocbs = 1; ctx->u.iocb_cmd = iocb; iocb->free = qla2x00_ctx_sp_free; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 841ffb34d416..55a96761b5a4 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1818,6 +1818,7 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp) uint32_t index, handle; request_t *pkt; uint16_t cnt, req_cnt; + struct srb_ctx *ctx; pkt = NULL; req_cnt = 1; @@ -1846,6 +1847,12 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp) req->outstanding_cmds[handle] = sp; sp->handle = handle; + /* Adjust entry-counts as needed. */ + if (sp->ctx) { + ctx = sp->ctx; + req_cnt = ctx->iocbs; + } + skip_cmd_array: /* Check for room on request queue. */ if (req->cnt < req_cnt) { @@ -2622,8 +2629,8 @@ qla2x00_start_sp(srb_t *sp) break; case SRB_CT_CMD: IS_FWI2_CAPABLE(ha) ? - qla24xx_ct_iocb(sp, pkt) : - qla2x00_ct_iocb(sp, pkt); + qla24xx_ct_iocb(sp, pkt) : + qla2x00_ct_iocb(sp, pkt); break; case SRB_ADISC_CMD: IS_FWI2_CAPABLE(ha) ? -- cgit From cba1e47f4d641459e05eacaaa50a26d5e3d28818 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 18 Nov 2011 09:03:21 -0800 Subject: [SCSI] qla2xxx: Move initialization of some variables before iospace_config. Some variables need to be initialized before we config PCI I/O config space or else strange firmware initialization errors may occur. Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d713bc387790..4ed1e4a96b95 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2027,6 +2027,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pdev->needs_freset = 1; } + ha->prev_topology = 0; + ha->init_cb_size = sizeof(init_cb_t); + ha->link_data_rate = PORT_SPEED_UNKNOWN; + ha->optrom_size = OPTROM_SIZE_2300; + /* Assign ISP specific operations. */ max_id = MAX_TARGETS_2200; if (IS_QLA2100(ha)) { @@ -2143,11 +2148,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql_log_pci(ql_log_info, pdev, 0x001d, "Found an ISP%04X irq %d iobase 0x%p.\n", pdev->device, pdev->irq, ha->iobase); - ha->prev_topology = 0; - ha->init_cb_size = sizeof(init_cb_t); - ha->link_data_rate = PORT_SPEED_UNKNOWN; - ha->optrom_size = OPTROM_SIZE_2300; - mutex_init(&ha->vport_lock); init_completion(&ha->mbx_cmd_comp); complete(&ha->mbx_cmd_comp); -- cgit From a6f9091876fc07990d243072b03238a1f87b32a0 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 18 Nov 2011 09:03:22 -0800 Subject: [SCSI] qla2xxx: Do not check for minidump when device state is QLA82XX_DEV_READY. Signed-off-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 24447ddb4b66..1c927acf5f08 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3275,7 +3275,6 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) switch (dev_state) { case QLA82XX_DEV_READY: - qla82xx_check_md_needed(vha); ha->flags.isp82xx_reset_owner = 0; goto exit; case QLA82XX_DEV_COLD: -- cgit From cd6dbb038a191b1bea34819de547f66a2187e309 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 20 Nov 2011 22:34:15 +0100 Subject: [SCSI] qla2xxx: remove redundant semicolon One ';' at the end of the return statement is enough. Signed-off-by: Jesper Juhl Acked-by: Chad Dupuis Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 1c927acf5f08..1cd46cd7ff90 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1055,7 +1055,7 @@ ql82xx_rom_lock_d(struct qla_hw_data *ha) "ROM lock failed.\n"); return -1; } - return 0;; + return 0; } static int -- cgit From 45bcf018d1a4779d592764ef57517c92589d55d7 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 28 Nov 2011 10:15:20 -0600 Subject: [SCSI] hpsa: Add IRQF_SHARED back in for the non-MSI(X) interrupt handler IRQF_SHARED is required for older controllers that don't support MSI(X) and which may end up sharing an interrupt. All the controllers hpsa normally supports have MSI(X) capability, but older controllers may be encountered via the hpsa_allow_any=1 module parameter. Also remove deprecated IRQF_DISABLED. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 865d452542be..594ce8316727 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4072,10 +4072,10 @@ static int hpsa_request_irq(struct ctlr_info *h, if (h->msix_vector || h->msi_vector) rc = request_irq(h->intr[h->intr_mode], msixhandler, - IRQF_DISABLED, h->devname, h); + 0, h->devname, h); else rc = request_irq(h->intr[h->intr_mode], intxhandler, - IRQF_DISABLED, h->devname, h); + IRQF_SHARED, h->devname, h); if (rc) { dev_err(&h->pdev->dev, "unable to get irq %d for %s\n", h->intr[h->intr_mode], h->devname); -- cgit From 7af0abbc2ffcae601ea14e39048901833528f104 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Mon, 28 Nov 2011 15:39:55 +0100 Subject: [SCSI] hpsa: add the Smart Array 5i to the kdump blacklist The '5i' controller freezes when a kdump is attemted. This patch admits it and adds the controller to the unresetable list. Signed-off-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 594ce8316727..5140f5d0fd6b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -293,12 +293,14 @@ static u32 unresettable_controller[] = { 0x3215103C, /* Smart Array E200i */ 0x3237103C, /* Smart Array E500 */ 0x323D103C, /* Smart Array P700m */ + 0x40800E11, /* Smart Array 5i */ 0x409C0E11, /* Smart Array 6400 */ 0x409D0E11, /* Smart Array 6400 EM */ }; /* List of controllers which cannot even be soft reset */ static u32 soft_unresettable_controller[] = { + 0x40800E11, /* Smart Array 5i */ /* Exclude 640x boards. These are two pci devices in one slot * which share a battery backed cache module. One controls the * cache, the other accesses the cache through the one that controls -- cgit From 4053a4be525d3441cad6cd1ae207177f03eb9ce7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 26 Sep 2011 09:23:37 +0300 Subject: [SCSI] be2iscsi: cleanup a min_t() call "sense_len" was declared as int type but actually it only stores a u16 value that comes from hardware. The cast to u16 in min_t() confuses static analysis because it truncates the int to u16 so I've fixed the declaration to reflect that "sense_len" is just a u16. Also there was a call to cpu_to_be16() which I've changed to be16_to_cpu(). The functions are equivalent, but obviously the hardware is big endian and we're doing the min_t() comparison on CPU endian values. This whole patch is just a cleanup and doesn't affect how the code works. Signed-off-by: Dan Carpenter Reviewed-by: Mike Christie Acked-by: Jayamohan Kallickal Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 379c696dac19..fc7c97d7e34d 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1105,7 +1105,6 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn, struct be_status_bhs *sts_bhs = (struct be_status_bhs *)io_task->cmd_bhs; struct iscsi_conn *conn = beiscsi_conn->conn; - unsigned int sense_len; unsigned char *sense; u32 resid = 0, exp_cmdsn, max_cmdsn; u8 rsp, status, flags; @@ -1153,9 +1152,11 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn, } if (status == SAM_STAT_CHECK_CONDITION) { + u16 sense_len; unsigned short *slen = (unsigned short *)sts_bhs->sense_info; + sense = sts_bhs->sense_info + sizeof(unsigned short); - sense_len = cpu_to_be16(*slen); + sense_len = be16_to_cpu(*slen); memcpy(task->sc->sense_buffer, sense, min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE)); } -- cgit From 845a0e40afb77bebdbda353b44ebf48784aa51f4 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:42:04 +0530 Subject: [SCSI] mpt2sas: Better handling DEAD IOC (PCI-E LInk down) error condition Detection of Dead IOC has been done in fault_reset_work thread. If IOC Doorbell is 0xFFFFFFFF, it will be detected as non-operation/DEAD IOC. When a DEAD IOC is detected, the code is modified to remove that IOC and all its attached devices from OS. The PCI layer API pci_remove_bus_device() is called to remove the dead IOC. Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 59 ++++++++++++++++++++++++++++++++++++ drivers/scsi/mpt2sas/mpt2sas_base.h | 3 ++ drivers/scsi/mpt2sas/mpt2sas_scsih.c | 1 + 3 files changed, 63 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index beda04a8404b..c041cc70a25f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include "mpt2sas_base.h" @@ -120,9 +121,33 @@ _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) ioc->fwfault_debug = mpt2sas_fwfault_debug; return 0; } + module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug, param_get_int, &mpt2sas_fwfault_debug, 0644); +/** + * mpt2sas_remove_dead_ioc_func - kthread context to remove dead ioc + * @arg: input argument, used to derive ioc + * + * Return 0 if controller is removed from pci subsystem. + * Return -1 for other case. + */ +static int mpt2sas_remove_dead_ioc_func(void *arg) +{ + struct MPT2SAS_ADAPTER *ioc = (struct MPT2SAS_ADAPTER *)arg; + struct pci_dev *pdev; + + if ((ioc == NULL)) + return -1; + + pdev = ioc->pdev; + if ((pdev == NULL)) + return -1; + pci_remove_bus_device(pdev); + return 0; +} + + /** * _base_fault_reset_work - workq handling ioc fault conditions * @work: input argument, used to derive ioc @@ -138,6 +163,7 @@ _base_fault_reset_work(struct work_struct *work) unsigned long flags; u32 doorbell; int rc; + struct task_struct *p; spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); if (ioc->shost_recovery) @@ -145,6 +171,39 @@ _base_fault_reset_work(struct work_struct *work) spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); doorbell = mpt2sas_base_get_iocstate(ioc, 0); + if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) { + printk(MPT2SAS_INFO_FMT "%s : SAS host is non-operational !!!!\n", + ioc->name, __func__); + + /* + * Call _scsih_flush_pending_cmds callback so that we flush all + * pending commands back to OS. This call is required to aovid + * deadlock at block layer. Dead IOC will fail to do diag reset, + * and this call is safe since dead ioc will never return any + * command back from HW. + */ + ioc->schedule_dead_ioc_flush_running_cmds(ioc); + /* + * Set remove_host flag early since kernel thread will + * take some time to execute. + */ + ioc->remove_host = 1; + /*Remove the Dead Host */ + p = kthread_run(mpt2sas_remove_dead_ioc_func, ioc, + "mpt2sas_dead_ioc_%d", ioc->id); + if (IS_ERR(p)) { + printk(MPT2SAS_ERR_FMT + "%s: Running mpt2sas_dead_ioc thread failed !!!!\n", + ioc->name, __func__); + } else { + printk(MPT2SAS_ERR_FMT + "%s: Running mpt2sas_dead_ioc thread success !!!!\n", + ioc->name, __func__); + } + + return; /* don't rearm timer */ + } + if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 3c3babc7d260..61e5b2400aa8 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -623,6 +623,7 @@ enum mutex_type { TM_MUTEX_ON = 1, }; +typedef void (*MPT2SAS_FLUSH_RUNNING_CMDS)(struct MPT2SAS_ADAPTER *ioc); /** * struct MPT2SAS_ADAPTER - per adapter struct * @list: ioc_list @@ -665,6 +666,7 @@ enum mutex_type { * @msix_vector_count: number msix vectors * @cpu_msix_table: table for mapping cpus to msix index * @cpu_msix_table_sz: table size + * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands * @scsi_io_cb_idx: shost generated commands * @tm_cb_idx: task management commands * @scsih_cb_idx: scsih internal commands @@ -816,6 +818,7 @@ struct MPT2SAS_ADAPTER { resource_size_t **reply_post_host_index; u16 cpu_msix_table_sz; u32 ioc_reset_count; + MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; /* internal commands, callback index */ u8 scsi_io_cb_idx; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index d570573b7963..0b6b6b44e362 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -7928,6 +7928,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx; ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; ioc->logging_level = logging_level; + ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; /* misc semaphores and spin locks */ mutex_init(&ioc->reset_in_progress_mutex); spin_lock_init(&ioc->ioc_reset_in_progress_lock); -- cgit From 3ade1ca7ac16a9c5cf5883d6f04e340562c17148 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:42:40 +0530 Subject: [SCSI] mpt2sas: When IOs are terminated, update the result to DID_SOFT_ERROR to avoid infinite resets Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 0b6b6b44e362..5060634f7651 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -4485,6 +4485,8 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) scmd->result = DID_TRANSPORT_DISRUPTED << 16; goto out; } + scmd->result = DID_SOFT_ERROR << 16; + break; case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: scmd->result = DID_RESET << 16; -- cgit From 70e73f9945f80a5ad469d4d21b32209218aa51ac Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:43:00 +0530 Subject: [SCSI] mpt2sas: Adding support for customer specific branding Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 4 ++++ drivers/scsi/mpt2sas/mpt2sas_base.h | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index c041cc70a25f..0cca61def30a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1975,6 +1975,10 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc) printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, MPT2SAS_INTEL_RMS2LL040_BRANDING); break; + case MPT2SAS_INTEL_RAMSDALE_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RAMSDALE_BRANDING); + break; default: break; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 61e5b2400aa8..c19982b3e8b4 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -163,14 +163,15 @@ "Intel Integrated RAID Module RMS2LL040" #define MPT2SAS_INTEL_RS25GB008_BRANDING \ "Intel(R) RAID Controller RS25GB008" - +#define MPT2SAS_INTEL_RAMSDALE_BRANDING \ + "Intel 720 Series SSD" /* * Intel HBA SSDIDs */ #define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E #define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F #define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000 - +#define MPT2SAS_INTEL_RAMSDALE_SSDID 0x3700 /* * HP HBA branding -- cgit From c1bc0704e52f200bc747c6bddb970a3686e230ab Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:43:37 +0530 Subject: [SCSI] mpt2sas: MPI next revision header update 1) Added product specific range of ImageType macros for the Extended Image Header. 2) Added Flags field and related defines to MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST to support automatic reserve/release and page addressing. Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpi/mpi2.h | 9 ++++++--- drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h | 12 ++++++------ drivers/scsi/mpt2sas/mpi/mpi2_ioc.h | 28 +++++++++++++++++----------- drivers/scsi/mpt2sas/mpi/mpi2_tool.h | 9 +++++++-- 4 files changed, 36 insertions(+), 22 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h index 8dc1b32918dd..985913304c3f 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2.h @@ -8,7 +8,7 @@ * scatter/gather formats. * Creation Date: June 21, 2006 * - * mpi2.h Version: 02.00.20 + * mpi2.h Version: 02.00.21 * * Version History * --------------- @@ -69,6 +69,7 @@ * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT. * Added MPI2_FUNCTION_SEND_HOST_MESSAGE. * 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT. + * 05-25-11 02.00.21 Bumped MPI2_HEADER_VERSION_UNIT. * -------------------------------------------------------------------------- */ @@ -94,7 +95,7 @@ #define MPI2_VERSION_02_00 (0x0200) /* versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x14) +#define MPI2_HEADER_VERSION_UNIT (0x15) #define MPI2_HEADER_VERSION_DEV (0x00) #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) @@ -1073,8 +1074,10 @@ typedef struct _MPI2_IEEE_SGE_UNION #define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) #define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) /* IEEE Simple Element only */ -#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR (0x03) +#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR (0x03) /* IEEE Chain Element only */ +#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR \ + (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR) /* typo in name */ /**************************************************************************** * IEEE SGE operation Macros diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h index cfd95b4e3004..d237ab8028c8 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h @@ -6,7 +6,7 @@ * Title: MPI Configuration messages and pages * Creation Date: November 10, 2006 * - * mpi2_cnfg.h Version: 02.00.19 + * mpi2_cnfg.h Version: 02.00.20 * * Version History * --------------- @@ -140,6 +140,7 @@ * Added SASNotifyPrimitiveMasks field to * MPI2_CONFIG_PAGE_IOC_7. * 03-09-11 02.00.19 Fixed IO Unit Page 10 (to match the spec). + * 05-25-11 02.00.20 Cleaned up a few comments. * -------------------------------------------------------------------------- */ @@ -2321,13 +2322,12 @@ typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1 /* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ -/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ - /* values for SAS Expander Page 1 DiscoveryInfo field */ #define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) #define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) #define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) +/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ /**************************************************************************** * SAS Device Config Pages @@ -2447,6 +2447,8 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 #define MPI2_SASPHY0_PAGEVERSION (0x03) +/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ + /* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ /* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ @@ -2454,12 +2456,10 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 /* values for SAS PHY Page 0 Flags field */ #define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) -/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ +/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */ /* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ -/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */ - /* SAS PHY Page 1 */ diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h index 93d9b6956d05..7b53be83e7e3 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h @@ -6,7 +6,7 @@ * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: October 11, 2006 * - * mpi2_ioc.h Version: 02.00.17 + * mpi2_ioc.h Version: 02.00.18 * * Version History * --------------- @@ -110,6 +110,10 @@ * Added Temperature Threshold Event. * Added Host Message Event. * Added Send Host Message request and reply. + * 05-25-11 02.00.18 For Extended Image Header, added + * MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and + * MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines. + * Deprecated MPI2_EXT_IMAGE_TYPE_MAX define. * -------------------------------------------------------------------------- */ @@ -1366,16 +1370,18 @@ typedef struct _MPI2_EXT_IMAGE_HEADER #define MPI2_EXT_IMAGE_HEADER_SIZE (0x40) /* defines for the ImageType field */ -#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) -#define MPI2_EXT_IMAGE_TYPE_FW (0x01) -#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03) -#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04) -#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05) -#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06) -#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) -#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) - -#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MEGARAID) +#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) +#define MPI2_EXT_IMAGE_TYPE_FW (0x01) +#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03) +#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04) +#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05) +#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06) +#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) +#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) +#define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80) +#define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF) +#define MPI2_EXT_IMAGE_TYPE_MAX \ + (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC) /* deprecated */ diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h index 2a4bceda364b..3cbe677c6886 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h @@ -6,7 +6,7 @@ * Title: MPI diagnostic tool structures and definitions * Creation Date: March 26, 2007 * - * mpi2_tool.h Version: 02.00.06 + * mpi2_tool.h Version: 02.00.07 * * Version History * --------------- @@ -25,6 +25,8 @@ * 05-12-10 02.00.05 Added Diagnostic Data Upload tool. * 08-11-10 02.00.06 Added defines that were missing for Diagnostic Buffer * Post Request. + * 05-25-11 02.00.07 Added Flags field and related defines to + * MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST. * -------------------------------------------------------------------------- */ @@ -181,7 +183,7 @@ typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST { U8 DevIndex; /* 0x14 */ U8 Action; /* 0x15 */ U8 SGLFlags; /* 0x16 */ - U8 Reserved7; /* 0x17 */ + U8 Flags; /* 0x17 */ U16 TxDataLength; /* 0x18 */ U16 RxDataLength; /* 0x1A */ U32 Reserved8; /* 0x1C */ @@ -205,6 +207,9 @@ typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST { /* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ +/* values for the Flags field */ +#define MPI2_TOOL_ISTWI_FLAG_AUTO_RESERVE_RELEASE (0x80) +#define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK (0x07) /* Toolbox ISTWI Read Write Tool reply message */ typedef struct _MPI2_TOOLBOX_ISTWI_REPLY { -- cgit From 23edb6e71696a5da9c5f3987d22221e12370dbce Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:43:50 +0530 Subject: [SCSI] mpt2sas: Do not set sas_device->starget to NULL from the slave_destroy callback when all the LUNS have been deleted If the sas_device->starget to NULL from slave_destroy callback for LUN=1 even though LUN=0 exist, results in entire target getting deleted. To resolve the issue, the driver should only set sas_device->starget to NULL when all the LUNS have been deleted from the slave_destroy. Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 5060634f7651..a9efc4551086 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -612,13 +612,17 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, if (!mpt2sas_transport_port_add(ioc, sas_device->handle, sas_device->sas_address_parent)) { _scsih_sas_device_remove(ioc, sas_device); - } else if (!sas_device->starget) { - if (!ioc->is_driver_loading) - mpt2sas_transport_port_remove(ioc, - sas_device->sas_address, - sas_device->sas_address_parent); - _scsih_sas_device_remove(ioc, sas_device); - } + } else if (!sas_device->starget) { + /* When asyn scanning is enabled, its not possible to remove + * devices while scanning is turned on due to an oops in + * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start() + */ + if (!ioc->is_driver_loading) + mpt2sas_transport_port_remove(ioc, + sas_device->sas_address, + sas_device->sas_address_parent); + _scsih_sas_device_remove(ioc, sas_device); + } } /** @@ -1449,7 +1453,7 @@ _scsih_slave_destroy(struct scsi_device *sdev) spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, sas_target_priv_data->sas_address); - if (sas_device) + if (sas_device && !sas_target_priv_data->num_luns) sas_device->starget = NULL; spin_unlock_irqrestore(&ioc->sas_device_lock, flags); } -- cgit From f01690d31d905d46aaf2df8021a33231a71cd744 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:43:58 +0530 Subject: [SCSI] mpt2sas: Rearrange the the code so that the completion queues are initialized prior to sending the request to controller firmware Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 6 +++--- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 8 ++++---- drivers/scsi/mpt2sas/mpt2sas_transport.c | 9 +++++---- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 0cca61def30a..4a8706867700 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3199,8 +3199,8 @@ mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) ioc->ioc_link_reset_in_progress = 1; - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->base_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, msecs_to_jiffies(10000)); if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || @@ -3301,8 +3301,8 @@ mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, request = mpt2sas_base_get_msg_frame(ioc, smid); ioc->base_cmds.smid = smid; memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->base_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, msecs_to_jiffies(10000)); if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { @@ -3809,8 +3809,8 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) mpi_request->EventMasks[i] = cpu_to_le32(ioc->event_masks[i]); - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->base_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { printk(MPT2SAS_ERR_FMT "%s: timeout\n", diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index aabcb911706e..7fceb899029e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -818,6 +818,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, _ctl_display_some_debug(ioc, smid, "ctl_request", NULL); #endif + init_completion(&ioc->ctl_cmds.done); switch (mpi_request->Function) { case MPI2_FUNCTION_SCSI_IO_REQUEST: case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: @@ -903,7 +904,6 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, timeout = MPT2_IOCTL_DEFAULT_TIMEOUT; else timeout = karg.timeout; - init_completion(&ioc->ctl_cmds.done); timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, timeout*HZ); if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { @@ -1477,8 +1477,8 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc, mpi_request->ProductSpecific[i] = cpu_to_le32(ioc->product_specific[buffer_type][i]); - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->ctl_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); @@ -1821,8 +1821,8 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->ctl_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); @@ -2095,8 +2095,8 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->ctl_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 230732241aa2..831047466a5a 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -398,8 +398,8 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - " "send to sas_addr(0x%016llx)\n", ioc->name, (unsigned long long)sas_address)); - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->transport_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); @@ -1184,8 +1184,8 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc, dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - " "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name, (unsigned long long)phy->identify.sas_address, phy->number)); - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->transport_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); @@ -1509,8 +1509,9 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc, "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name, (unsigned long long)phy->identify.sas_address, phy->number, phy_operation)); - mpt2sas_base_put_smid_default(ioc, smid); + init_completion(&ioc->transport_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); @@ -1949,8 +1950,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - " "sending smp request\n", ioc->name, __func__)); - mpt2sas_base_put_smid_default(ioc, smid); init_completion(&ioc->transport_cmds.done); + mpt2sas_base_put_smid_default(ioc, smid); timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); -- cgit From 7509d6bb955d08c4125bcf44650b2df839470bf8 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:44:10 +0530 Subject: [SCSI] mpt2sas: Bump driver version to 11.100.00.00 Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index c19982b3e8b4..b3b03bb8ab50 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -69,8 +69,8 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation " #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "10.100.00.00" -#define MPT2SAS_MAJOR_VERSION 10 +#define MPT2SAS_DRIVER_VERSION "11.100.00.00" +#define MPT2SAS_MAJOR_VERSION 11 #define MPT2SAS_MINOR_VERSION 100 #define MPT2SAS_BUILD_VERSION 00 #define MPT2SAS_RELEASE_VERSION 00 -- cgit From ba96bd0b1d4a4e11f23671e1f375a5c8f46b0fe7 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:51:55 +0530 Subject: [SCSI] mpt2sas: Support for greater than 2TB capacity WarpDrive The driver is modified to allow access to the greater than 2TB WarpDrive and properly handle direct-io mapping for WarpDrive volumes greater than 2TB. Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 2 + drivers/scsi/mpt2sas/mpt2sas_scsih.c | 115 ++++++++++++++++++++++------------- 2 files changed, 74 insertions(+), 43 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index b3b03bb8ab50..88ead5ed2afc 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -374,6 +374,7 @@ struct _sas_device { * @percent_complete: resync percent complete * @direct_io_enabled: Whether direct io to PDs are allowed or not * @stripe_exponent: X where 2powX is the stripe sz in blocks + * @block_exponent: X where 2powX is the block sz in bytes * @max_lba: Maximum number of LBA in the volume * @stripe_sz: Stripe Size of the volume * @device_info: Device info of the volume member disk @@ -395,6 +396,7 @@ struct _raid_device { u8 percent_complete; u8 direct_io_enabled; u8 stripe_exponent; + u8 block_exponent; u64 max_lba; u32 stripe_sz; u32 device_info; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index a9efc4551086..ba8171fe17ef 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -1780,11 +1780,9 @@ _scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t mpi_reply; u16 sz; u8 num_pds, count; - u64 mb = 1024 * 1024; - u64 tb_2 = 2 * mb * mb; - u64 capacity; - u32 stripe_sz; - u8 i, stripe_exp; + unsigned long stripe_sz, block_sz; + u8 stripe_exp, block_exp; + u64 dev_max_lba; if (!ioc->is_warpdrive) return; @@ -1848,51 +1846,57 @@ _scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc, vol_pg0->PhysDisk[count].PhysDiskNum); goto out_error; } + /* Disable direct I/O if member drive lba exceeds 4 bytes */ + dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA); + if (dev_max_lba >> 32) { + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is " + "disabled for the drive with handle(0x%04x) member" + "handle (0x%04x) unsupported max lba 0x%016llx\n", + ioc->name, raid_device->handle, + le16_to_cpu(pd_pg0.DevHandle), + (unsigned long long)dev_max_lba); + goto out_error; + } + raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle); } /* * Assumption for WD: Direct I/O is not supported if the volume is - * not RAID0, if the stripe size is not 64KB, if the block size is - * not 512 and if the volume size is >2TB + * not RAID0 */ - if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0 || - le16_to_cpu(vol_pg0->BlockSize) != 512) { + if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) { printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " "for the drive with handle(0x%04x): type=%d, " "s_sz=%uK, blk_size=%u\n", ioc->name, raid_device->handle, raid_device->volume_type, - le32_to_cpu(vol_pg0->StripeSize)/2, + (le32_to_cpu(vol_pg0->StripeSize) * + le16_to_cpu(vol_pg0->BlockSize)) / 1024, le16_to_cpu(vol_pg0->BlockSize)); goto out_error; } - capacity = (u64) le16_to_cpu(vol_pg0->BlockSize) * - (le64_to_cpu(vol_pg0->MaxLBA) + 1); - - if (capacity > tb_2) { + stripe_sz = le32_to_cpu(vol_pg0->StripeSize); + stripe_exp = find_first_bit(&stripe_sz, 32); + if (stripe_exp == 32) { printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " - "for the drive with handle(0x%04x) since drive sz > 2TB\n", - ioc->name, raid_device->handle); + "for the drive with handle(0x%04x) invalid stripe sz %uK\n", + ioc->name, raid_device->handle, + (le32_to_cpu(vol_pg0->StripeSize) * + le16_to_cpu(vol_pg0->BlockSize)) / 1024); goto out_error; } - - stripe_sz = le32_to_cpu(vol_pg0->StripeSize); - stripe_exp = 0; - for (i = 0; i < 32; i++) { - if (stripe_sz & 1) - break; - stripe_exp++; - stripe_sz >>= 1; - } - if (i == 32) { + raid_device->stripe_exponent = stripe_exp; + block_sz = le16_to_cpu(vol_pg0->BlockSize); + block_exp = find_first_bit(&block_sz, 16); + if (block_exp == 16) { printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled " - "for the drive with handle(0x%04x) invalid stripe sz %uK\n", + "for the drive with handle(0x%04x) invalid block sz %u\n", ioc->name, raid_device->handle, - le32_to_cpu(vol_pg0->StripeSize)/2); + le16_to_cpu(vol_pg0->BlockSize)); goto out_error; } - raid_device->stripe_exponent = stripe_exp; + raid_device->block_exponent = block_exp; raid_device->direct_io_enabled = 1; printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive" @@ -3808,8 +3812,9 @@ _scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, { u32 v_lba, p_lba, stripe_off, stripe_unit, column, io_size; u32 stripe_sz, stripe_exp; - u8 num_pds, *cdb_ptr, *tmp_ptr, *lba_ptr1, *lba_ptr2; + u8 num_pds, *cdb_ptr, i; u8 cdb0 = scmd->cmnd[0]; + u64 v_llba; /* * Try Direct I/O to RAID memeber disks @@ -3820,15 +3825,11 @@ _scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, if ((cdb0 < READ_16) || !(cdb_ptr[2] | cdb_ptr[3] | cdb_ptr[4] | cdb_ptr[5])) { - io_size = scsi_bufflen(scmd) >> 9; + io_size = scsi_bufflen(scmd) >> + raid_device->block_exponent; + i = (cdb0 < READ_16) ? 2 : 6; /* get virtual lba */ - lba_ptr1 = lba_ptr2 = (cdb0 < READ_16) ? &cdb_ptr[2] : - &cdb_ptr[6]; - tmp_ptr = (u8 *)&v_lba + 3; - *tmp_ptr-- = *lba_ptr1++; - *tmp_ptr-- = *lba_ptr1++; - *tmp_ptr-- = *lba_ptr1++; - *tmp_ptr = *lba_ptr1; + v_lba = be32_to_cpu(*(__be32 *)(&cdb_ptr[i])); if (((u64)v_lba + (u64)io_size - 1) <= (u32)raid_device->max_lba) { @@ -3847,11 +3848,39 @@ _scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, mpi_request->DevHandle = cpu_to_le16(raid_device-> pd_handle[column]); - tmp_ptr = (u8 *)&p_lba + 3; - *lba_ptr2++ = *tmp_ptr--; - *lba_ptr2++ = *tmp_ptr--; - *lba_ptr2++ = *tmp_ptr--; - *lba_ptr2 = *tmp_ptr; + (*(__be32 *)(&cdb_ptr[i])) = + cpu_to_be32(p_lba); + /* + * WD: To indicate this I/O is directI/O + */ + _scsih_scsi_direct_io_set(ioc, smid, 1); + } + } + } else { + io_size = scsi_bufflen(scmd) >> + raid_device->block_exponent; + /* get virtual lba */ + v_llba = be64_to_cpu(*(__be64 *)(&cdb_ptr[2])); + + if ((v_llba + (u64)io_size - 1) <= + raid_device->max_lba) { + stripe_sz = raid_device->stripe_sz; + stripe_exp = raid_device->stripe_exponent; + stripe_off = (u32) (v_llba & (stripe_sz - 1)); + + /* Check whether IO falls within a stripe */ + if ((stripe_off + io_size) <= stripe_sz) { + num_pds = raid_device->num_pds; + p_lba = (u32)(v_llba >> stripe_exp); + stripe_unit = p_lba / num_pds; + column = p_lba % num_pds; + p_lba = (stripe_unit << stripe_exp) + + stripe_off; + mpi_request->DevHandle = + cpu_to_le16(raid_device-> + pd_handle[column]); + (*(__be64 *)(&cdb_ptr[2])) = + cpu_to_be64((u64)p_lba); /* * WD: To indicate this I/O is directI/O */ -- cgit From 9ac49d3a510c2686545d4e0520fdc79b341b5794 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:52:08 +0530 Subject: [SCSI] mpt2sas: Increase max transfer support from 4MB to 16MB Increase max transfer support from 4MB to 16MB. This is done by changing the shost->max_sector from 8192 to 32767 Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index ba8171fe17ef..06117207f601 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -99,7 +99,7 @@ MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info " static ushort max_sectors = 0xFFFF; module_param(max_sectors, ushort, 0); -MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 8192 default=8192"); +MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767"); /* scsi-mid layer global parmeter is max_report_luns, which is 511 */ #define MPT2SAS_MAX_LUN (16895) @@ -7453,7 +7453,7 @@ static struct scsi_host_template scsih_driver_template = { .can_queue = 1, .this_id = -1, .sg_tablesize = MPT2SAS_SG_DEPTH, - .max_sectors = 8192, + .max_sectors = 32767, .cmd_per_lun = 7, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = mpt2sas_host_attrs, @@ -7994,11 +7994,11 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(MPT2SAS_WARN_FMT "Invalid value %d passed " "for max_sectors, range is 64 to 8192. Assigning " "value of 64.\n", ioc->name, max_sectors); - } else if (max_sectors > 8192) { - shost->max_sectors = 8192; + } else if (max_sectors > 32767) { + shost->max_sectors = 32767; printk(MPT2SAS_WARN_FMT "Invalid value %d passed " "for max_sectors, range is 64 to 8192. Assigning " - "default value of 8192.\n", ioc->name, + "default value of 32767.\n", ioc->name, max_sectors); } else { shost->max_sectors = max_sectors & 0xFFFE; -- cgit From 8bad3055e902a16b7cf47777fc3e78a965d0b57a Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:52:42 +0530 Subject: [SCSI] mpt2sas: Added support for customer specific branding Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 16 ++++++++++++++++ drivers/scsi/mpt2sas/mpt2sas_base.h | 12 ++++++++++++ 2 files changed, 28 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 4a8706867700..c0526878a337 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1988,6 +1988,22 @@ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc) printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, MPT2SAS_INTEL_RS25GB008_BRANDING); break; + case MPT2SAS_INTEL_RMS25JB080_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25JB080_BRANDING); + break; + case MPT2SAS_INTEL_RMS25JB040_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25JB040_BRANDING); + break; + case MPT2SAS_INTEL_RMS25KB080_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25KB080_BRANDING); + break; + case MPT2SAS_INTEL_RMS25KB040_SSDID: + printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, + MPT2SAS_INTEL_RMS25KB040_BRANDING); + break; default: break; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 88ead5ed2afc..f2b7e40f105c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -157,6 +157,14 @@ /* * Intel HBA branding */ +#define MPT2SAS_INTEL_RMS25JB080_BRANDING \ + "Intel(R) Integrated RAID Module RMS25JB080" +#define MPT2SAS_INTEL_RMS25JB040_BRANDING \ + "Intel(R) Integrated RAID Module RMS25JB040" +#define MPT2SAS_INTEL_RMS25KB080_BRANDING \ + "Intel(R) Integrated RAID Module RMS25KB080" +#define MPT2SAS_INTEL_RMS25KB040_BRANDING \ + "Intel(R) Integrated RAID Module RMS25KB040" #define MPT2SAS_INTEL_RMS2LL080_BRANDING \ "Intel Integrated RAID Module RMS2LL080" #define MPT2SAS_INTEL_RMS2LL040_BRANDING \ @@ -168,6 +176,10 @@ /* * Intel HBA SSDIDs */ +#define MPT2SAS_INTEL_RMS25JB080_SSDID 0x3516 +#define MPT2SAS_INTEL_RMS25JB040_SSDID 0x3517 +#define MPT2SAS_INTEL_RMS25KB080_SSDID 0x3518 +#define MPT2SAS_INTEL_RMS25KB040_SSDID 0x3519 #define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E #define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F #define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000 -- cgit From a6affbd5ccbb45e03168996bae4a4d0abb780874 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:52:49 +0530 Subject: [SCSI] mpt2sas: MPI next revision header update 1)Removed Power Management Control option for PCIe link. 2)Added RAID Action for performing a compatibility check. Added product-specific range to RAID Action values. 3)Added PhysicalPort field to SAS Device Status Change Event data. 4)Added SpinupFlags field containing a Disable Spin-up bit to the SpinupGroupParameters fields of SAS IO Unit Page 4. Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpi/mpi2.h | 5 +-- drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h | 18 +++++++--- drivers/scsi/mpt2sas/mpi/mpi2_ioc.h | 23 +++++++------ drivers/scsi/mpt2sas/mpi/mpi2_raid.h | 67 ++++++++++++++++++++++++++++++++---- 4 files changed, 90 insertions(+), 23 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h index 985913304c3f..a01f0aa66f20 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2.h @@ -8,7 +8,7 @@ * scatter/gather formats. * Creation Date: June 21, 2006 * - * mpi2.h Version: 02.00.21 + * mpi2.h Version: 02.00.22 * * Version History * --------------- @@ -70,6 +70,7 @@ * Added MPI2_FUNCTION_SEND_HOST_MESSAGE. * 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT. * 05-25-11 02.00.21 Bumped MPI2_HEADER_VERSION_UNIT. + * 08-24-11 02.00.22 Bumped MPI2_HEADER_VERSION_UNIT. * -------------------------------------------------------------------------- */ @@ -95,7 +96,7 @@ #define MPI2_VERSION_02_00 (0x0200) /* versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x15) +#define MPI2_HEADER_VERSION_UNIT (0x16) #define MPI2_HEADER_VERSION_DEV (0x00) #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h index d237ab8028c8..3a023dad77a1 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h @@ -6,7 +6,7 @@ * Title: MPI Configuration messages and pages * Creation Date: November 10, 2006 * - * mpi2_cnfg.h Version: 02.00.20 + * mpi2_cnfg.h Version: 02.00.21 * * Version History * --------------- @@ -141,6 +141,12 @@ * MPI2_CONFIG_PAGE_IOC_7. * 03-09-11 02.00.19 Fixed IO Unit Page 10 (to match the spec). * 05-25-11 02.00.20 Cleaned up a few comments. + * 08-24-11 02.00.21 Marked the IO Unit Page 7 PowerManagementCapabilities + * for PCIe link as obsolete. + * Added SpinupFlags field containing a Disable Spin-up + * bit to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of + * SAS IO Unit Page 4. + * -------------------------------------------------------------------------- */ @@ -905,8 +911,8 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { #define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED (0x00000400) #define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED (0x00000200) #define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED (0x00000100) -#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) -#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) +#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) /* obsolete */ +#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) /* obsolete */ /* defines for IO Unit Page 7 IOCTemperatureUnits field */ #define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00) @@ -1971,10 +1977,14 @@ typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP { U8 MaxTargetSpinup; /* 0x00 */ U8 SpinupDelay; /* 0x01 */ - U16 Reserved1; /* 0x02 */ + U8 SpinupFlags; /* 0x02 */ + U8 Reserved1; /* 0x03 */ } MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP, Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t; +/* defines for SAS IO Unit Page 4 SpinupFlags */ +#define MPI2_SASIOUNIT4_SPINUP_DISABLE_FLAG (0x01) + /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to * one and check the value returned for NumPhys at runtime. diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h index 7b53be83e7e3..9a925c07a9ec 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h @@ -6,7 +6,7 @@ * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: October 11, 2006 * - * mpi2_ioc.h Version: 02.00.18 + * mpi2_ioc.h Version: 02.00.19 * * Version History * --------------- @@ -114,6 +114,9 @@ * MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and * MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines. * Deprecated MPI2_EXT_IMAGE_TYPE_MAX define. + * 08-24-11 02.00.19 Added PhysicalPort field to + * MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure. + * Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete. * -------------------------------------------------------------------------- */ @@ -582,7 +585,7 @@ typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE { U16 TaskTag; /* 0x00 */ U8 ReasonCode; /* 0x02 */ - U8 Reserved1; /* 0x03 */ + U8 PhysicalPort; /* 0x03 */ U8 ASC; /* 0x04 */ U8 ASCQ; /* 0x05 */ U16 DevHandle; /* 0x06 */ @@ -1574,7 +1577,7 @@ typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST { /* defines for the Feature field */ #define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01) #define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02) -#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) +#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) /* obsolete */ #define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04) #define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80) #define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF) @@ -1603,14 +1606,14 @@ typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST { /* parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */ /* Parameter1 indicates desired PCIe link speed using these defines */ -#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) -#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) -#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) +#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) /* obsolete */ +#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) /* obsolete */ +#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) /* obsolete */ /* Parameter2 indicates desired PCIe link width using these defines */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) /* obsolete */ +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) /* obsolete */ +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) /* obsolete */ +#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) /* obsolete */ /* Parameter3 and Parameter4 are reserved */ /* parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */ diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h index bd61a7b60a2b..0601612b875a 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h @@ -6,7 +6,7 @@ * Title: MPI Integrated RAID messages and structures * Creation Date: April 26, 2007 * - * mpi2_raid.h Version: 02.00.05 + * mpi2_raid.h Version: 02.00.06 * * Version History * --------------- @@ -23,6 +23,10 @@ * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of * VolumeCreationFlags and marked the old one as obsolete. * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define. + * 08-24-10 02.00.06 Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with + * related structures and defines. + * Added product-specific range to RAID Action values. + * -------------------------------------------------------------------------- */ @@ -176,7 +180,9 @@ typedef struct _MPI2_RAID_ACTION_REQUEST #define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20) #define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21) #define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22) - +#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK (0x23) +#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC (0x80) +#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC (0xFF) /* RAID Volume Creation Structure */ @@ -244,6 +250,23 @@ typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION Mpi2RaidOnlineCapacityExpansion_t, MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t; +/* RAID Compatibility Input Structure */ + +typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT { + U16 SourceDevHandle; /* 0x00 */ + U16 CandidateDevHandle; /* 0x02 */ + U32 Flags; /* 0x04 */ + U32 Reserved1; /* 0x08 */ + U32 Reserved2; /* 0x0C */ +} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT, +MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT, +Mpi2RaidCompatibilityInputStruct_t, +MPI2_POINTER pMpi2RaidCompatibilityInputStruct_t; + +/* defines for RAID Compatibility Structure Flags field */ +#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG (0x00000002) +#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG (0x00000001) + /* RAID Volume Indicator Structure */ @@ -263,15 +286,45 @@ typedef struct _MPI2_RAID_VOL_INDICATOR #define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003) #define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004) +/* RAID Compatibility Result Structure */ + +typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT { + U8 State; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U16 Reserved2; /* 0x02 */ + U32 GenericAttributes; /* 0x04 */ + U32 OEMSpecificAttributes; /* 0x08 */ + U32 Reserved3; /* 0x0C */ + U32 Reserved4; /* 0x10 */ +} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT, +MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT, +Mpi2RaidCompatibilityResultStruct_t, +MPI2_POINTER pMpi2RaidCompatibilityResultStruct_t; + +/* defines for RAID Compatibility Result Structure State field */ +#define MPI2_RAID_COMPAT_STATE_COMPATIBLE (0x00) +#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE (0x01) + +/* defines for RAID Compatibility Result Structure GenericAttributes field */ +#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR (0x00000010) + +#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK (0x0000000C) +#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE (0x00000008) +#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE (0x00000004) + +#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK (0x00000003) +#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL (0x00000002) +#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL (0x00000001) /* RAID Action Reply ActionData union */ typedef union _MPI2_RAID_ACTION_REPLY_DATA { - U32 Word[5]; - MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator; - U16 VolDevHandle; - U8 VolumeState; - U8 PhysDiskNum; + U32 Word[5]; + MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator; + U16 VolDevHandle; + U8 VolumeState; + U8 PhysDiskNum; + MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult; } MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA, Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t; -- cgit From 30c43282f3d347f47f9e05199d2b14f56f3f2837 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:52:56 +0530 Subject: [SCSI] mpt2sas: Release spinlock for the raid device list before blocking it Added code to release the spinlock that is used to protect the raid device list before calling a function that can block. The blocking was causing a reschedule, and subsequently it is tried to acquire the same lock, resulting in a panic (NMI Watchdog detecting a CPU lockup). Signed-off-by: Nagalakshmi Nandigama Cc: stable@kernel.org Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 06117207f601..8e2e9973df29 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -6749,6 +6749,7 @@ _scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid, } else sas_target_priv_data = NULL; raid_device->responding = 1; + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); starget_printk(KERN_INFO, raid_device->starget, "handle(0x%04x), wwid(0x%016llx)\n", handle, (unsigned long long)raid_device->wwid); @@ -6759,16 +6760,16 @@ _scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid, */ _scsih_init_warpdrive_properties(ioc, raid_device); if (raid_device->handle == handle) - goto out; + return; printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", raid_device->handle); raid_device->handle = handle; if (sas_target_priv_data) sas_target_priv_data->handle = handle; - goto out; + return; } } - out: + spin_unlock_irqrestore(&ioc->raid_device_lock, flags); } -- cgit From 4da7af9494b2f98a1503a2634059300c3e4615e6 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:53:02 +0530 Subject: [SCSI] mpt2sas: Do not retry a timed out direct IO for warpdrive When an I/O request to a WarpDrive is timed out by SML and if the I/O request to the WarpDrive is sent as direct I/O then the aborted direct I/O will be retried as normal Volume I/O and which results in failure of Target Reset and results in host reset. The fix is to not retry a failed IO to volume when the original IO was sent as direct IO with an ioc status MPI2_IOCSTATUS_SCSI_TASK_TERMINATED. Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 8e2e9973df29..fd1ba744b423 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -4436,11 +4436,14 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) scmd->result = DID_NO_CONNECT << 16; goto out; } + ioc_status = le16_to_cpu(mpi_reply->IOCStatus); /* * WARPDRIVE: If direct_io is set then it is directIO, * the failed direct I/O should be redirected to volume */ - if (_scsih_scsi_direct_io_get(ioc, smid)) { + if (_scsih_scsi_direct_io_get(ioc, smid) && + ((ioc_status & MPI2_IOCSTATUS_MASK) + != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) { spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); ioc->scsi_lookup[smid - 1].scmd = scmd; spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); @@ -4474,7 +4477,6 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt); - ioc_status = le16_to_cpu(mpi_reply->IOCStatus); if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) log_info = le32_to_cpu(mpi_reply->IOCLogInfo); else -- cgit From aff132d95ffe14eca96cab90597cdd010b457af7 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:53:08 +0530 Subject: [SCSI] mpt2sas : Fix for memory allocation error for large host credits The amount of memory required for tracking chain buffers is rather large, and when the host credit count is big, memory allocation failure occurs inside __get_free_pages. The fix is to limit the number of chains to 100,000. In addition, the number of host credits is limited to 30,000 IOs. However this limitation can be overridden this using the command line option max_queue_depth. The algorithm for calculating the reply_post_queue_depth is changed so that it is equal to (reply_free_queue_depth + 16), previously it was (reply_free_queue_depth * 2). Signed-off-by: Nagalakshmi Nandigama Cc: stable@kernel.org Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 83 ++++++++++++------------------------ drivers/scsi/mpt2sas/mpt2sas_scsih.c | 4 +- 2 files changed, 29 insertions(+), 58 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index c0526878a337..961b11ea8c04 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -66,6 +66,8 @@ static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ +#define MAX_HBA_QUEUE_DEPTH 30000 +#define MAX_CHAIN_DEPTH 100000 static int max_queue_depth = -1; module_param(max_queue_depth, int, 0); MODULE_PARM_DESC(max_queue_depth, " max controller queue depth "); @@ -2390,8 +2392,6 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) } if (ioc->chain_dma_pool) pci_pool_destroy(ioc->chain_dma_pool); - } - if (ioc->chain_lookup) { free_pages((ulong)ioc->chain_lookup, ioc->chain_pages); ioc->chain_lookup = NULL; } @@ -2409,9 +2409,7 @@ static int _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) { struct mpt2sas_facts *facts; - u32 queue_size, queue_diff; u16 max_sge_elements; - u16 num_of_reply_frames; u16 chains_needed_per_io; u32 sz, total_sz, reply_post_free_sz; u32 retry_sz; @@ -2438,7 +2436,8 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) max_request_credit = (max_queue_depth < facts->RequestCredit) ? max_queue_depth : facts->RequestCredit; else - max_request_credit = facts->RequestCredit; + max_request_credit = min_t(u16, facts->RequestCredit, + MAX_HBA_QUEUE_DEPTH); ioc->hba_queue_depth = max_request_credit; ioc->hi_priority_depth = facts->HighPriorityCredit; @@ -2479,50 +2478,25 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } ioc->chains_needed_per_io = chains_needed_per_io; - /* reply free queue sizing - taking into account for events */ - num_of_reply_frames = ioc->hba_queue_depth + 32; - - /* number of replies frames can't be a multiple of 16 */ - /* decrease number of reply frames by 1 */ - if (!(num_of_reply_frames % 16)) - num_of_reply_frames--; - - /* calculate number of reply free queue entries - * (must be multiple of 16) - */ - - /* (we know reply_free_queue_depth is not a multiple of 16) */ - queue_size = num_of_reply_frames; - queue_size += 16 - (queue_size % 16); - ioc->reply_free_queue_depth = queue_size; - - /* reply descriptor post queue sizing */ - /* this size should be the number of request frames + number of reply - * frames - */ - - queue_size = ioc->hba_queue_depth + num_of_reply_frames + 1; - /* round up to 16 byte boundary */ - if (queue_size % 16) - queue_size += 16 - (queue_size % 16); - - /* check against IOC maximum reply post queue depth */ - if (queue_size > facts->MaxReplyDescriptorPostQueueDepth) { - queue_diff = queue_size - - facts->MaxReplyDescriptorPostQueueDepth; + /* reply free queue sizing - taking into account for 64 FW events */ + ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; - /* round queue_diff up to multiple of 16 */ - if (queue_diff % 16) - queue_diff += 16 - (queue_diff % 16); - - /* adjust hba_queue_depth, reply_free_queue_depth, - * and queue_size - */ - ioc->hba_queue_depth -= (queue_diff / 2); - ioc->reply_free_queue_depth -= (queue_diff / 2); - queue_size = facts->MaxReplyDescriptorPostQueueDepth; + /* align the reply post queue on the next 16 count boundary */ + if (!ioc->reply_free_queue_depth % 16) + ioc->reply_post_queue_depth = ioc->reply_free_queue_depth + 16; + else + ioc->reply_post_queue_depth = ioc->reply_free_queue_depth + + 32 - (ioc->reply_free_queue_depth % 16); + if (ioc->reply_post_queue_depth > + facts->MaxReplyDescriptorPostQueueDepth) { + ioc->reply_post_queue_depth = min_t(u16, + (facts->MaxReplyDescriptorPostQueueDepth - + (facts->MaxReplyDescriptorPostQueueDepth % 16)), + (ioc->hba_queue_depth - (ioc->hba_queue_depth % 16))); + ioc->reply_free_queue_depth = ioc->reply_post_queue_depth - 16; + ioc->hba_queue_depth = ioc->reply_free_queue_depth - 64; } - ioc->reply_post_queue_depth = queue_size; + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " @@ -2608,15 +2582,12 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) "depth(%d)\n", ioc->name, ioc->request, ioc->scsiio_depth)); - /* loop till the allocation succeeds */ - do { - sz = ioc->chain_depth * sizeof(struct chain_tracker); - ioc->chain_pages = get_order(sz); - ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( - GFP_KERNEL, ioc->chain_pages); - if (ioc->chain_lookup == NULL) - ioc->chain_depth -= 100; - } while (ioc->chain_lookup == NULL); + ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH); + sz = ioc->chain_depth * sizeof(struct chain_tracker); + ioc->chain_pages = get_order(sz); + + ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( + GFP_KERNEL, ioc->chain_pages); ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev, ioc->request_sz, 16, 0); if (!ioc->chain_dma_pool) { diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index fd1ba744b423..8cd4ebb9349f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -1011,8 +1011,8 @@ _scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid) spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); if (list_empty(&ioc->free_chain_list)) { spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - printk(MPT2SAS_WARN_FMT "chain buffers not available\n", - ioc->name); + dfailprintk(ioc, printk(MPT2SAS_WARN_FMT "chain buffers not " + "available\n", ioc->name)); return NULL; } chain_req = list_entry(ioc->free_chain_list.next, -- cgit From dab2f6b80cfda6b0ab8b722f7f9e901f971513aa Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Thu, 1 Dec 2011 07:53:13 +0530 Subject: [SCSI] mpt2sas : Bump driver vesion to 12.100.00.00 Bump driver vesion to 12.100.00.00 Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index f2b7e40f105c..c7459fdc06cc 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -69,8 +69,8 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation " #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "11.100.00.00" -#define MPT2SAS_MAJOR_VERSION 11 +#define MPT2SAS_DRIVER_VERSION "12.100.00.00" +#define MPT2SAS_MAJOR_VERSION 12 #define MPT2SAS_MINOR_VERSION 100 #define MPT2SAS_BUILD_VERSION 00 #define MPT2SAS_RELEASE_VERSION 00 -- cgit From c24a1710d18d706ee2bbd87390868242f1a6d8d5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 30 Nov 2011 17:14:22 -0800 Subject: [SCSI] mpt2sas: Fix leak on mpt2sas_base_attach() error path Commit 911ae9434f83 ("[SCSI] mpt2sas: Added NUNA IO support in driver which uses multi-reply queue support of the HBA") added new allocations to the beginning of mpt2sas_base_attach(), which means directly returning an error on failure of mpt2sas_base_map_resources() will leak those allocations. Fix this by doing "goto out_free_resources" in this place too, as the rest of the function does. Signed-off-by: Roland Dreier Acked-by: "Nandigama, Nagalakshmi" Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 961b11ea8c04..65c377dc0279 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -4256,7 +4256,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) r = mpt2sas_base_map_resources(ioc); if (r) - return r; + goto out_free_resources; if (ioc->is_warpdrive) { ioc->reply_post_host_index[0] = -- cgit From 2f73b9a896634dd0ce68b5af9ae5f475e24ce51e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 30 Nov 2011 16:30:33 -0800 Subject: [SCSI] mpt2sas: Fix possible integer truncation of cpu_count When computing reply_queue_count (the number of MSI-X vectors to use), the driver does ioc->reply_queue_count = min_t(u8, ioc->cpu_count, ioc->msix_vector_count); However, on a big machine, ioc->cpu_count could be outside the range that fits in a u8; eg a system with 256 CPUs will end up reply_queue_count set to 0. Fix this by calculating the minimum as ints and then letting the assignment to reply_queue_count handle integer demotion. Signed-off-by: Roland Dreier Acked-by: "Nandigama, Nagalakshmi" Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 65c377dc0279..2da49cdf0208 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1407,7 +1407,7 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc) if (_base_check_enable_msix(ioc) != 0) goto try_ioapic; - ioc->reply_queue_count = min_t(u8, ioc->cpu_count, + ioc->reply_queue_count = min_t(int, ioc->cpu_count, ioc->msix_vector_count); entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry), -- cgit From ef8c98543c3ad75240599d4032f7e56b793740a9 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 30 Nov 2011 10:05:50 -0800 Subject: [SCSI] mpt2sas: Remove unused duplicate diag_buffer_enable param Commit 921cd8024b90 ("[SCSI] mpt2sas: New feature - Fast Load Support") moved handling of the diag_buffer_enable module parameter from mpt2sas_base.c to mpt2sas_scsih.c, but it left an old copy of the parameter in mpt2sas_base.c. Remove the unused stub. Signed-off-by: Roland Dreier Acked-by: "Nandigama, Nagalakshmi" Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 2da49cdf0208..4819181876fd 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -92,19 +92,6 @@ static int disable_discovery = -1; module_param(disable_discovery, int, 0); MODULE_PARM_DESC(disable_discovery, " disable discovery "); - -/* diag_buffer_enable is bitwise - * bit 0 set = TRACE - * bit 1 set = SNAPSHOT - * bit 2 set = EXTENDED - * - * Either bit can be set, or both - */ -static int diag_buffer_enable; -module_param(diag_buffer_enable, int, 0); -MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers " - "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); - /** * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. * -- cgit From 0c70d84b794c9a99f7395b617ecaef34c00d82ec Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 5 Dec 2011 16:44:01 -0600 Subject: [SCSI] iscsi class: export pid of process that created There could be multiple userspace entities creating/destroying/ recoverying sessions and also the kernel's iscsi drivers could be doing this too. If the userspace apps do try to manage the kernel ones it can get the driver/fw out of sync and cause the user to loose the root disk, oopses or ping ponging becasue userspace wants to do one thing but the kernel manager thought we are trying to do another. This patch fixes the problem by just exporting the pid of the entity that created the session. Userspace programs like iscsid, iscsiadm, iscsistart, qlogic's tools, etc, can then figure out which sessions they own and only manage them. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 96029e6d027f..c1b172b76689 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1030,6 +1030,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, return NULL; session->transport = transport; + session->creator = -1; session->recovery_tmo = 120; session->state = ISCSI_SESSION_FREE; INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); @@ -1634,8 +1635,9 @@ EXPORT_SYMBOL_GPL(iscsi_session_event); static int iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep, - struct iscsi_uevent *ev, uint32_t initial_cmdsn, - uint16_t cmds_max, uint16_t queue_depth) + struct iscsi_uevent *ev, pid_t pid, + uint32_t initial_cmdsn, uint16_t cmds_max, + uint16_t queue_depth) { struct iscsi_transport *transport = priv->iscsi_transport; struct iscsi_cls_session *session; @@ -1646,6 +1648,7 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep, if (!session) return -ENOMEM; + session->creator = pid; shost = iscsi_session_to_shost(session); ev->r.c_session_ret.host_no = shost->host_no; ev->r.c_session_ret.sid = session->sid; @@ -1938,6 +1941,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) switch (nlh->nlmsg_type) { case ISCSI_UEVENT_CREATE_SESSION: err = iscsi_if_create_session(priv, ep, ev, + NETLINK_CREDS(skb)->pid, ev->u.c_session.initial_cmdsn, ev->u.c_session.cmds_max, ev->u.c_session.queue_depth); @@ -1950,6 +1954,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) } err = iscsi_if_create_session(priv, ep, ev, + NETLINK_CREDS(skb)->pid, ev->u.c_bound_session.initial_cmdsn, ev->u.c_bound_session.cmds_max, ev->u.c_bound_session.queue_depth); @@ -2298,6 +2303,15 @@ show_priv_session_state(struct device *dev, struct device_attribute *attr, } static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state, NULL); +static ssize_t +show_priv_session_creator(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent); + return sprintf(buf, "%d\n", session->creator); +} +static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator, + NULL); #define iscsi_priv_session_attr_show(field, format) \ static ssize_t \ @@ -2367,6 +2381,7 @@ static struct attribute *iscsi_session_attrs[] = { &dev_attr_sess_targetalias.attr, &dev_attr_priv_sess_recovery_tmo.attr, &dev_attr_priv_sess_state.attr, + &dev_attr_priv_sess_creator.attr, NULL, }; @@ -2424,6 +2439,8 @@ static mode_t iscsi_session_attr_is_visible(struct kobject *kobj, return S_IRUGO | S_IWUSR; else if (attr == &dev_attr_priv_sess_state.attr) return S_IRUGO; + else if (attr == &dev_attr_priv_sess_creator.attr) + return S_IRUGO; else { WARN_ONCE(1, "Invalid session attr"); return 0; -- cgit From 4c6a794d2c0affde28f46ef5646cd41cd1a35f06 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 1 Dec 2011 22:42:06 -0800 Subject: [SCSI] qla4xxx: Perform context resets in case of context failures. For 4032, context reset was the same as chip reset, and any firmware issue was recovered by performing a chip reset. For 82xx, the iSCSI firmware runs along with FCoE and the NIC firmware contexts, and an error encountered doesnot essentially mean that a chip reset is necessary. Perform Chip resets only in the following cases: 1. Mailbox system error. 2. Mailbox command timeout. 3. fw_heartbeat_counter counter stops incrementing. For all other cases, only perform a context reset. 1. Command Completion with an invalid srb. 2. Other mailbox failures. Signed-off-by: Vikas Chaudhary Signed-off-by: Shyam Sunder Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_isr.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 827e93078b94..95828862eea0 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -123,13 +123,13 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); if (!srb) { - DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Status Entry invalid " - "handle 0x%x, sp=%p. This cmd may have already " - "been completed.\n", ha->host_no, __func__, - le32_to_cpu(sts_entry->handle), srb)); - ql4_printk(KERN_WARNING, ha, "%s invalid status entry:" - " handle=0x%0x\n", __func__, sts_entry->handle); - set_bit(DPC_RESET_HA, &ha->dpc_flags); + ql4_printk(KERN_WARNING, ha, "%s invalid status entry: " + "handle=0x%0x, srb=%p\n", __func__, + sts_entry->handle, srb); + if (is_qla8022(ha)) + set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); + else + set_bit(DPC_RESET_HA, &ha->dpc_flags); return; } @@ -563,7 +563,11 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, case MBOX_ASTS_DHCP_LEASE_EXPIRED: DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, " "Reset HA\n", ha->host_no, mbox_status)); - set_bit(DPC_RESET_HA, &ha->dpc_flags); + if (is_qla8022(ha)) + set_bit(DPC_RESET_HA_FW_CONTEXT, + &ha->dpc_flags); + else + set_bit(DPC_RESET_HA, &ha->dpc_flags); break; case MBOX_ASTS_LINK_UP: @@ -617,9 +621,13 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, (mbox_sts[2] == ACB_STATE_ACQUIRING))) set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) && - (mbox_sts[2] == ACB_STATE_VALID)) - set_bit(DPC_RESET_HA, &ha->dpc_flags); - else if ((mbox_sts[3] == ACB_STATE_UNCONFIGURED)) + (mbox_sts[2] == ACB_STATE_VALID)) { + if (is_qla8022(ha)) + set_bit(DPC_RESET_HA_FW_CONTEXT, + &ha->dpc_flags); + else + set_bit(DPC_RESET_HA, &ha->dpc_flags); + } else if ((mbox_sts[3] == ACB_STATE_UNCONFIGURED)) complete(&ha->disable_acb_comp); break; -- cgit From 9acf753393cde200e9d25574c6d7d2cf57636001 Mon Sep 17 00:00:00 2001 From: Mike Hernandez Date: Thu, 1 Dec 2011 22:42:07 -0800 Subject: [SCSI] qla4xxx: Fix CPU lockups when ql4xdontresethba set Fix issue where CPU lockup is seen when ql4xdontresethba is set and driver is "stuck" in NEED_RESET state handler. Signed-off-by: Mike Hernandez Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_nx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index f484ff438199..7fc29c6ff57e 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1836,6 +1836,10 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) * reset handler */ dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); + } else { + qla4_8xxx_idc_unlock(ha); + msleep(1000); + qla4_8xxx_idc_lock(ha); } qla4_8xxx_idc_unlock(ha); break; -- cgit From 8a288960192591c405767d98ebe372f66df1a6c6 Mon Sep 17 00:00:00 2001 From: Sarang Radke Date: Tue, 6 Dec 2011 02:34:10 -0800 Subject: [SCSI] qla4xxx: fix call trace on rmmod with ql4xdontresethba=1 abort all active commands from eh_host_reset in-case of ql4xdontresethba=1 Fix following call trace:- Nov 21 14:50:47 172.17.140.111 qla4xxx 0000:13:00.4: qla4_8xxx_disable_msix: qla4xxx (rsp_q) Nov 21 14:50:47 172.17.140.111 qla4xxx 0000:13:00.4: PCI INT A disabled Nov 21 14:50:47 172.17.140.111 slab error in kmem_cache_destroy(): cache `qla4xxx_srbs': Can't free all objects Nov 21 14:50:47 172.17.140.111 Pid: 9154, comm: rmmod Tainted: G O 3.2.0-rc2+ #2 Nov 21 14:50:47 172.17.140.111 Call Trace: Nov 21 14:50:47 172.17.140.111 [] ? kmem_cache_destroy+0x9a/0xb0 Nov 21 14:50:47 172.17.140.111 [] ? sys_delete_module+0x14a/0x210 Nov 21 14:50:47 172.17.140.111 [] ? do_munmap+0x202/0x280 Nov 21 14:50:47 172.17.140.111 [] ? audit_syscall_entry+0x1ae/0x1d0 Nov 21 14:50:47 172.17.140.111 [] ? sysenter_do_call+0x12/0x28 Nov 21 14:51:50 172.17.140.111 SLAB: cache with size 64 has lost its name Nov 21 14:51:50 172.17.140.111 iscsi: registered transport (qla4xxx) Nov 21 14:51:50 172.17.140.111 qla4xxx 0000:13:00.4: PCI INT A -> GSI 28 (level, low) -> IRQ 28 Signed-off-by: Sarang Radke Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 4169c8baa112..dde539ca4b3d 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2806,6 +2806,7 @@ dpc_post_reset_ha: **/ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) { + qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { /* Turn-off interrupts on the card. */ @@ -4815,6 +4816,20 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) return SUCCESS; } +/** + * qla4xxx_is_eh_active - check if error handler is running + * @shost: Pointer to SCSI Host struct + * + * This routine finds that if reset host is called in EH + * scenario or from some application like sg_reset + **/ +static int qla4xxx_is_eh_active(struct Scsi_Host *shost) +{ + if (shost->shost_state == SHOST_RECOVERY) + return 1; + return 0; +} + /** * qla4xxx_eh_host_reset - kernel callback * @cmd: Pointer to Linux's SCSI command structure @@ -4832,6 +4847,11 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) if (ql4xdontresethba) { DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", ha->host_no, __func__)); + + /* Clear outstanding srb in queues */ + if (qla4xxx_is_eh_active(cmd->device->host)) + qla4xxx_abort_active_cmds(ha, DID_ABORT << 16); + return FAILED; } -- cgit From 8e0f3a66a2833eaad618584c2bac89a8ae2efce7 Mon Sep 17 00:00:00 2001 From: Sarang Radke Date: Thu, 1 Dec 2011 22:42:09 -0800 Subject: [SCSI] qla4xxx: Don't recover adapter if device state is FAILED Multiple reset request don't get handled correctly as the driver tries to recover adapter which is in FAILED state. Signed-off-by: Sarang Radke Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index dde539ca4b3d..064d67282f59 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2414,6 +2414,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) { int status = QLA_ERROR; uint8_t reset_chip = 0; + uint32_t dev_state; /* Stall incoming I/O until we are done */ scsi_block_requests(ha->host); @@ -2501,6 +2502,25 @@ recover_ha_init_adapter: * Since we don't want to block the DPC for too long * with multiple resets in the same thread, * utilize DPC to retry */ + if (is_qla8022(ha)) { + qla4_8xxx_idc_lock(ha); + dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + qla4_8xxx_idc_unlock(ha); + if (dev_state == QLA82XX_DEV_FAILED) { + ql4_printk(KERN_INFO, ha, "%s: don't retry " + "recover adapter. H/W is in Failed " + "state\n", __func__); + qla4xxx_dead_adapter_cleanup(ha); + clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); + clear_bit(DPC_RESET_HA, &ha->dpc_flags); + clear_bit(DPC_RESET_HA_FW_CONTEXT, + &ha->dpc_flags); + status = QLA_ERROR; + + goto exit_recover; + } + } + if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; DEBUG2(printk("scsi%ld: recover adapter - retrying " @@ -2539,6 +2559,7 @@ recover_ha_init_adapter: clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); } +exit_recover: ha->adapter_error_count++; if (test_bit(AF_ONLINE, &ha->flags)) -- cgit From ce505f9d1d9701f02b124ba1ee6caec21c2100e2 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 1 Dec 2011 22:42:10 -0800 Subject: [SCSI] qla4xxx: Wait for disable_acb before doing set_acb In function qla4xxx_iface_set_param wait for disable_acb to complete so that set_acb will not fail. Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 064d67282f59..0c9ee9378094 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -935,7 +935,16 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len) goto exit_init_fw_cb; } - qla4xxx_disable_acb(ha); + rval = qla4xxx_disable_acb(ha); + if (rval != QLA_SUCCESS) { + ql4_printk(KERN_ERR, ha, "%s: disable acb mbx failed\n", + __func__); + rval = -EIO; + goto exit_init_fw_cb; + } + + wait_for_completion_timeout(&ha->disable_acb_comp, + DISABLE_ACB_TOV * HZ); qla4xxx_initcb_to_acb(init_fw_cb); -- cgit From e3f37d1636b7142527704ff62bf6f695a2887501 Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Thu, 1 Dec 2011 22:42:11 -0800 Subject: [SCSI] qla4xxx: Fix the IDC locking mechanism This ensures the transition of dev_state from COLD to INITIALIZING is within lock and atomic. Signed-off-by: Nilesh Javali Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_nx.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 7fc29c6ff57e..8d6bc1b2ff17 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1792,8 +1792,11 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) int rval = QLA_SUCCESS; unsigned long dev_init_timeout; - if (!test_bit(AF_INIT_DONE, &ha->flags)) + if (!test_bit(AF_INIT_DONE, &ha->flags)) { + qla4_8xxx_idc_lock(ha); qla4_8xxx_set_drv_active(ha); + qla4_8xxx_idc_unlock(ha); + } dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, @@ -1802,8 +1805,8 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) /* wait for 30 seconds for device to go ready */ dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); + qla4_8xxx_idc_lock(ha); while (1) { - qla4_8xxx_idc_lock(ha); if (time_after_eq(jiffies, dev_init_timeout)) { ql4_printk(KERN_WARNING, ha, "Device init failed!\n"); @@ -1819,15 +1822,14 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) /* NOTE: Make sure idc unlocked upon exit of switch statement */ switch (dev_state) { case QLA82XX_DEV_READY: - qla4_8xxx_idc_unlock(ha); goto exit; case QLA82XX_DEV_COLD: rval = qla4_8xxx_device_bootstrap(ha); - qla4_8xxx_idc_unlock(ha); goto exit; case QLA82XX_DEV_INITIALIZING: qla4_8xxx_idc_unlock(ha); msleep(1000); + qla4_8xxx_idc_lock(ha); break; case QLA82XX_DEV_NEED_RESET: if (!ql4xdontresethba) { @@ -1841,31 +1843,32 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) msleep(1000); qla4_8xxx_idc_lock(ha); } - qla4_8xxx_idc_unlock(ha); break; case QLA82XX_DEV_NEED_QUIESCENT: - qla4_8xxx_idc_unlock(ha); /* idc locked/unlocked in handler */ qla4_8xxx_need_qsnt_handler(ha); - qla4_8xxx_idc_lock(ha); - /* fall thru needs idc_locked */ + break; case QLA82XX_DEV_QUIESCENT: qla4_8xxx_idc_unlock(ha); msleep(1000); + qla4_8xxx_idc_lock(ha); break; case QLA82XX_DEV_FAILED: qla4_8xxx_idc_unlock(ha); qla4xxx_dead_adapter_cleanup(ha); rval = QLA_ERROR; + qla4_8xxx_idc_lock(ha); goto exit; default: qla4_8xxx_idc_unlock(ha); qla4xxx_dead_adapter_cleanup(ha); rval = QLA_ERROR; + qla4_8xxx_idc_lock(ha); goto exit; } } exit: + qla4_8xxx_idc_unlock(ha); return rval; } -- cgit From 0a24361566d750065849f63521097f8373a0ac6b Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 1 Dec 2011 22:42:12 -0800 Subject: [SCSI] qla4xxx: Fix qla4xxx_dump_buffer to dump buffer correctly KERN_INFO in printk adding new line character that mess-up dump print format. Remove KERN_INFO to fix dump format. Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_dbg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c index af62c3cf8752..8d58ae274829 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c @@ -20,12 +20,12 @@ void qla4xxx_dump_buffer(void *b, uint32_t size) printk("------------------------------------------------------------" "--\n"); for (cnt = 0; cnt < size; c++) { - printk(KERN_INFO "%02x", *c); + printk("%02x", *c); if (!(++cnt % 16)) - printk(KERN_INFO "\n"); + printk("\n"); else - printk(KERN_INFO " "); + printk(" "); } printk(KERN_INFO "\n"); } -- cgit From 9ee91a38b1e224b0ee4ddc9a69d41f732d776310 Mon Sep 17 00:00:00 2001 From: Shyam Sunder Date: Thu, 1 Dec 2011 22:42:13 -0800 Subject: [SCSI] qla4xxx: check for FW alive before calling chip_reset Check for firmware alive and do premature completion of mbox commands in case of FW hung before doing chip_reset Signed-off-by: Shyam Sunder Reviewed-by: Mike Christie Signed-off-by: Nilesh Javali Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 1 + drivers/scsi/qla4xxx/ql4_os.c | 75 ++++++++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 24 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index fd5edc6e166d..22a3ff02e48a 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -177,6 +177,7 @@ #define LOGIN_TOV 12 #define MAX_RESET_HA_RETRIES 2 +#define FW_ALIVE_WAIT_TOV 3 #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 0c9ee9378094..70778d5227a9 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1975,9 +1975,10 @@ mem_alloc_error_exit: * * Context: Interrupt **/ -static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) +static int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) { - uint32_t fw_heartbeat_counter, halt_status; + uint32_t fw_heartbeat_counter; + int status = QLA_SUCCESS; fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */ @@ -1985,7 +1986,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen " "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n", ha->host_no, __func__)); - return; + return status; } if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { @@ -1993,8 +1994,6 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) /* FW not alive after 2 seconds */ if (ha->seconds_since_last_heartbeat == 2) { ha->seconds_since_last_heartbeat = 0; - halt_status = qla4_8xxx_rd_32(ha, - QLA82XX_PEG_HALT_STATUS1); ql4_printk(KERN_INFO, ha, "scsi(%ld): %s, Dumping hw/fw registers:\n " @@ -2002,7 +2001,9 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) " 0x%x,\n PEG_NET_0_PC: 0x%x, PEG_NET_1_PC:" " 0x%x,\n PEG_NET_2_PC: 0x%x, PEG_NET_3_PC:" " 0x%x,\n PEG_NET_4_PC: 0x%x\n", - ha->host_no, __func__, halt_status, + ha->host_no, __func__, + qla4_8xxx_rd_32(ha, + QLA82XX_PEG_HALT_STATUS1), qla4_8xxx_rd_32(ha, QLA82XX_PEG_HALT_STATUS2), qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 + @@ -2015,24 +2016,13 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) 0x3c), qla4_8xxx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c)); - - /* Since we cannot change dev_state in interrupt - * context, set appropriate DPC flag then wakeup - * DPC */ - if (halt_status & HALT_STATUS_UNRECOVERABLE) - set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); - else { - printk("scsi%ld: %s: detect abort needed!\n", - ha->host_no, __func__); - set_bit(DPC_RESET_HA, &ha->dpc_flags); - } - qla4xxx_wake_dpc(ha); - qla4xxx_mailbox_premature_completion(ha); + status = QLA_ERROR; } } else ha->seconds_since_last_heartbeat = 0; ha->fw_heartbeat_counter = fw_heartbeat_counter; + return status; } /** @@ -2043,14 +2033,13 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) **/ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) { - uint32_t dev_state; - - dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + uint32_t dev_state, halt_status; /* don't poll if reset is going on */ if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || test_bit(DPC_RESET_HA, &ha->dpc_flags) || test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { + dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); if (dev_state == QLA82XX_DEV_NEED_RESET && !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { if (!ql4xdontresethba) { @@ -2058,7 +2047,6 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) "NEED RESET!\n", __func__); set_bit(DPC_RESET_HA, &ha->dpc_flags); qla4xxx_wake_dpc(ha); - qla4xxx_mailbox_premature_completion(ha); } } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { @@ -2068,7 +2056,24 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) qla4xxx_wake_dpc(ha); } else { /* Check firmware health */ - qla4_8xxx_check_fw_alive(ha); + if (qla4_8xxx_check_fw_alive(ha)) { + halt_status = qla4_8xxx_rd_32(ha, + QLA82XX_PEG_HALT_STATUS1); + + /* Since we cannot change dev_state in interrupt + * context, set appropriate DPC flag then wakeup + * DPC */ + if (halt_status & HALT_STATUS_UNRECOVERABLE) + set_bit(DPC_HA_UNRECOVERABLE, + &ha->dpc_flags); + else { + ql4_printk(KERN_INFO, ha, "%s: detect " + "abort needed!\n", __func__); + set_bit(DPC_RESET_HA, &ha->dpc_flags); + } + qla4xxx_mailbox_premature_completion(ha); + qla4xxx_wake_dpc(ha); + } } } } @@ -2424,6 +2429,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) int status = QLA_ERROR; uint8_t reset_chip = 0; uint32_t dev_state; + unsigned long wait; /* Stall incoming I/O until we are done */ scsi_block_requests(ha->host); @@ -2474,8 +2480,29 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) * or if stop_firmware fails for ISP-82xx. * This is the default case for ISP-4xxx */ if (!is_qla8022(ha) || reset_chip) { + if (!is_qla8022(ha)) + goto chip_reset; + + /* Check if 82XX firmware is alive or not + * We may have arrived here from NEED_RESET + * detection only */ + if (test_bit(AF_FW_RECOVERY, &ha->flags)) + goto chip_reset; + + wait = jiffies + (FW_ALIVE_WAIT_TOV * HZ); + while (time_before(jiffies, wait)) { + if (qla4_8xxx_check_fw_alive(ha)) { + qla4xxx_mailbox_premature_completion(ha); + break; + } + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + } + if (!test_bit(AF_FW_RECOVERY, &ha->flags)) qla4xxx_cmd_wait(ha); +chip_reset: qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); qla4xxx_abort_active_cmds(ha, DID_RESET << 16); DEBUG2(ql4_printk(KERN_INFO, ha, -- cgit From 7b12859ae4776d868ea732424a452826d9ee03df Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 1 Dec 2011 22:42:14 -0800 Subject: [SCSI] qla4xxx: Update driver version to 5.02.00-k10 Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 5254e57968f5..26a3fa34a33c 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k9" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k10" -- cgit From dddaaf793d73f1e3dc931b2040f1578b1bdf0ece Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 11 Dec 2011 10:04:51 +0100 Subject: [SCSI] mac_scsi: Remove obsolete IRQ_FLG_* users The m68k core irq code stopped honoring these flags during the irq restructuring in 2006. Signed-off-by: Geert Uytterhoeven Signed-off-by: James Bottomley --- drivers/scsi/mac_scsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index af3a6af97cc7..ea2bde206f7f 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -291,8 +291,7 @@ int __init macscsi_detect(struct scsi_host_template * tpnt) ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; if (instance->irq != SCSI_IRQ_NONE) - if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, - "ncr5380", instance)) { + if (request_irq(instance->irq, NCR5380_intr, 0, "ncr5380", instance)) { printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = SCSI_IRQ_NONE; -- cgit From 2cb6fc8c014b9b00c4487a79b8f6ed0da4121f45 Mon Sep 17 00:00:00 2001 From: "nagalakshmi.nandigama@lsi.com" Date: Tue, 13 Dec 2011 09:29:15 +0530 Subject: [SCSI] mpt2sas: Removed redundant calling of _scsih_probe_devices() from _scsih_probe Removed redundant calling of _scsih_probe_devices() from _scsih_probe as it is getting called from _scsih_scan_finished. Also moved the function scsi_scan_host(shost) to get called after the volumes on warp drive are reported to the OS. Otherwise by the time the (ioc->hide_drives) flags is set, the volumes on warp drive are reported to the OS already. Also modified the initialization of reply queues only in case of driver load time in the function _base_make_ioc_operational(). Signed-off-by: Nagalakshmi Nandigama Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 20 +++++++------------- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 3 +-- 2 files changed, 8 insertions(+), 15 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 4819181876fd..0b2c95583660 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -4099,7 +4099,8 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) ioc->reply_free[i] = cpu_to_le32(reply_address); /* initialize reply queues */ - _base_assign_reply_queues(ioc); + if (ioc->is_driver_loading) + _base_assign_reply_queues(ioc); /* initialize Reply Post Free Queue */ reply_post_free = (long)ioc->reply_post_free; @@ -4147,24 +4148,17 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) if (ioc->is_driver_loading) { - - - - ioc->wait_for_discovery_to_complete = - _base_determine_wait_on_discovery(ioc); - return r; /* scan_start and scan_finished support */ - } - - - if (ioc->wait_for_discovery_to_complete && ioc->is_warpdrive) { - if (ioc->manu_pg10.OEMIdentifier == 0x80) { + if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier + == 0x80) { hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 & MFG_PAGE10_HIDE_SSDS_MASK); if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK) ioc->mfg_pg10_hide_flag = hide_flag; } + ioc->wait_for_discovery_to_complete = + _base_determine_wait_on_discovery(ioc); + return r; /* scan_start and scan_finished support */ } - r = _base_send_port_enable(ioc, sleep_flag); if (r) return r; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 8cd4ebb9349f..193e33e28e49 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -8039,7 +8039,6 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_attach_fail; } - scsi_scan_host(shost); if (ioc->is_warpdrive) { if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) ioc->hide_drives = 0; @@ -8053,8 +8052,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } else ioc->hide_drives = 0; + scsi_scan_host(shost); - _scsih_probe_devices(ioc); return 0; out_attach_fail: -- cgit From 026abb87a5586c838a47aca7198d78e356b6351e Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 13 Dec 2011 13:20:45 -0500 Subject: [SCSI] lpfc 8.3.28: Miscellaneous fixes in sysfs and mgmt interfaces Miscellaneous fixes in sysfs and mgmt interfaces: - Added SLI4 INTF_TYPE and SLI_FAMILY as sub-field to the fwrev sysfs attribute (CR 124103) - Added a sysfs attribute "protocol" to report SLI4 port link protocol type (CR 124102) - Increment mix-and-match minor number by 1 for added "protocol" sysfs attribute. (124102) - Move the link speed check into the generic sli3/sli4 code path. (CR 124185, 124122) - Deleted check for inExtWLen (CR 122523) - Add the word "offline" to message 2889 (CR 124385) - Conditionalize the firmware upgrade/downgrade so that it is only attempted for SLI4 type 2 boards (CR 124406) - Return an error if the mbox sysfs is called. (CR 124210) - When port_state is less than LPFC_VPORT_READY, report FC_PORTSTATE_BYPASSED (CR 120018) - Added driver support for performing persistent linkdown based on configure region 23 (CR 124534) - Added restore state and error log when sysfs board_mode attribute access failed (CR 124158) - Added support for SLI4_CONFIG non-embedded COMN_GET_CNTL_ADDL_ATTR pass-through (CR 124466) - Rejecting un-supported multi-buffer mailbox commands (CR 124771) - Byte swap the extended data request and response data for extended mailbox data (CR 125081) Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 14 -- drivers/scsi/lpfc/lpfc_attr.c | 413 +++++++++++++----------------------------- drivers/scsi/lpfc/lpfc_bsg.c | 74 ++++++-- drivers/scsi/lpfc/lpfc_bsg.h | 3 +- drivers/scsi/lpfc/lpfc_crtn.h | 2 +- drivers/scsi/lpfc/lpfc_hw4.h | 2 + drivers/scsi/lpfc/lpfc_init.c | 84 ++++----- drivers/scsi/lpfc/lpfc_mbox.c | 13 +- drivers/scsi/lpfc/lpfc_sli.c | 149 ++++++++++++--- 9 files changed, 356 insertions(+), 398 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index bb4c8e0584e2..825f9307417a 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -247,18 +247,6 @@ struct lpfc_stats { uint32_t fcpLocalErr; }; -enum sysfs_mbox_state { - SMBOX_IDLE, - SMBOX_WRITING, - SMBOX_READING -}; - -struct lpfc_sysfs_mbox { - enum sysfs_mbox_state state; - size_t offset; - struct lpfcMboxq * mbox; -}; - struct lpfc_hba; @@ -783,8 +771,6 @@ struct lpfc_hba { uint64_t bg_apptag_err_cnt; uint64_t bg_reftag_err_cnt; - struct lpfc_sysfs_mbox sysfs_mbox; - /* fastpath list. */ spinlock_t scsi_buf_list_lock; struct list_head lpfc_scsi_buf_list; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index d0ebaeb7ef60..7bf492e156d9 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -351,10 +351,23 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr, struct Scsi_Host *shost = class_to_shost(dev); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; + uint32_t if_type; + uint8_t sli_family; char fwrev[32]; + int len; lpfc_decode_firmware_rev(phba, fwrev, 1); - return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev); + if_type = phba->sli4_hba.pc_sli4_params.if_type; + sli_family = phba->sli4_hba.pc_sli4_params.sli_family; + + if (phba->sli_rev < LPFC_SLI_REV4) + len = snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", + fwrev, phba->sli_rev); + else + len = snprintf(buf, PAGE_SIZE, "%s, sli-%d:%d:%x\n", + fwrev, phba->sli_rev, if_type, sli_family); + + return len; } /** @@ -487,6 +500,34 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr, return len; } +/** + * lpfc_sli4_protocol_show - Return the fip mode of the HBA + * @dev: class unused variable. + * @attr: device attribute, not used. + * @buf: on return contains the module description text. + * + * Returns: size of formatted string. + **/ +static ssize_t +lpfc_sli4_protocol_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + + if (phba->sli_rev < LPFC_SLI_REV4) + return snprintf(buf, PAGE_SIZE, "fc\n"); + + if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) { + if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_GE) + return snprintf(buf, PAGE_SIZE, "fcoe\n"); + if (phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) + return snprintf(buf, PAGE_SIZE, "fc\n"); + } + return snprintf(buf, PAGE_SIZE, "unknown\n"); +} + /** * lpfc_link_state_store - Transition the link_state on an HBA port * @dev: class device that is converted into a Scsi_host. @@ -773,7 +814,12 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, * the readyness after performing a firmware reset. * * Returns: - * zero for success + * zero for success, -EPERM when port does not have privilage to perform the + * reset, -EIO when port timeout from recovering from the reset. + * + * Note: + * As the caller will interpret the return code by value, be careful in making + * change or addition to return codes. **/ int lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba) @@ -826,9 +872,11 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) { struct completion online_compl; struct pci_dev *pdev = phba->pcidev; + uint32_t before_fc_flag; + uint32_t sriov_nr_virtfn; uint32_t reg_val; - int status = 0; - int rc; + int status = 0, rc = 0; + int job_posted = 1, sriov_err; if (!phba->cfg_enable_hba_reset) return -EACCES; @@ -838,6 +886,10 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) LPFC_SLI_INTF_IF_TYPE_2)) return -EPERM; + /* Keep state if we need to restore back */ + before_fc_flag = phba->pport->fc_flag; + sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn; + /* Disable SR-IOV virtual functions if enabled */ if (phba->cfg_sriov_nr_virtfn) { pci_disable_sriov(pdev); @@ -869,21 +921,44 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) /* delay driver action following IF_TYPE_2 reset */ rc = lpfc_sli4_pdev_status_reg_wait(phba); - if (rc) + if (rc == -EPERM) { + /* no privilage for reset, restore if needed */ + if (before_fc_flag & FC_OFFLINE_MODE) + goto out; + } else if (rc == -EIO) { + /* reset failed, there is nothing more we can do */ return rc; + } + + /* keep the original port state */ + if (before_fc_flag & FC_OFFLINE_MODE) + goto out; init_completion(&online_compl); - rc = lpfc_workq_post_event(phba, &status, &online_compl, - LPFC_EVT_ONLINE); - if (rc == 0) - return -ENOMEM; + job_posted = lpfc_workq_post_event(phba, &status, &online_compl, + LPFC_EVT_ONLINE); + if (!job_posted) + goto out; wait_for_completion(&online_compl); - if (status != 0) - return -EIO; +out: + /* in any case, restore the virtual functions enabled as before */ + if (sriov_nr_virtfn) { + sriov_err = + lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn); + if (!sriov_err) + phba->cfg_sriov_nr_virtfn = sriov_nr_virtfn; + } - return 0; + /* return proper error code */ + if (!rc) { + if (!job_posted) + rc = -ENOMEM; + else if (status) + rc = -EIO; + } + return rc; } /** @@ -955,33 +1030,38 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; struct completion online_compl; - int status=0; + char *board_mode_str = NULL; + int status = 0; int rc; - if (!phba->cfg_enable_hba_reset) - return -EACCES; + if (!phba->cfg_enable_hba_reset) { + status = -EACCES; + goto board_mode_out; + } lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, - "3050 lpfc_board_mode set to %s\n", buf); + "3050 lpfc_board_mode set to %s\n", buf); init_completion(&online_compl); if(strncmp(buf, "online", sizeof("online") - 1) == 0) { rc = lpfc_workq_post_event(phba, &status, &online_compl, LPFC_EVT_ONLINE); - if (rc == 0) - return -ENOMEM; + if (rc == 0) { + status = -ENOMEM; + goto board_mode_out; + } wait_for_completion(&online_compl); } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0) if (phba->sli_rev == LPFC_SLI_REV4) - return -EINVAL; + status = -EINVAL; else status = lpfc_do_offline(phba, LPFC_EVT_WARM_START); else if (strncmp(buf, "error", sizeof("error") - 1) == 0) if (phba->sli_rev == LPFC_SLI_REV4) - return -EINVAL; + status = -EINVAL; else status = lpfc_do_offline(phba, LPFC_EVT_KILL); else if (strncmp(buf, "dump", sizeof("dump") - 1) == 0) @@ -991,12 +1071,21 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, else if (strncmp(buf, "dv_reset", sizeof("dv_reset") - 1) == 0) status = lpfc_sli4_pdev_reg_request(phba, LPFC_DV_RESET); else - return -EINVAL; + status = -EINVAL; +board_mode_out: if (!status) return strlen(buf); - else + else { + board_mode_str = strchr(buf, '\n'); + if (board_mode_str) + *board_mode_str = '\0'; + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "3097 Failed \"%s\", status(%d), " + "fc_flag(x%x)\n", + buf, status, phba->pport->fc_flag); return status; + } } /** @@ -1942,6 +2031,7 @@ static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL); static DEVICE_ATTR(lpfc_sriov_hw_max_virtfn, S_IRUGO, lpfc_sriov_hw_max_virtfn_show, NULL); +static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL); static char *lpfc_soft_wwn_key = "C99G71SL8032A"; @@ -3830,6 +3920,7 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_fips_rev, &dev_attr_lpfc_dss, &dev_attr_lpfc_sriov_hw_max_virtfn, + &dev_attr_protocol, NULL, }; @@ -3987,23 +4078,6 @@ static struct bin_attribute sysfs_ctlreg_attr = { .write = sysfs_ctlreg_write, }; -/** - * sysfs_mbox_idle - frees the sysfs mailbox - * @phba: lpfc_hba pointer - **/ -static void -sysfs_mbox_idle(struct lpfc_hba *phba) -{ - phba->sysfs_mbox.state = SMBOX_IDLE; - phba->sysfs_mbox.offset = 0; - - if (phba->sysfs_mbox.mbox) { - mempool_free(phba->sysfs_mbox.mbox, - phba->mbox_mem_pool); - phba->sysfs_mbox.mbox = NULL; - } -} - /** * sysfs_mbox_write - Write method for writing information via mbox * @filp: open sysfs file @@ -4014,71 +4088,18 @@ sysfs_mbox_idle(struct lpfc_hba *phba) * @count: bytes to transfer. * * Description: - * Accessed via /sys/class/scsi_host/hostxxx/mbox. - * Uses the sysfs mbox to send buf contents to the adapter. + * Deprecated function. All mailbox access from user space is performed via the + * bsg interface. * * Returns: - * -ERANGE off and count combo out of range - * -EINVAL off, count or buff address invalid - * zero if count is zero - * -EPERM adapter is offline - * -ENOMEM failed to allocate memory for the mail box - * -EAGAIN offset, state or mbox is NULL - * count number of bytes transferred + * -EPERM operation not permitted **/ static ssize_t sysfs_mbox_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - struct lpfcMboxq *mbox = NULL; - - if ((count + off) > MAILBOX_CMD_SIZE) - return -ERANGE; - - if (off % 4 || count % 4 || (unsigned long)buf % 4) - return -EINVAL; - - if (count == 0) - return 0; - - if (off == 0) { - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mbox) - return -ENOMEM; - memset(mbox, 0, sizeof (LPFC_MBOXQ_t)); - } - - spin_lock_irq(&phba->hbalock); - - if (off == 0) { - if (phba->sysfs_mbox.mbox) - mempool_free(mbox, phba->mbox_mem_pool); - else - phba->sysfs_mbox.mbox = mbox; - phba->sysfs_mbox.state = SMBOX_WRITING; - } else { - if (phba->sysfs_mbox.state != SMBOX_WRITING || - phba->sysfs_mbox.offset != off || - phba->sysfs_mbox.mbox == NULL) { - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return -EAGAIN; - } - } - - memcpy((uint8_t *) &phba->sysfs_mbox.mbox->u.mb + off, - buf, count); - - phba->sysfs_mbox.offset = off + count; - - spin_unlock_irq(&phba->hbalock); - - return count; + return -EPERM; } /** @@ -4091,201 +4112,18 @@ sysfs_mbox_write(struct file *filp, struct kobject *kobj, * @count: bytes to transfer. * * Description: - * Accessed via /sys/class/scsi_host/hostxxx/mbox. - * Uses the sysfs mbox to receive data from to the adapter. + * Deprecated function. All mailbox access from user space is performed via the + * bsg interface. * * Returns: - * -ERANGE off greater than mailbox command size - * -EINVAL off, count or buff address invalid - * zero if off and count are zero - * -EACCES adapter over temp - * -EPERM garbage can value to catch a multitude of errors - * -EAGAIN management IO not permitted, state or off error - * -ETIME mailbox timeout - * -ENODEV mailbox error - * count number of bytes transferred + * -EPERM operation not permitted **/ static ssize_t sysfs_mbox_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct device *dev = container_of(kobj, struct device, kobj); - struct Scsi_Host *shost = class_to_shost(dev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - LPFC_MBOXQ_t *mboxq; - MAILBOX_t *pmb; - uint32_t mbox_tmo; - int rc; - - if (off > MAILBOX_CMD_SIZE) - return -ERANGE; - - if ((count + off) > MAILBOX_CMD_SIZE) - count = MAILBOX_CMD_SIZE - off; - - if (off % 4 || count % 4 || (unsigned long)buf % 4) - return -EINVAL; - - if (off && count == 0) - return 0; - - spin_lock_irq(&phba->hbalock); - - if (phba->over_temp_state == HBA_OVER_TEMP) { - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return -EACCES; - } - - if (off == 0 && - phba->sysfs_mbox.state == SMBOX_WRITING && - phba->sysfs_mbox.offset >= 2 * sizeof(uint32_t)) { - mboxq = (LPFC_MBOXQ_t *)&phba->sysfs_mbox.mbox; - pmb = &mboxq->u.mb; - switch (pmb->mbxCommand) { - /* Offline only */ - case MBX_INIT_LINK: - case MBX_DOWN_LINK: - case MBX_CONFIG_LINK: - case MBX_CONFIG_RING: - case MBX_RESET_RING: - case MBX_UNREG_LOGIN: - case MBX_CLEAR_LA: - case MBX_DUMP_CONTEXT: - case MBX_RUN_DIAGS: - case MBX_RESTART: - case MBX_SET_MASK: - case MBX_SET_DEBUG: - if (!(vport->fc_flag & FC_OFFLINE_MODE)) { - printk(KERN_WARNING "mbox_read:Command 0x%x " - "is illegal in on-line state\n", - pmb->mbxCommand); - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return -EPERM; - } - case MBX_WRITE_NV: - case MBX_WRITE_VPARMS: - case MBX_LOAD_SM: - case MBX_READ_NV: - case MBX_READ_CONFIG: - case MBX_READ_RCONFIG: - case MBX_READ_STATUS: - case MBX_READ_XRI: - case MBX_READ_REV: - case MBX_READ_LNK_STAT: - case MBX_DUMP_MEMORY: - case MBX_DOWN_LOAD: - case MBX_UPDATE_CFG: - case MBX_KILL_BOARD: - case MBX_LOAD_AREA: - case MBX_LOAD_EXP_ROM: - case MBX_BEACON: - case MBX_DEL_LD_ENTRY: - case MBX_SET_VARIABLE: - case MBX_WRITE_WWN: - case MBX_PORT_CAPABILITIES: - case MBX_PORT_IOV_CONTROL: - break; - case MBX_SECURITY_MGMT: - case MBX_AUTH_PORT: - if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { - printk(KERN_WARNING "mbox_read:Command 0x%x " - "is not permitted\n", pmb->mbxCommand); - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return -EPERM; - } - break; - case MBX_READ_SPARM64: - case MBX_READ_TOPOLOGY: - case MBX_REG_LOGIN: - case MBX_REG_LOGIN64: - case MBX_CONFIG_PORT: - case MBX_RUN_BIU_DIAG: - printk(KERN_WARNING "mbox_read: Illegal Command 0x%x\n", - pmb->mbxCommand); - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return -EPERM; - default: - printk(KERN_WARNING "mbox_read: Unknown Command 0x%x\n", - pmb->mbxCommand); - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return -EPERM; - } - - /* If HBA encountered an error attention, allow only DUMP - * or RESTART mailbox commands until the HBA is restarted. - */ - if (phba->pport->stopped && - pmb->mbxCommand != MBX_DUMP_MEMORY && - pmb->mbxCommand != MBX_RESTART && - pmb->mbxCommand != MBX_WRITE_VPARMS && - pmb->mbxCommand != MBX_WRITE_WWN) - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, - "1259 mbox: Issued mailbox cmd " - "0x%x while in stopped state.\n", - pmb->mbxCommand); - - phba->sysfs_mbox.mbox->vport = vport; - - /* Don't allow mailbox commands to be sent when blocked - * or when in the middle of discovery - */ - if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) { - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return -EAGAIN; - } - - if ((vport->fc_flag & FC_OFFLINE_MODE) || - (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))) { - - spin_unlock_irq(&phba->hbalock); - rc = lpfc_sli_issue_mbox (phba, - phba->sysfs_mbox.mbox, - MBX_POLL); - spin_lock_irq(&phba->hbalock); - - } else { - spin_unlock_irq(&phba->hbalock); - mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq); - rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); - spin_lock_irq(&phba->hbalock); - } - - if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) { - phba->sysfs_mbox.mbox = NULL; - } - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV; - } - phba->sysfs_mbox.state = SMBOX_READING; - } - else if (phba->sysfs_mbox.offset != off || - phba->sysfs_mbox.state != SMBOX_READING) { - printk(KERN_WARNING "mbox_read: Bad State\n"); - sysfs_mbox_idle(phba); - spin_unlock_irq(&phba->hbalock); - return -EAGAIN; - } - - memcpy(buf, (uint8_t *) &pmb + off, count); - - phba->sysfs_mbox.offset = off + count; - - if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE) - sysfs_mbox_idle(phba); - - spin_unlock_irq(&phba->hbalock); - - return count; + return -EPERM; } static struct bin_attribute sysfs_mbox_attr = { @@ -4429,8 +4267,13 @@ lpfc_get_host_port_state(struct Scsi_Host *shost) case LPFC_LINK_UP: case LPFC_CLEAR_LA: case LPFC_HBA_READY: - /* Links up, beyond this port_type reports state */ - fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; + /* Links up, reports port state accordingly */ + if (vport->port_state < LPFC_VPORT_READY) + fc_host_port_state(shost) = + FC_PORTSTATE_BYPASSED; + else + fc_host_port_state(shost) = + FC_PORTSTATE_ONLINE; break; case LPFC_HBA_ERROR: fc_host_port_state(shost) = FC_PORTSTATE_ERROR; diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 6760c69f5253..c13e54760cb1 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -3140,6 +3140,9 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) unsigned long flags; uint32_t size; int rc = 0; + struct lpfc_dmabuf *dmabuf; + struct lpfc_sli_config_mbox *sli_cfg_mbx; + uint8_t *pmbx; spin_lock_irqsave(&phba->ct_ev_lock, flags); dd_data = pmboxq->context1; @@ -3156,7 +3159,19 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) */ pmb = (uint8_t *)&pmboxq->u.mb; pmb_buf = (uint8_t *)dd_data->context_un.mbox.mb; + /* Copy the byte swapped response mailbox back to the user */ memcpy(pmb_buf, pmb, sizeof(MAILBOX_t)); + /* if there is any non-embedded extended data copy that too */ + dmabuf = phba->mbox_ext_buf_ctx.mbx_dmabuf; + sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; + if (!bsg_bf_get(lpfc_mbox_hdr_emb, + &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) { + pmbx = (uint8_t *)dmabuf->virt; + /* byte swap the extended data following the mailbox command */ + lpfc_sli_pcimem_bcopy(&pmbx[sizeof(MAILBOX_t)], + &pmbx[sizeof(MAILBOX_t)], + sli_cfg_mbx->un.sli_config_emb0_subsys.mse[0].buf_len); + } job = dd_data->context_un.mbox.set_job; if (job) { @@ -3519,6 +3534,18 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, /* state change */ phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_PORT; + /* + * Non-embedded mailbox subcommand data gets byte swapped here because + * the lower level driver code only does the first 64 mailbox words. + */ + if ((!bsg_bf_get(lpfc_mbox_hdr_emb, + &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr)) && + (nemb_tp == nemb_mse)) + lpfc_sli_pcimem_bcopy(&pmbx[sizeof(MAILBOX_t)], + &pmbx[sizeof(MAILBOX_t)], + sli_cfg_mbx->un.sli_config_emb0_subsys. + mse[0].buf_len); + rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) { lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, @@ -3575,7 +3602,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, &sli_cfg_mbx->un.sli_config_emb0_subsys.sli_config_hdr); if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_MSE) { lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, - "2953 Handled SLI_CONFIG(mse) wr, " + "2953 Failed SLI_CONFIG(mse) wr, " "ext_buf_cnt(%d) out of range(%d)\n", ext_buf_cnt, LPFC_MBX_SLI_CONFIG_MAX_MSE); @@ -3593,7 +3620,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, ext_buf_cnt = sli_cfg_mbx->un.sli_config_emb1_subsys.hbd_count; if (ext_buf_cnt > LPFC_MBX_SLI_CONFIG_MAX_HBD) { lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, - "2954 Handled SLI_CONFIG(hbd) wr, " + "2954 Failed SLI_CONFIG(hbd) wr, " "ext_buf_cnt(%d) out of range(%d)\n", ext_buf_cnt, LPFC_MBX_SLI_CONFIG_MAX_HBD); @@ -3687,6 +3714,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct fc_bsg_job *job, "2956 Failed to issue SLI_CONFIG ext-buffer " "maibox command, rc:x%x\n", rc); rc = -EPIPE; + goto job_error; } /* wait for additoinal external buffers */ @@ -3721,7 +3749,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t opcode; int rc = SLI_CONFIG_NOT_HANDLED; - /* state change */ + /* state change on new multi-buffer pass-through mailbox command */ phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_HOST; sli_cfg_mbx = (struct lpfc_sli_config_mbox *)dmabuf->virt; @@ -3752,18 +3780,36 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, break; default: lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, - "2959 Not handled SLI_CONFIG " + "2959 Reject SLI_CONFIG " "subsys_fcoe, opcode:x%x\n", opcode); - rc = SLI_CONFIG_NOT_HANDLED; + rc = -EPERM; + break; + } + } else if (subsys == SLI_CONFIG_SUBSYS_COMN) { + switch (opcode) { + case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES: + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3106 Handled SLI_CONFIG " + "subsys_fcoe, opcode:x%x\n", + opcode); + rc = lpfc_bsg_sli_cfg_read_cmd_ext(phba, job, + nemb_mse, dmabuf); + break; + default: + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3107 Reject SLI_CONFIG " + "subsys_fcoe, opcode:x%x\n", + opcode); + rc = -EPERM; break; } } else { lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, - "2977 Handled SLI_CONFIG " + "2977 Reject SLI_CONFIG " "subsys:x%d, opcode:x%x\n", subsys, opcode); - rc = SLI_CONFIG_NOT_HANDLED; + rc = -EPERM; } } else { subsys = bsg_bf_get(lpfc_emb1_subcmnd_subsys, @@ -3799,12 +3845,17 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, } } else { lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, - "2978 Handled SLI_CONFIG " + "2978 Not handled SLI_CONFIG " "subsys:x%d, opcode:x%x\n", subsys, opcode); rc = SLI_CONFIG_NOT_HANDLED; } } + + /* state reset on not handled new multi-buffer mailbox command */ + if (rc != SLI_CONFIG_HANDLED) + phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_IDLE; + return rc; } @@ -4262,11 +4313,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, /* extended mailbox commands will need an extended buffer */ if (mbox_req->inExtWLen || mbox_req->outExtWLen) { - /* any data for the device? */ - if (mbox_req->inExtWLen) { - from = pmbx; - ext = from + sizeof(MAILBOX_t); - } + from = pmbx; + ext = from + sizeof(MAILBOX_t); pmboxq->context2 = ext; pmboxq->in_ext_byte_len = mbox_req->inExtWLen * sizeof(uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h index c8c2b47ea886..edfe61fc52b1 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.h +++ b/drivers/scsi/lpfc/lpfc_bsg.h @@ -96,7 +96,7 @@ struct get_mgmt_rev { }; #define MANAGEMENT_MAJOR_REV 1 -#define MANAGEMENT_MINOR_REV 0 +#define MANAGEMENT_MINOR_REV 1 /* the MgmtRevInfo structure */ struct MgmtRevInfo { @@ -248,6 +248,7 @@ struct lpfc_sli_config_emb1_subsys { #define COMN_OPCODE_WRITE_OBJECT 0xAC #define COMN_OPCODE_READ_OBJECT_LIST 0xAD #define COMN_OPCODE_DELETE_OBJECT 0xAE +#define COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES 0x79 uint32_t timeout; uint32_t request_length; uint32_t word9; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 60f95347babf..f74afa23e0dd 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -26,7 +26,7 @@ void lpfc_sli_read_link_ste(struct lpfc_hba *); void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t, uint16_t); void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); -int lpfc_dump_fcoe_param(struct lpfc_hba *, struct lpfcMboxq *); +int lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *, struct lpfcMboxq *); void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 98d21521f539..447da2a546ae 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -2104,6 +2104,8 @@ struct lpfc_mbx_read_config { #define lpfc_mbx_rd_conf_lnk_type_SHIFT 6 #define lpfc_mbx_rd_conf_lnk_type_MASK 0x00000003 #define lpfc_mbx_rd_conf_lnk_type_WORD word2 +#define LPFC_LNK_TYPE_GE 0 +#define LPFC_LNK_TYPE_FC 1 #define lpfc_mbx_rd_conf_lnk_ldv_SHIFT 8 #define lpfc_mbx_rd_conf_lnk_ldv_MASK 0x00000001 #define lpfc_mbx_rd_conf_lnk_ldv_WORD word2 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 55bc4fc7376f..d247eb015526 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -475,27 +475,6 @@ lpfc_config_port_post(struct lpfc_hba *phba) /* Get the default values for Model Name and Description */ lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc); - if ((phba->cfg_link_speed > LPFC_USER_LINK_SPEED_16G) - || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_1G) - && !(phba->lmt & LMT_1Gb)) - || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_2G) - && !(phba->lmt & LMT_2Gb)) - || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_4G) - && !(phba->lmt & LMT_4Gb)) - || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_8G) - && !(phba->lmt & LMT_8Gb)) - || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G) - && !(phba->lmt & LMT_10Gb)) - || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) - && !(phba->lmt & LMT_16Gb))) { - /* Reset link speed to auto */ - lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, - "1302 Invalid speed for this board: " - "Reset link speed to auto: x%x\n", - phba->cfg_link_speed); - phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; - } - phba->link_state = LPFC_LINK_DOWN; /* Only process IOCBs on ELS ring till hba_state is READY */ @@ -585,28 +564,10 @@ lpfc_config_port_post(struct lpfc_hba *phba) return -EIO; } } else if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) { - lpfc_init_link(phba, pmb, phba->cfg_topology, - phba->cfg_link_speed); - pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - lpfc_set_loopback_flag(phba); - rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); - if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0454 Adapter failed to init, mbxCmd x%x " - "INIT_LINK, mbxStatus x%x\n", - mb->mbxCommand, mb->mbxStatus); - - /* Clear all interrupt enable conditions */ - writel(0, phba->HCregaddr); - readl(phba->HCregaddr); /* flush */ - /* Clear all pending interrupts */ - writel(0xffffffff, phba->HAregaddr); - readl(phba->HAregaddr); /* flush */ - phba->link_state = LPFC_HBA_ERROR; - if (rc != MBX_BUSY) - mempool_free(pmb, phba->mbox_mem_pool); - return -EIO; - } + mempool_free(pmb, phba->mbox_mem_pool); + rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); + if (rc) + return rc; } /* MBOX buffer will be freed in mbox compl */ pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); @@ -681,6 +642,26 @@ lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag) mb = &pmb->u.mb; pmb->vport = vport; + if ((phba->cfg_link_speed > LPFC_USER_LINK_SPEED_MAX) || + ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_1G) && + !(phba->lmt & LMT_1Gb)) || + ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_2G) && + !(phba->lmt & LMT_2Gb)) || + ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_4G) && + !(phba->lmt & LMT_4Gb)) || + ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_8G) && + !(phba->lmt & LMT_8Gb)) || + ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G) && + !(phba->lmt & LMT_10Gb)) || + ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) && + !(phba->lmt & LMT_16Gb))) { + /* Reset link speed to auto */ + lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, + "1302 Invalid speed for this board:%d " + "Reset link speed to auto.\n", + phba->cfg_link_speed); + phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; + } lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; lpfc_set_loopback_flag(phba); @@ -1474,7 +1455,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) /* TODO: Register for Overtemp async events. */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "2889 Port Overtemperature event, " - "taking port\n"); + "taking port offline\n"); spin_lock_irq(&phba->hbalock); phba->over_temp_state = HBA_OVER_TEMP; spin_unlock_irq(&phba->hbalock); @@ -9198,12 +9179,15 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) /* Perform post initialization setup */ lpfc_post_init_setup(phba); - /* check for firmware upgrade or downgrade */ - snprintf(file_name, 16, "%s.grp", phba->ModelName); - error = request_firmware(&fw, file_name, &phba->pcidev->dev); - if (!error) { - lpfc_write_firmware(phba, fw); - release_firmware(fw); + /* check for firmware upgrade or downgrade (if_type 2 only) */ + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_IF_TYPE_2) { + snprintf(file_name, 16, "%s.grp", phba->ModelName); + error = request_firmware(&fw, file_name, &phba->pcidev->dev); + if (!error) { + lpfc_write_firmware(phba, fw); + release_firmware(fw); + } } /* Check if there are static vports to be created. */ diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 2ebc7d2540c0..0228f04061da 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -2175,16 +2175,15 @@ lpfc_unreg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport) } /** - * lpfc_dump_fcoe_param - Dump config region 23 to get FCoe parameters. + * lpfc_sli4_dump_cfg_rg23 - Dump sli4 port config region 23 * @phba: pointer to the hba structure containing. * @mbox: pointer to lpfc mbox command to initialize. * - * This function create a SLI4 dump mailbox command to dump FCoE - * parameters stored in region 23. + * This function create a SLI4 dump mailbox command to dump configure + * region 23. **/ int -lpfc_dump_fcoe_param(struct lpfc_hba *phba, - struct lpfcMboxq *mbox) +lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *phba, struct lpfcMboxq *mbox) { struct lpfc_dmabuf *mp = NULL; MAILBOX_t *mb; @@ -2198,9 +2197,9 @@ lpfc_dump_fcoe_param(struct lpfc_hba *phba, if (!mp || !mp->virt) { kfree(mp); - /* dump_fcoe_param failed to allocate memory */ + /* dump config region 23 failed to allocate memory */ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, - "2569 lpfc_dump_fcoe_param: memory" + "2569 lpfc dump config region 23: memory" " allocation failed\n"); return 1; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4d4104f38c98..1be13e757eda 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4566,7 +4566,7 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba, phba->fc_map[2] = LPFC_FCOE_FCF_MAP2; mqe = &mboxq->u.mqe; - if (lpfc_dump_fcoe_param(phba, mboxq)) + if (lpfc_sli4_dump_cfg_rg23(phba, mboxq)) return -ENOMEM; mp = (struct lpfc_dmabuf *) mboxq->context1; @@ -6205,7 +6205,11 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) rc = 0; phba->fcf.fcfi = bf_get(lpfc_reg_fcfi_fcfi, &mboxq->u.mqe.un.reg_fcfi); + + /* Check if the port is configured to be disabled */ + lpfc_sli_read_link_ste(phba); } + /* * The port is ready, set the host's link state to LINK_DOWN * in preparation for link interrupts. @@ -6213,7 +6217,19 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); phba->link_state = LPFC_LINK_DOWN; spin_unlock_irq(&phba->hbalock); - if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) { + if (!(phba->hba_flag & HBA_FCOE_MODE) && + (phba->hba_flag & LINK_DISABLED)) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI, + "3103 Adapter Link is disabled.\n"); + lpfc_down_link(phba, mboxq); + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + if (rc != MBX_SUCCESS) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI, + "3104 Adapter failed to issue " + "DOWN_LINK mbox cmd, rc:x%x\n", rc); + goto out_unset_queue; + } + } else if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) { rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); if (rc) goto out_unset_queue; @@ -15252,45 +15268,42 @@ lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *phba) } /** - * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled. + * lpfc_sli_get_config_region23 - Get sli3 port region 23 data. * @phba: pointer to lpfc hba data structure. + * @rgn23_data: pointer to configure region 23 data. * - * This function read region 23 and parse TLV for port status to - * decide if the user disaled the port. If the TLV indicates the - * port is disabled, the hba_flag is set accordingly. + * This function gets SLI3 port configure region 23 data through memory dump + * mailbox command. When it successfully retrieves data, the size of the data + * will be returned, otherwise, 0 will be returned. **/ -void -lpfc_sli_read_link_ste(struct lpfc_hba *phba) +static uint32_t +lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data) { LPFC_MBOXQ_t *pmb = NULL; MAILBOX_t *mb; - uint8_t *rgn23_data = NULL; - uint32_t offset = 0, data_size, sub_tlv_len, tlv_offset; + uint32_t offset = 0; int rc; + if (!rgn23_data) + return 0; + pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2600 lpfc_sli_read_serdes_param failed to" - " allocate mailbox memory\n"); - goto out; + "2600 failed to allocate mailbox memory\n"); + return 0; } mb = &pmb->u.mb; - /* Get adapter Region 23 data */ - rgn23_data = kzalloc(DMP_RGN23_SIZE, GFP_KERNEL); - if (!rgn23_data) - goto out; - do { lpfc_dump_mem(phba, pmb, offset, DMP_REGION_23); rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "2601 lpfc_sli_read_link_ste failed to" - " read config region 23 rc 0x%x Status 0x%x\n", - rc, mb->mbxStatus); + "2601 failed to read config " + "region 23, rc 0x%x Status 0x%x\n", + rc, mb->mbxStatus); mb->un.varDmp.word_cnt = 0; } /* @@ -15303,13 +15316,96 @@ lpfc_sli_read_link_ste(struct lpfc_hba *phba) mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset; lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, - rgn23_data + offset, - mb->un.varDmp.word_cnt); + rgn23_data + offset, + mb->un.varDmp.word_cnt); offset += mb->un.varDmp.word_cnt; } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE); - data_size = offset; - offset = 0; + mempool_free(pmb, phba->mbox_mem_pool); + return offset; +} + +/** + * lpfc_sli4_get_config_region23 - Get sli4 port region 23 data. + * @phba: pointer to lpfc hba data structure. + * @rgn23_data: pointer to configure region 23 data. + * + * This function gets SLI4 port configure region 23 data through memory dump + * mailbox command. When it successfully retrieves data, the size of the data + * will be returned, otherwise, 0 will be returned. + **/ +static uint32_t +lpfc_sli4_get_config_region23(struct lpfc_hba *phba, char *rgn23_data) +{ + LPFC_MBOXQ_t *mboxq = NULL; + struct lpfc_dmabuf *mp = NULL; + struct lpfc_mqe *mqe; + uint32_t data_length = 0; + int rc; + + if (!rgn23_data) + return 0; + + mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mboxq) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3105 failed to allocate mailbox memory\n"); + return 0; + } + + if (lpfc_sli4_dump_cfg_rg23(phba, mboxq)) + goto out; + mqe = &mboxq->u.mqe; + mp = (struct lpfc_dmabuf *) mboxq->context1; + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + if (rc) + goto out; + data_length = mqe->un.mb_words[5]; + if (data_length == 0) + goto out; + if (data_length > DMP_RGN23_SIZE) { + data_length = 0; + goto out; + } + lpfc_sli_pcimem_bcopy((char *)mp->virt, rgn23_data, data_length); +out: + mempool_free(mboxq, phba->mbox_mem_pool); + if (mp) { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } + return data_length; +} + +/** + * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled. + * @phba: pointer to lpfc hba data structure. + * + * This function read region 23 and parse TLV for port status to + * decide if the user disaled the port. If the TLV indicates the + * port is disabled, the hba_flag is set accordingly. + **/ +void +lpfc_sli_read_link_ste(struct lpfc_hba *phba) +{ + uint8_t *rgn23_data = NULL; + uint32_t if_type, data_size, sub_tlv_len, tlv_offset; + uint32_t offset = 0; + + /* Get adapter Region 23 data */ + rgn23_data = kzalloc(DMP_RGN23_SIZE, GFP_KERNEL); + if (!rgn23_data) + goto out; + + if (phba->sli_rev < LPFC_SLI_REV4) + data_size = lpfc_sli_get_config_region23(phba, rgn23_data); + else { + if_type = bf_get(lpfc_sli_intf_if_type, + &phba->sli4_hba.sli_intf); + if (if_type == LPFC_SLI_INTF_IF_TYPE_0) + goto out; + data_size = lpfc_sli4_get_config_region23(phba, rgn23_data); + } if (!data_size) goto out; @@ -15373,9 +15469,8 @@ lpfc_sli_read_link_ste(struct lpfc_hba *phba) goto out; } } + out: - if (pmb) - mempool_free(pmb, phba->mbox_mem_pool); kfree(rgn23_data); return; } -- cgit From ff78d8f97c85a568c0799b06137a4171db45b923 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 13 Dec 2011 13:21:35 -0500 Subject: [SCSI] lpfc 8.3.28: SLI fixes and added SLI4 support Adapter (SLI) interface fixes: - Modify WQ handling to use entry_repost (CR 123981) - Fix for ABTS. Do not free original IOCB whenever ABTS fails. (CR 115829) - Check board for FCoE before reading FCoE paramaters (CR124731) - Add support for SLI4 FC Loop mode (CR 124721) - Add support for resource count changes during fw reset. (CR 125888, 125675) - Increase CQE count from 256 to 1024. (CR 126149) Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 23 +++++ drivers/scsi/lpfc/lpfc_crtn.h | 2 + drivers/scsi/lpfc/lpfc_els.c | 18 ++-- drivers/scsi/lpfc/lpfc_hbadisc.c | 1 - drivers/scsi/lpfc/lpfc_init.c | 52 ++++++++--- drivers/scsi/lpfc/lpfc_sli.c | 184 +++++++++++++++++---------------------- drivers/scsi/lpfc/lpfc_sli4.h | 2 +- 7 files changed, 156 insertions(+), 126 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 7bf492e156d9..f6697cb0e216 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2777,6 +2777,14 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr, if (val >= 0 && val <= 6) { prev_val = phba->cfg_topology; phba->cfg_topology = val; + if (phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G && + val == 4) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "3113 Loop mode not supported at speed %d\n", + phba->cfg_link_speed); + phba->cfg_topology = prev_val; + return -EINVAL; + } if (nolip) return strlen(buf); @@ -3222,6 +3230,14 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, val); return -EINVAL; } + if (val == LPFC_USER_LINK_SPEED_16G && + phba->fc_topology == LPFC_TOPOLOGY_LOOP) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3112 lpfc_link_speed attribute cannot be set " + "to %d. Speed is not supported in loop mode.\n", + val); + return -EINVAL; + } if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) && (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) { prev_val = phba->cfg_link_speed; @@ -3266,6 +3282,13 @@ lpfc_param_show(link_speed) static int lpfc_link_speed_init(struct lpfc_hba *phba, int val) { + if (val == LPFC_USER_LINK_SPEED_16G && phba->cfg_topology == 4) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3111 lpfc_link_speed of %d cannot " + "support loop mode, setting topology to default.\n", + val); + phba->cfg_topology = 0; + } if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) && (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) { phba->cfg_link_speed = val; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index f74afa23e0dd..9237ff154234 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -453,3 +453,5 @@ int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *); int lpfc_sli4_queue_create(struct lpfc_hba *); void lpfc_sli4_queue_destroy(struct lpfc_hba *); +int lpfc_sli4_read_config(struct lpfc_hba *phba); +int lpfc_scsi_buf_update(struct lpfc_hba *phba); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 445826a4c981..846ebfd37b5e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -909,15 +909,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ if (phba->alpa_map[0] == 0) { vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; - if ((phba->sli_rev == LPFC_SLI_REV4) && - (!(vport->fc_flag & FC_VFI_REGISTERED) || - (vport->fc_prevDID != vport->fc_myDID))) { - if (vport->fc_flag & FC_VFI_REGISTERED) - lpfc_sli4_unreg_all_rpis(vport); - lpfc_issue_reg_vfi(vport); - lpfc_nlp_put(ndlp); - goto out; - } + } + if ((phba->sli_rev == LPFC_SLI_REV4) && + (!(vport->fc_flag & FC_VFI_REGISTERED) || + (vport->fc_prevDID != vport->fc_myDID))) { + if (vport->fc_flag & FC_VFI_REGISTERED) + lpfc_sli4_unreg_all_rpis(vport); + lpfc_issue_reg_vfi(vport); + lpfc_nlp_put(ndlp); + goto out; } goto flogifail; } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 091f68e5cb70..cf4408f9a2cb 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -2858,7 +2858,6 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if (vport->port_state == LPFC_FABRIC_CFG_LINK) { /* For private loop just start discovery and we are done. */ if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && - (phba->alpa_map[0] == 0) && !(vport->fc_flag & FC_PUBLIC_LOOP)) { /* Use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index d247eb015526..6096c9a091d1 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -62,7 +62,6 @@ static int lpfc_post_rcv_buf(struct lpfc_hba *); static int lpfc_sli4_queue_verify(struct lpfc_hba *); static int lpfc_create_bootstrap_mbox(struct lpfc_hba *); static int lpfc_setup_endian_order(struct lpfc_hba *); -static int lpfc_sli4_read_config(struct lpfc_hba *); static void lpfc_destroy_bootstrap_mbox(struct lpfc_hba *); static void lpfc_free_sgl_list(struct lpfc_hba *); static int lpfc_init_sgl_list(struct lpfc_hba *); @@ -2654,6 +2653,32 @@ lpfc_offline(struct lpfc_hba *phba) lpfc_destroy_vport_work_array(phba, vports); } +/** + * lpfc_scsi_buf_update - Update the scsi_buffers that are already allocated. + * @phba: pointer to lpfc hba data structure. + * + * This routine goes through all the scsi buffers in the system and updates the + * Physical XRIs assigned to the SCSI buffer because these may change after any + * firmware reset + * + * Return codes + * 0 - successful (for now, it always returns 0) + **/ +int +lpfc_scsi_buf_update(struct lpfc_hba *phba) +{ + struct lpfc_scsi_buf *sb, *sb_next; + + spin_lock_irq(&phba->hbalock); + spin_lock(&phba->scsi_buf_list_lock); + list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) + sb->cur_iocbq.sli4_xritag = + phba->sli4_hba.xri_ids[sb->cur_iocbq.sli4_lxritag]; + spin_unlock(&phba->scsi_buf_list_lock); + spin_unlock_irq(&phba->hbalock); + return 0; +} + /** * lpfc_scsi_free - Free all the SCSI buffers and IOCBs from driver lists * @phba: pointer to lpfc hba data structure. @@ -5021,15 +5046,8 @@ lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba) struct lpfc_rpi_hdr *rpi_hdr; INIT_LIST_HEAD(&phba->sli4_hba.lpfc_rpi_hdr_list); - /* - * If the SLI4 port supports extents, posting the rpi header isn't - * required. Set the expected maximum count and let the actual value - * get set when extents are fully allocated. - */ - if (!phba->sli4_hba.rpi_hdrs_in_use) { - phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.max_rpi; + if (!phba->sli4_hba.rpi_hdrs_in_use) return rc; - } if (phba->sli4_hba.extents_in_use) return -EIO; @@ -5923,7 +5941,7 @@ lpfc_destroy_bootstrap_mbox(struct lpfc_hba *phba) * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ -static int +int lpfc_sli4_read_config(struct lpfc_hba *phba) { LPFC_MBOXQ_t *pmb; @@ -5955,6 +5973,20 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) rc = -EIO; } else { rd_config = &pmb->u.mqe.un.rd_config; + if (bf_get(lpfc_mbx_rd_conf_lnk_ldv, rd_config)) { + phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL; + phba->sli4_hba.lnk_info.lnk_tp = + bf_get(lpfc_mbx_rd_conf_lnk_type, rd_config); + phba->sli4_hba.lnk_info.lnk_no = + bf_get(lpfc_mbx_rd_conf_lnk_numb, rd_config); + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "3081 lnk_type:%d, lnk_numb:%d\n", + phba->sli4_hba.lnk_info.lnk_tp, + phba->sli4_hba.lnk_info.lnk_no); + } else + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3082 Mailbox (x%x) returned ldv:x0\n", + bf_get(lpfc_mqe_command, &pmb->u.mqe)); phba->sli4_hba.extents_in_use = bf_get(lpfc_mbx_rd_conf_extnts_inuse, rd_config); phba->sli4_hba.max_cfg_param.max_xri = diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 1be13e757eda..4c4d77356bb2 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -97,7 +97,7 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) if (((q->host_index + 1) % q->entry_count) == q->hba_index) return -ENOMEM; /* set consumption flag every once in a while */ - if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL)) + if (!((q->host_index + 1) % q->entry_repost)) bf_set(wqe_wqec, &wqe->generic.wqe_com, 1); if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); @@ -4551,9 +4551,9 @@ lpfc_sli_hba_setup_error: * data structure. **/ static int -lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba, - LPFC_MBOXQ_t *mboxq) +lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba) { + LPFC_MBOXQ_t *mboxq; struct lpfc_dmabuf *mp; struct lpfc_mqe *mqe; uint32_t data_length; @@ -4565,10 +4565,16 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba, phba->fc_map[1] = LPFC_FCOE_FCF_MAP1; phba->fc_map[2] = LPFC_FCOE_FCF_MAP2; - mqe = &mboxq->u.mqe; - if (lpfc_sli4_dump_cfg_rg23(phba, mboxq)) + mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mboxq) return -ENOMEM; + mqe = &mboxq->u.mqe; + if (lpfc_sli4_dump_cfg_rg23(phba, mboxq)) { + rc = -ENOMEM; + goto out_free_mboxq; + } + mp = (struct lpfc_dmabuf *) mboxq->context1; rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); @@ -4596,19 +4602,25 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba, if (rc) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); - return -EIO; + rc = -EIO; + goto out_free_mboxq; } data_length = mqe->un.mb_words[5]; if (data_length > DMP_RGN23_SIZE) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); - return -EIO; + rc = -EIO; + goto out_free_mboxq; } lpfc_parse_fcoe_conf(phba, mp->virt, data_length); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); - return 0; + rc = 0; + +out_free_mboxq: + mempool_free(mboxq, phba->mbox_mem_pool); + return rc; } /** @@ -4706,7 +4718,6 @@ static int lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba) { LPFC_MBOXQ_t *mboxq; - struct lpfc_mbx_read_config *rd_config; struct lpfc_mbx_get_cntl_attributes *mbx_cntl_attr; struct lpfc_controller_attribute *cntl_attr; struct lpfc_mbx_get_port_name *get_port_name; @@ -4724,33 +4735,11 @@ lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba) mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) return -ENOMEM; - /* obtain link type and link number via READ_CONFIG */ - lpfc_read_config(phba, mboxq); - rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); - if (rc == MBX_SUCCESS) { - rd_config = &mboxq->u.mqe.un.rd_config; - if (bf_get(lpfc_mbx_rd_conf_lnk_ldv, rd_config)) { - phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_VAL; - phba->sli4_hba.lnk_info.lnk_tp = - bf_get(lpfc_mbx_rd_conf_lnk_type, rd_config); - phba->sli4_hba.lnk_info.lnk_no = - bf_get(lpfc_mbx_rd_conf_lnk_numb, rd_config); - lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "3081 lnk_type:%d, lnk_numb:%d\n", - phba->sli4_hba.lnk_info.lnk_tp, - phba->sli4_hba.lnk_info.lnk_no); - goto retrieve_ppname; - } else - lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "3082 Mailbox (x%x) returned ldv:x0\n", - bf_get(lpfc_mqe_command, - &mboxq->u.mqe)); - } else - lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "3083 Mailbox (x%x) failed, status:x%x\n", - bf_get(lpfc_mqe_command, &mboxq->u.mqe), - bf_get(lpfc_mqe_status, &mboxq->u.mqe)); + phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_INVAL; + lpfc_sli4_read_config(phba); + if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL) + goto retrieve_ppname; /* obtain link type and link number via COMMON_GET_CNTL_ATTRIBUTES */ reqlen = sizeof(struct lpfc_mbx_get_cntl_attributes); @@ -5457,6 +5446,8 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) uint16_t count, base; unsigned long longs; + if (!phba->sli4_hba.rpi_hdrs_in_use) + phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.max_rpi; if (phba->sli4_hba.extents_in_use) { /* * The port supports resource extents. The XRI, VPI, VFI, RPI @@ -5538,9 +5529,10 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) * need any action - just exit. */ if (bf_get(lpfc_idx_rsrc_rdy, &phba->sli4_hba.sli4_flags) == - LPFC_IDX_RSRC_RDY) - return 0; - + LPFC_IDX_RSRC_RDY) { + lpfc_sli4_dealloc_resource_identifiers(phba); + lpfc_sli4_remove_rpis(phba); + } /* RPIs. */ count = phba->sli4_hba.max_cfg_param.max_rpi; base = phba->sli4_hba.max_cfg_param.rpi_base; @@ -5880,14 +5872,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) if (!mboxq) return -ENOMEM; - /* - * Continue initialization with default values even if driver failed - * to read FCoE param config regions - */ - if (lpfc_sli4_read_fcoe_params(phba, mboxq)) - lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_INIT, - "2570 Failed to read FCoE parameters\n"); - /* Issue READ_REV to collect vpd and FW information. */ vpd_size = SLI4_PAGE_SIZE; vpd = kzalloc(vpd_size, GFP_KERNEL); @@ -5924,6 +5908,16 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) goto out_free_mbox; } + /* + * Continue initialization with default values even if driver failed + * to read FCoE param config regions, only read parameters if the + * board is FCoE + */ + if (phba->hba_flag & HBA_FCOE_MODE && + lpfc_sli4_read_fcoe_params(phba)) + lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_INIT, + "2570 Failed to read FCoE parameters\n"); + /* * Retrieve sli4 device physical port name, failure of doing it * is considered as non-fatal. @@ -6044,6 +6038,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) "rc = x%x\n", rc); goto out_free_mbox; } + /* update physical xri mappings in the scsi buffers */ + lpfc_scsi_buf_update(phba); /* Read the port's service parameters. */ rc = lpfc_read_sparam(phba, mboxq, vport->vpi); @@ -7632,6 +7628,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, int numBdes, i; struct ulp_bde64 bde; struct lpfc_nodelist *ndlp; + uint32_t *pcmd; fip = phba->hba_flag & HBA_FIP_SUPPORT; /* The fcp commands will set command type */ @@ -7685,6 +7682,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->iocb.ulpCommand); return IOCB_ERROR; } + wqe->els_req.payload_len = xmit_len; /* Els_reguest64 has a TMO */ bf_set(wqe_tmo, &wqe->els_req.wqe_com, @@ -7699,9 +7697,25 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, bf_set(wqe_ct, &wqe->els_req.wqe_com, ct); bf_set(wqe_pu, &wqe->els_req.wqe_com, 0); /* CCP CCPE PV PRI in word10 were set in the memcpy */ - if (command_type == ELS_COMMAND_FIP) { + if (command_type == ELS_COMMAND_FIP) els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) >> LPFC_FIP_ELS_ID_SHIFT); + pcmd = (uint32_t *) (((struct lpfc_dmabuf *) + iocbq->context2)->virt); + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { + if (pcmd && (*pcmd == ELS_CMD_FLOGI || + *pcmd == ELS_CMD_PLOGI)) { + bf_set(els_req64_sp, &wqe->els_req, 1); + bf_set(els_req64_sid, &wqe->els_req, + iocbq->vport->fc_myDID); + bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + phba->vpi_ids[phba->pport->vpi]); + } else if (iocbq->context1) { + bf_set(wqe_ct, &wqe->els_req.wqe_com, 0); + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); + } } bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); @@ -7862,6 +7876,16 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]); + pcmd = (uint32_t *) (((struct lpfc_dmabuf *) + iocbq->context2)->virt); + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { + bf_set(els_req64_sp, &wqe->els_req, 1); + bf_set(els_req64_sid, &wqe->els_req, + iocbq->vport->fc_myDID); + bf_set(wqe_ct, &wqe->els_req.wqe_com, 1); + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + phba->vpi_ids[phba->pport->vpi]); + } command_type = OTHER_COMMAND; break; case CMD_CLOSE_XRI_CN: @@ -8839,12 +8863,14 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, { IOCB_t *irsp = &rspiocb->iocb; uint16_t abort_iotag, abort_context; - struct lpfc_iocbq *abort_iocb; - struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; - - abort_iocb = NULL; + struct lpfc_iocbq *abort_iocb = NULL; if (irsp->ulpStatus) { + + /* + * Assume that the port already completed and returned, or + * will return the iocb. Just Log the message. + */ abort_context = cmdiocb->iocb.un.acxri.abortContextTag; abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag; @@ -8862,68 +8888,15 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ abort_iocb = phba->sli.iocbq_lookup[abort_context]; - /* - * If the iocb is not found in Firmware queue the iocb - * might have completed already. Do not free it again. - */ - if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) { - if (irsp->un.ulpWord[4] != IOERR_NO_XRI) { - spin_unlock_irq(&phba->hbalock); - lpfc_sli_release_iocbq(phba, cmdiocb); - return; - } - /* For SLI4 the ulpContext field for abort IOCB - * holds the iotag of the IOCB being aborted so - * the local abort_context needs to be reset to - * match the aborted IOCBs ulpContext. - */ - if (abort_iocb && phba->sli_rev == LPFC_SLI_REV4) - abort_context = abort_iocb->iocb.ulpContext; - } - lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_SLI, "0327 Cannot abort els iocb %p " "with tag %x context %x, abort status %x, " "abort code %x\n", abort_iocb, abort_iotag, abort_context, irsp->ulpStatus, irsp->un.ulpWord[4]); - /* - * make sure we have the right iocbq before taking it - * off the txcmplq and try to call completion routine. - */ - if (!abort_iocb || - abort_iocb->iocb.ulpContext != abort_context || - (abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) == 0) - spin_unlock_irq(&phba->hbalock); - else if (phba->sli_rev < LPFC_SLI_REV4) { - /* - * leave the SLI4 aborted command on the txcmplq - * list and the command complete WCQE's XB bit - * will tell whether the SGL (XRI) can be released - * immediately or to the aborted SGL list for the - * following abort XRI from the HBA. - */ - list_del_init(&abort_iocb->list); - if (abort_iocb->iocb_flag & LPFC_IO_ON_Q) { - abort_iocb->iocb_flag &= ~LPFC_IO_ON_Q; - pring->txcmplq_cnt--; - } - - /* Firmware could still be in progress of DMAing - * payload, so don't free data buffer till after - * a hbeat. - */ - abort_iocb->iocb_flag |= LPFC_DELAY_MEM_FREE; - abort_iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; - spin_unlock_irq(&phba->hbalock); - abort_iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; - abort_iocb->iocb.un.ulpWord[4] = IOERR_ABORT_REQUESTED; - (abort_iocb->iocb_cmpl)(phba, abort_iocb, abort_iocb); - } else - spin_unlock_irq(&phba->hbalock); + spin_unlock_irq(&phba->hbalock); } - lpfc_sli_release_iocbq(phba, cmdiocb); return; } @@ -12167,6 +12140,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, wq->subtype = subtype; wq->host_index = 0; wq->hba_index = 0; + wq->entry_repost = LPFC_RELEASE_NOTIFICATION_INTERVAL; /* link the wq onto the parent cq child list */ list_add_tail(&wq->list, &cq->child_list); diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index d5cffd8af340..7d444c444db4 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -291,7 +291,7 @@ struct lpfc_bmbx { #define LPFC_RQE_SIZE 8 #define LPFC_EQE_DEF_COUNT 1024 -#define LPFC_CQE_DEF_COUNT 256 +#define LPFC_CQE_DEF_COUNT 1024 #define LPFC_WQE_DEF_COUNT 256 #define LPFC_MQE_DEF_COUNT 16 #define LPFC_RQE_DEF_COUNT 512 -- cgit From cb69f7decc3777822b240c46890a209df288c7bb Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 13 Dec 2011 13:21:57 -0500 Subject: [SCSI] lpfc 8.3.28: Add support for ABTS failure handling Add support for ABTS failure handling: - Add asynchronous ABTS notification event feature to driver (CR 124578) - Change driver message 3092 and 3116 to KERN_WARNING (CR 124768) - Alter the SCR ELS command to use the temporary RPI and the Destination DID for SLI4-FC (CR 126070) Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_crtn.h | 4 +- drivers/scsi/lpfc/lpfc_els.c | 50 --------- drivers/scsi/lpfc/lpfc_hbadisc.c | 67 ++++++++++++ drivers/scsi/lpfc/lpfc_hw.h | 13 ++- drivers/scsi/lpfc/lpfc_mbox.c | 4 + drivers/scsi/lpfc/lpfc_scsi.c | 4 +- drivers/scsi/lpfc/lpfc_sli.c | 214 ++++++++++++++++++++++++++++++++------- 7 files changed, 263 insertions(+), 93 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 9237ff154234..bcc021f3c8eb 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -106,7 +106,7 @@ void lpfc_cleanup(struct lpfc_vport *); void lpfc_disc_timeout(unsigned long); struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); - +struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t); void lpfc_worker_wake_up(struct lpfc_hba *); int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t); int lpfc_do_work(void *); @@ -455,3 +455,5 @@ int lpfc_sli4_queue_create(struct lpfc_hba *); void lpfc_sli4_queue_destroy(struct lpfc_hba *); int lpfc_sli4_read_config(struct lpfc_hba *phba); int lpfc_scsi_buf_update(struct lpfc_hba *phba); +void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *, + struct sli4_wcqe_xri_aborted *); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 846ebfd37b5e..46876941bac6 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -6595,56 +6595,6 @@ dropit: phba->fc_stat.elsRcvDrop++; } -/** - * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier - * @phba: pointer to lpfc hba data structure. - * @vpi: host virtual N_Port identifier. - * - * This routine finds a vport on a HBA (referred by @phba) through a - * @vpi. The function walks the HBA's vport list and returns the address - * of the vport with the matching @vpi. - * - * Return code - * NULL - No vport with the matching @vpi found - * Otherwise - Address to the vport with the matching @vpi. - **/ -struct lpfc_vport * -lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) -{ - struct lpfc_vport *vport; - unsigned long flags; - int i = 0; - - /* The physical ports are always vpi 0 - translate is unnecessary. */ - if (vpi > 0) { - /* - * Translate the physical vpi to the logical vpi. The - * vport stores the logical vpi. - */ - for (i = 0; i < phba->max_vpi; i++) { - if (vpi == phba->vpi_ids[i]) - break; - } - - if (i >= phba->max_vpi) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "2936 Could not find Vport mapped " - "to vpi %d\n", vpi); - return NULL; - } - } - - spin_lock_irqsave(&phba->hbalock, flags); - list_for_each_entry(vport, &phba->port_list, listentry) { - if (vport->vpi == i) { - spin_unlock_irqrestore(&phba->hbalock, flags); - return vport; - } - } - spin_unlock_irqrestore(&phba->hbalock, flags); - return NULL; -} - /** * lpfc_els_unsol_event - Process an unsolicited event from an els sli ring * @phba: pointer to lpfc hba data structure. diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index cf4408f9a2cb..99c76677e394 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -5352,6 +5352,73 @@ lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn) return ndlp; } +/* + * This routine looks up the ndlp lists for the given RPI. If the rpi + * is found, the routine returns the node element list pointer else + * return NULL. + */ +struct lpfc_nodelist * +lpfc_findnode_rpi(struct lpfc_vport *vport, uint16_t rpi) +{ + struct Scsi_Host *shost = lpfc_shost_from_vport(vport); + struct lpfc_nodelist *ndlp; + + spin_lock_irq(shost->host_lock); + ndlp = __lpfc_findnode_rpi(vport, rpi); + spin_unlock_irq(shost->host_lock); + return ndlp; +} + +/** + * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier + * @phba: pointer to lpfc hba data structure. + * @vpi: the physical host virtual N_Port identifier. + * + * This routine finds a vport on a HBA (referred by @phba) through a + * @vpi. The function walks the HBA's vport list and returns the address + * of the vport with the matching @vpi. + * + * Return code + * NULL - No vport with the matching @vpi found + * Otherwise - Address to the vport with the matching @vpi. + **/ +struct lpfc_vport * +lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) +{ + struct lpfc_vport *vport; + unsigned long flags; + int i = 0; + + /* The physical ports are always vpi 0 - translate is unnecessary. */ + if (vpi > 0) { + /* + * Translate the physical vpi to the logical vpi. The + * vport stores the logical vpi. + */ + for (i = 0; i < phba->max_vpi; i++) { + if (vpi == phba->vpi_ids[i]) + break; + } + + if (i >= phba->max_vpi) { + lpfc_printf_log(phba, KERN_ERR, LOG_ELS, + "2936 Could not find Vport mapped " + "to vpi %d\n", vpi); + return NULL; + } + } + + spin_lock_irqsave(&phba->hbalock, flags); + list_for_each_entry(vport, &phba->port_list, listentry) { + if (vport->vpi == i) { + spin_unlock_irqrestore(&phba->hbalock, flags); + return vport; + } + } + spin_unlock_irqrestore(&phba->hbalock, flags); + return NULL; +} + void lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint32_t did) diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 046edc4ab35f..2dd464b0f29e 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -2819,7 +2819,8 @@ typedef struct { #ifdef __BIG_ENDIAN_BITFIELD uint32_t rsvd1 : 19; /* Reserved */ uint32_t cdss : 1; /* Configure Data Security SLI */ - uint32_t rsvd2 : 3; /* Reserved */ + uint32_t casabt : 1; /* Configure async abts status notice */ + uint32_t rsvd2 : 2; /* Reserved */ uint32_t cbg : 1; /* Configure BlockGuard */ uint32_t cmv : 1; /* Configure Max VPIs */ uint32_t ccrp : 1; /* Config Command Ring Polling */ @@ -2839,14 +2840,16 @@ typedef struct { uint32_t ccrp : 1; /* Config Command Ring Polling */ uint32_t cmv : 1; /* Configure Max VPIs */ uint32_t cbg : 1; /* Configure BlockGuard */ - uint32_t rsvd2 : 3; /* Reserved */ + uint32_t rsvd2 : 2; /* Reserved */ + uint32_t casabt : 1; /* Configure async abts status notice */ uint32_t cdss : 1; /* Configure Data Security SLI */ uint32_t rsvd1 : 19; /* Reserved */ #endif #ifdef __BIG_ENDIAN_BITFIELD uint32_t rsvd3 : 19; /* Reserved */ uint32_t gdss : 1; /* Configure Data Security SLI */ - uint32_t rsvd4 : 3; /* Reserved */ + uint32_t gasabt : 1; /* Grant async abts status notice */ + uint32_t rsvd4 : 2; /* Reserved */ uint32_t gbg : 1; /* Grant BlockGuard */ uint32_t gmv : 1; /* Grant Max VPIs */ uint32_t gcrp : 1; /* Grant Command Ring Polling */ @@ -2866,7 +2869,8 @@ typedef struct { uint32_t gcrp : 1; /* Grant Command Ring Polling */ uint32_t gmv : 1; /* Grant Max VPIs */ uint32_t gbg : 1; /* Grant BlockGuard */ - uint32_t rsvd4 : 3; /* Reserved */ + uint32_t rsvd4 : 2; /* Reserved */ + uint32_t gasabt : 1; /* Grant async abts status notice */ uint32_t gdss : 1; /* Configure Data Security SLI */ uint32_t rsvd3 : 19; /* Reserved */ #endif @@ -3465,6 +3469,7 @@ typedef struct { } ASYNCSTAT_FIELDS; #define ASYNC_TEMP_WARN 0x100 #define ASYNC_TEMP_SAFE 0x101 +#define ASYNC_STATUS_CN 0x102 /* IOCB Command template for CMD_IOCB_RCV_ELS64_CX (0xB7) or CMD_IOCB_RCV_SEQ64_CX (0xB5) */ diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 0228f04061da..328782efc839 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -1293,6 +1293,10 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) phba->sli_rev = LPFC_SLI_REV2; mb->un.varCfgPort.sli_mode = phba->sli_rev; + /* If this is an SLI3 port, configure async status notification. */ + if (phba->sli_rev == LPFC_SLI_REV3) + mb->un.varCfgPort.casabt = 1; + /* Now setup pcb */ phba->pcb->type = TYPE_NATIVE_SLI2; phba->pcb->feature = FEATURE_INITIAL_SLI2; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 2e1e54e5c3ae..f1af3f9dead4 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -681,8 +681,10 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, rrq_empty = list_empty(&phba->active_rrq_list); spin_unlock_irqrestore(&phba->hbalock, iflag); - if (ndlp) + if (ndlp) { lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1); + lpfc_sli4_abts_err_handler(phba, ndlp, axri); + } lpfc_release_scsi_buf_s4(phba, psb); if (rrq_empty) lpfc_worker_wake_up(phba); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4c4d77356bb2..97bbafb21bc2 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4339,6 +4339,11 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->sli.sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK; spin_unlock_irq(&phba->hbalock); done = 1; + + if ((pmb->u.mb.un.varCfgPort.casabt == 1) && + (pmb->u.mb.un.varCfgPort.gasabt == 0)) + lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, + "3110 Port did not grant ASABT\n"); } } if (!done) { @@ -7704,6 +7709,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->context2)->virt); if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { if (pcmd && (*pcmd == ELS_CMD_FLOGI || + *pcmd == ELS_CMD_SCR || *pcmd == ELS_CMD_PLOGI)) { bf_set(els_req64_sp, &wqe->els_req, 1); bf_set(els_req64_sid, &wqe->els_req, @@ -8213,6 +8219,137 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) return 0; } +/* lpfc_sli_abts_recover_port - Recover a port that failed an ABTS. + * @vport: pointer to virtual port object. + * @ndlp: nodelist pointer for the impacted rport. + * + * The driver calls this routine in response to a XRI ABORT CQE + * event from the port. In this event, the driver is required to + * recover its login to the rport even though its login may be valid + * from the driver's perspective. The failed ABTS notice from the + * port indicates the rport is not responding. + */ +static void +lpfc_sli_abts_recover_port(struct lpfc_vport *vport, + struct lpfc_nodelist *ndlp) +{ + struct Scsi_Host *shost; + struct lpfc_hba *phba; + unsigned long flags = 0; + + shost = lpfc_shost_from_vport(vport); + phba = vport->phba; + if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) { + lpfc_printf_log(phba, KERN_INFO, + LOG_SLI, "3093 No rport recovery needed. " + "rport in state 0x%x\n", + ndlp->nlp_state); + return; + } + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "3094 Start rport recovery on shost id 0x%x " + "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x " + "flags 0x%x\n", + shost->host_no, ndlp->nlp_DID, + vport->vpi, ndlp->nlp_rpi, ndlp->nlp_state, + ndlp->nlp_flag); + /* + * The rport is not responding. Don't attempt ADISC recovery. + * Remove the FCP-2 flag to force a PLOGI. + */ + spin_lock_irqsave(shost->host_lock, flags); + ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; + spin_unlock_irqrestore(shost->host_lock, flags); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RECOVERY); + lpfc_cancel_retry_delay_tmo(vport, ndlp); + spin_lock_irqsave(shost->host_lock, flags); + ndlp->nlp_flag |= NLP_NPR_2B_DISC; + spin_unlock_irqrestore(shost->host_lock, flags); + lpfc_disc_start(vport); +} + +/* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port. + * @phba: Pointer to HBA context object. + * @iocbq: Pointer to iocb object. + * + * The async_event handler calls this routine when it receives + * an ASYNC_STATUS_CN event from the port. The port generates + * this event when an Abort Sequence request to an rport fails + * twice in succession. The abort could be originated by the + * driver or by the port. The ABTS could have been for an ELS + * or FCP IO. The port only generates this event when an ABTS + * fails to complete after one retry. + */ +static void +lpfc_sli_abts_err_handler(struct lpfc_hba *phba, + struct lpfc_iocbq *iocbq) +{ + struct lpfc_nodelist *ndlp = NULL; + uint16_t rpi = 0, vpi = 0; + struct lpfc_vport *vport = NULL; + + /* The rpi in the ulpContext is vport-sensitive. */ + vpi = iocbq->iocb.un.asyncstat.sub_ctxt_tag; + rpi = iocbq->iocb.ulpContext; + + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3092 Port generated ABTS async event " + "on vpi %d rpi %d status 0x%x\n", + vpi, rpi, iocbq->iocb.ulpStatus); + + vport = lpfc_find_vport_by_vpid(phba, vpi); + if (!vport) + goto err_exit; + ndlp = lpfc_findnode_rpi(vport, rpi); + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + goto err_exit; + + if (iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT) + lpfc_sli_abts_recover_port(vport, ndlp); + return; + + err_exit: + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "3095 Event Context not found, no " + "action on vpi %d rpi %d status 0x%x, reason 0x%x\n", + iocbq->iocb.ulpContext, iocbq->iocb.ulpStatus, + vpi, rpi); +} + +/* lpfc_sli4_abts_err_handler - handle a failed ABTS request from an SLI4 port. + * @phba: pointer to HBA context object. + * @ndlp: nodelist pointer for the impacted rport. + * @axri: pointer to the wcqe containing the failed exchange. + * + * The driver calls this routine when it receives an ABORT_XRI_FCP CQE from the + * port. The port generates this event when an abort exchange request to an + * rport fails twice in succession with no reply. The abort could be originated + * by the driver or by the port. The ABTS could have been for an ELS or FCP IO. + */ +void +lpfc_sli4_abts_err_handler(struct lpfc_hba *phba, + struct lpfc_nodelist *ndlp, + struct sli4_wcqe_xri_aborted *axri) +{ + struct lpfc_vport *vport; + + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "3115 Node Context not found, driver " + "ignoring abts err event\n"); + vport = ndlp->vport; + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3116 Port generated FCP XRI ABORT event on " + "vpi %d rpi %d xri x%x status 0x%x\n", + ndlp->vport->vpi, ndlp->nlp_rpi, + bf_get(lpfc_wcqe_xa_xri, axri), + bf_get(lpfc_wcqe_xa_status, axri)); + + if (bf_get(lpfc_wcqe_xa_status, axri) == IOSTAT_LOCAL_REJECT) + lpfc_sli_abts_recover_port(vport, ndlp); +} + /** * lpfc_sli_async_event_handler - ASYNC iocb handler function * @phba: Pointer to HBA context object. @@ -8232,63 +8369,58 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, { IOCB_t *icmd; uint16_t evt_code; - uint16_t temp; struct temp_event temp_event_data; struct Scsi_Host *shost; uint32_t *iocb_w; icmd = &iocbq->iocb; evt_code = icmd->un.asyncstat.evt_code; - temp = icmd->ulpContext; - if ((evt_code != ASYNC_TEMP_WARN) && - (evt_code != ASYNC_TEMP_SAFE)) { + switch (evt_code) { + case ASYNC_TEMP_WARN: + case ASYNC_TEMP_SAFE: + temp_event_data.data = (uint32_t) icmd->ulpContext; + temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; + if (evt_code == ASYNC_TEMP_WARN) { + temp_event_data.event_code = LPFC_THRESHOLD_TEMP; + lpfc_printf_log(phba, KERN_ERR, LOG_TEMP, + "0347 Adapter is very hot, please take " + "corrective action. temperature : %d Celsius\n", + (uint32_t) icmd->ulpContext); + } else { + temp_event_data.event_code = LPFC_NORMAL_TEMP; + lpfc_printf_log(phba, KERN_ERR, LOG_TEMP, + "0340 Adapter temperature is OK now. " + "temperature : %d Celsius\n", + (uint32_t) icmd->ulpContext); + } + + /* Send temperature change event to applications */ + shost = lpfc_shost_from_vport(phba->pport); + fc_host_post_vendor_event(shost, fc_get_event_number(), + sizeof(temp_event_data), (char *) &temp_event_data, + LPFC_NL_VENDOR_ID); + break; + case ASYNC_STATUS_CN: + lpfc_sli_abts_err_handler(phba, iocbq); + break; + default: iocb_w = (uint32_t *) icmd; - lpfc_printf_log(phba, - KERN_ERR, - LOG_SLI, + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0346 Ring %d handler: unexpected ASYNC_STATUS" " evt_code 0x%x\n" "W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n" "W4 0x%08x W5 0x%08x W6 0x%08x W7 0x%08x\n" "W8 0x%08x W9 0x%08x W10 0x%08x W11 0x%08x\n" "W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n", - pring->ringno, - icmd->un.asyncstat.evt_code, + pring->ringno, icmd->un.asyncstat.evt_code, iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3], iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7], iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11], iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]); - return; - } - temp_event_data.data = (uint32_t)temp; - temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; - if (evt_code == ASYNC_TEMP_WARN) { - temp_event_data.event_code = LPFC_THRESHOLD_TEMP; - lpfc_printf_log(phba, - KERN_ERR, - LOG_TEMP, - "0347 Adapter is very hot, please take " - "corrective action. temperature : %d Celsius\n", - temp); - } - if (evt_code == ASYNC_TEMP_SAFE) { - temp_event_data.event_code = LPFC_NORMAL_TEMP; - lpfc_printf_log(phba, - KERN_ERR, - LOG_TEMP, - "0340 Adapter temperature is OK now. " - "temperature : %d Celsius\n", - temp); + break; } - - /* Send temperature change event to applications */ - shost = lpfc_shost_from_vport(phba->pport); - fc_host_post_vendor_event(shost, fc_get_event_number(), - sizeof(temp_event_data), (char *) &temp_event_data, - LPFC_NL_VENDOR_ID); - } @@ -9247,6 +9379,14 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "3096 ABORT_XRI_CN completing on xri x%x " + "original iotag x%x, abort cmd iotag x%x " + "status 0x%x, reason 0x%x\n", + cmdiocb->iocb.un.acxri.abortContextTag, + cmdiocb->iocb.un.acxri.abortIoTag, + cmdiocb->iotag, rspiocb->iocb.ulpStatus, + rspiocb->iocb.un.ulpWord[4]); lpfc_sli_release_iocbq(phba, cmdiocb); return; } -- cgit From df9e1b59f9e4671930a7762b9518461df4ea85f5 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 13 Dec 2011 13:22:17 -0500 Subject: [SCSI] Lpfc 8.3.28: FC and SCSI Discovery Fixes FC and SCSI Discovery Fixes: - Clear the virtual fabrics bit (word 1 bit 30) when sending the FLOGI and FDISC. (CR 124339) - Return a MLQUEUE_DEVICE_BUSY if the driver detects that an I/O is being retried too quickly (CR 124668) - Remove NDLP reference put in lpfc_cmpl_els_logo_acc for all but fabric nodes (CR 123924) - Only retry FDISCs every second and stop retrying after devloss number of retries (CR 13939) - Check to see if vports are unloading before adding them to the vport work array. (CR 124996) - Fixed illegal state transition during driver unload (CR 124191) - Added missing protection on setting/clearing of vport->fc_flag bit (CR 126002) - Set NPIV flag in lpfc_mbx_process_link_up for all ports sli3 and above. (CR 126094) - Clear FCP command bytes that are not used. (CR 126209) Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 23 ++++++++++++++++++----- drivers/scsi/lpfc/lpfc_hbadisc.c | 29 +++++++++++++++++++++++------ drivers/scsi/lpfc/lpfc_hw.h | 6 ++++++ drivers/scsi/lpfc/lpfc_hw4.h | 2 ++ drivers/scsi/lpfc/lpfc_nportdisc.c | 10 +++++++++- drivers/scsi/lpfc/lpfc_scsi.c | 13 +++++++++++-- drivers/scsi/lpfc/lpfc_scsi.h | 5 +++-- drivers/scsi/lpfc/lpfc_vport.c | 6 +++--- 8 files changed, 75 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 46876941bac6..0b662db23284 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1075,6 +1075,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Setup CSPs accordingly for Fabric */ sp->cmn.e_d_tov = 0; sp->cmn.w2.r_a_tov = 0; + sp->cmn.virtual_fabric_support = 0; sp->cls1.classValid = 0; sp->cls2.seqDelivery = 1; sp->cls3.seqDelivery = 1; @@ -3066,17 +3067,22 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (did == FDMI_DID) retry = 1; - if (((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) && + if ((cmd == ELS_CMD_FLOGI) && (phba->fc_topology != LPFC_TOPOLOGY_LOOP) && !lpfc_error_lost_link(irsp)) { /* FLOGI retry policy */ retry = 1; - /* retry forever */ + /* retry FLOGI forever */ maxretry = 0; if (cmdiocb->retry >= 100) delay = 5000; else if (cmdiocb->retry >= 32) delay = 1000; + } else if ((cmd == ELS_CMD_FDISC) && !lpfc_error_lost_link(irsp)) { + /* retry FDISCs every second up to devloss */ + retry = 1; + maxretry = vport->cfg_devloss_tmo; + delay = 1000; } cmdiocb->retry++; @@ -3389,11 +3395,17 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* * The driver received a LOGO from the rport and has ACK'd it. - * At this point, the driver is done so release the IOCB and - * remove the ndlp reference. + * At this point, the driver is done so release the IOCB */ lpfc_els_free_iocb(phba, cmdiocb); - lpfc_nlp_put(ndlp); + + /* + * Remove the ndlp reference if it's a fabric node that has + * sent us an unsolicted LOGO. + */ + if (ndlp->nlp_type & NLP_FABRIC) + lpfc_nlp_put(ndlp); + return; } @@ -7231,6 +7243,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Setup CSPs accordingly for Fabric */ sp->cmn.e_d_tov = 0; sp->cmn.w2.r_a_tov = 0; + sp->cmn.virtual_fabric_support = 0; sp->cls1.classValid = 0; sp->cls2.seqDelivery = 1; sp->cls3.seqDelivery = 1; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 99c76677e394..d96498581ebe 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -2646,9 +2646,14 @@ lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { struct lpfc_vport *vport = mboxq->vport; - /* VFI not supported on interface type 0, just do the flogi */ - if (mboxq->u.mb.mbxStatus && (bf_get(lpfc_sli_intf_if_type, - &phba->sli4_hba.sli_intf) != LPFC_SLI_INTF_IF_TYPE_0)) { + /* + * VFI not supported on interface type 0, just do the flogi + * Also continue if the VFI is in use - just use the same one. + */ + if (mboxq->u.mb.mbxStatus && + (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != + LPFC_SLI_INTF_IF_TYPE_0) && + mboxq->u.mb.mbxStatus != MBX_VFI_IN_USE) { lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, "2891 Init VFI mailbox failed 0x%x\n", @@ -2922,6 +2927,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) { struct lpfc_vport *vport = phba->pport; LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox = NULL; + struct Scsi_Host *shost; int i; struct lpfc_dmabuf *mp; int rc; @@ -2945,6 +2951,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la); phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; + shost = lpfc_shost_from_vport(vport); if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED; @@ -2956,8 +2963,11 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) "1309 Link Up Event npiv not supported in loop " "topology\n"); /* Get Loop Map information */ - if (bf_get(lpfc_mbx_read_top_il, la)) + if (bf_get(lpfc_mbx_read_top_il, la)) { + spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_LBIT; + spin_unlock_irq(shost->host_lock); + } vport->fc_myDID = bf_get(lpfc_mbx_read_top_alpa_granted, la); i = la->lilpBde64.tus.f.bdeSize; @@ -3002,11 +3012,13 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) } else { if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { if (phba->max_vpi && phba->cfg_enable_npiv && - (phba->sli_rev == 3)) + (phba->sli_rev >= LPFC_SLI_REV3)) phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED; } vport->fc_myDID = phba->fc_pref_DID; + spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_LBIT; + spin_unlock_irq(shost->host_lock); } spin_unlock_irq(&phba->hbalock); @@ -3593,6 +3605,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) MAILBOX_t *mb = &pmb->u.mb; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); struct lpfc_nodelist *ndlp; + struct Scsi_Host *shost; ndlp = (struct lpfc_nodelist *) pmb->context2; pmb->context1 = NULL; @@ -3638,8 +3651,12 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) * vport discovery */ if (!(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG)) lpfc_start_fdiscs(phba); - else + else { + shost = lpfc_shost_from_vport(vport); + spin_lock_irq(shost->host_lock); vport->fc_flag &= ~FC_LOGO_RCVD_DID_CHNG ; + spin_unlock_irq(shost->host_lock); + } lpfc_do_scr_ns_plogi(phba, vport); } diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 2dd464b0f29e..73fc5318641b 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -349,6 +349,12 @@ struct csp { * Word 1 Bit 31 in FLOGI response is clean address bit */ #define clean_address_bit request_multiple_Nport /* Word 1, bit 31 */ +/* + * Word 1 Bit 30 in common service parameter is overloaded. + * Word 1 Bit 30 in FLOGI request is Virtual Fabrics + * Word 1 Bit 30 in PLOGI request is random offset + */ +#define virtual_fabric_support randomOffset /* Word 1, bit 30 */ #ifdef __BIG_ENDIAN_BITFIELD uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */ uint16_t randomOffset:1; /* FC Word 1, bit 30 */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 447da2a546ae..43c4c56f9e68 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1830,6 +1830,8 @@ struct lpfc_mbx_init_vfi { #define lpfc_init_vfi_hop_count_MASK 0x000000FF #define lpfc_init_vfi_hop_count_WORD word4 }; +#define MBX_VFI_IN_USE 0x9F02 + struct lpfc_mbx_reg_vfi { uint32_t word1; diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 2ddd02f7c603..e8bb00559943 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -782,6 +782,14 @@ lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return NLP_STE_FREED_NODE; } +static uint32_t +lpfc_device_recov_unused_node(struct lpfc_vport *vport, + struct lpfc_nodelist *ndlp, + void *arg, uint32_t evt) +{ + return ndlp->nlp_state; +} + static uint32_t lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) @@ -2147,7 +2155,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) lpfc_disc_illegal, /* CMPL_ADISC */ lpfc_disc_illegal, /* CMPL_REG_LOGIN */ lpfc_device_rm_unused_node, /* DEVICE_RM */ - lpfc_disc_illegal, /* DEVICE_RECOVERY */ + lpfc_device_recov_unused_node, /* DEVICE_RECOVERY */ lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */ lpfc_rcv_prli_plogi_issue, /* RCV_PRLI */ diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f1af3f9dead4..c60f5d0b3869 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -2913,8 +2913,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, int_to_scsilun(lpfc_cmd->pCmd->device->lun, &lpfc_cmd->fcp_cmnd->fcp_lun); - memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, 16); - + memset(&fcp_cmnd->fcpCdb[0], 0, LPFC_FCP_CDB_LEN); + memcpy(&fcp_cmnd->fcpCdb[0], scsi_cmnd->cmnd, scsi_cmnd->cmd_len); if (scsi_populate_tag_msg(scsi_cmnd, tag)) { switch (tag[0]) { case HEAD_OF_QUEUE_TAG: @@ -3238,6 +3238,15 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) cmnd->result = err; goto out_fail_command; } + /* + * Do not let the mid-layer retry I/O too fast. If an I/O is retried + * without waiting a bit then indicate that the device is busy. + */ + if (cmnd->retries && + time_before(jiffies, (cmnd->jiffies_at_alloc + + msecs_to_jiffies(LPFC_RETRY_PAUSE * + cmnd->retries)))) + return SCSI_MLQUEUE_DEVICE_BUSY; ndlp = rdata->pnode; if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) && diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index ce645b20a6ad..9075a08cf781 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h @@ -21,6 +21,7 @@ #include struct lpfc_hba; +#define LPFC_FCP_CDB_LEN 16 #define list_remove_head(list, entry, type, member) \ do { \ @@ -102,7 +103,7 @@ struct fcp_cmnd { #define WRITE_DATA 0x01 /* Bit 0 */ #define READ_DATA 0x02 /* Bit 1 */ - uint8_t fcpCdb[16]; /* SRB cdb field is copied here */ + uint8_t fcpCdb[LPFC_FCP_CDB_LEN]; /* SRB cdb field is copied here */ uint32_t fcpDl; /* Total transfer length */ }; @@ -153,5 +154,5 @@ struct lpfc_scsi_buf { #define LPFC_SCSI_DMA_EXT_SIZE 264 #define LPFC_BPL_SIZE 1024 - +#define LPFC_RETRY_PAUSE 300 #define MDAC_DIRECT_CMD 0x22 diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index cff6ca67415c..0fe188e66000 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -774,10 +774,10 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) return NULL; spin_lock_irq(&phba->hbalock); list_for_each_entry(port_iterator, &phba->port_list, listentry) { + if (port_iterator->load_flag & FC_UNLOADING) + continue; if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) { - if (!(port_iterator->load_flag & FC_UNLOADING)) - lpfc_printf_vlog(port_iterator, KERN_ERR, - LOG_VPORT, + lpfc_printf_vlog(port_iterator, KERN_ERR, LOG_VPORT, "1801 Create vport work array FAILED: " "cannot do scsi_host_get\n"); continue; -- cgit From 2e90f4b5a2a0ce5ab72c0c81c74269bd0a62522b Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 13 Dec 2011 13:22:37 -0500 Subject: [SCSI] lpfc 8.3.28: Critical Miscellaneous fixes - Make lpfc_sli4_pci_mem_unset interface type aware (CR 124390) - Convert byte count to word count when calling __iowrite32_copy (CR 122550) - Checked the ERR1 and ERR2 registers for error attention due to SLI Port state affected by forced debug dump. (CR 122986, 122426, 124859) - Use the lpfc_readl routine instead of the readl for the port status register read in lpfc_handle_eratt_s4 (CR 125403) - Call lpfc_sli4_queue_destroy inside of lpfc_sli4_brdreset before doing a pci function reset (CR 125124, 125168, 125572, 125622) - Zero out the HBQ when it is allocated (CR 125663) - Alter port reset log messages to indicate error type (CR 125989) - Added proper NULL pointer checking to all the places that accessing the queue memory (CR 125832) Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_compat.h | 5 +- drivers/scsi/lpfc/lpfc_debugfs.c | 172 +++++++++++++++++++++++++-------------- drivers/scsi/lpfc/lpfc_init.c | 164 ++++++++++++++++++++++++++----------- drivers/scsi/lpfc/lpfc_mem.c | 4 +- drivers/scsi/lpfc/lpfc_sli.c | 135 +++++++++++++++++++++++------- drivers/scsi/lpfc/lpfc_sli4.h | 9 ++ 6 files changed, 350 insertions(+), 139 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h index 75e2e569dede..c88e556ea62e 100644 --- a/drivers/scsi/lpfc/lpfc_compat.h +++ b/drivers/scsi/lpfc/lpfc_compat.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2005 Emulex. All rights reserved. * + * Copyright (C) 2004-2011 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -82,7 +82,8 @@ lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes) static inline void lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes) { - __iowrite32_copy(dest, src, bytes); + /* convert bytes in argument list to word count for copy function */ + __iowrite32_copy(dest, src, bytes / sizeof(uint32_t)); } static inline void diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 28382596fb9a..3587a3fe8fcb 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -1997,7 +1997,8 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, /* Get slow-path event queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Slow-path EQ information:\n"); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.sp_eq) { + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tEQID[%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", @@ -2006,12 +2007,17 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.sp_eq->entry_size, phba->sli4_hba.sp_eq->host_index, phba->sli4_hba.sp_eq->hba_index); + } /* Get fast-path event queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Fast-path EQ information:\n"); - for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.fp_eq) { + for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; + fcp_qidx++) { + if (phba->sli4_hba.fp_eq[fcp_qidx]) { + len += snprintf(pbuffer+len, + LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tEQID[%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", @@ -2020,16 +2026,19 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.fp_eq[fcp_qidx]->entry_size, phba->sli4_hba.fp_eq[fcp_qidx]->host_index, phba->sli4_hba.fp_eq[fcp_qidx]->hba_index); + } + } } len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); /* Get mailbox complete queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Slow-path MBX CQ information:\n"); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.mbx_cq) { + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Associated EQID[%02d]:\n", phba->sli4_hba.mbx_cq->assoc_qid); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tCQID[%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", @@ -2038,14 +2047,16 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.mbx_cq->entry_size, phba->sli4_hba.mbx_cq->host_index, phba->sli4_hba.mbx_cq->hba_index); + } /* Get slow-path complete queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Slow-path ELS CQ information:\n"); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.els_cq) { + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Associated EQID[%02d]:\n", phba->sli4_hba.els_cq->assoc_qid); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tCQID [%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", @@ -2054,16 +2065,21 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.els_cq->entry_size, phba->sli4_hba.els_cq->host_index, phba->sli4_hba.els_cq->hba_index); + } /* Get fast-path complete queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Fast-path FCP CQ information:\n"); fcp_qidx = 0; - do { - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.fcp_cq) { + do { + if (phba->sli4_hba.fcp_cq[fcp_qidx]) { + len += snprintf(pbuffer+len, + LPFC_QUE_INFO_GET_BUF_SIZE-len, "Associated EQID[%02d]:\n", phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + len += snprintf(pbuffer+len, + LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tCQID[%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", @@ -2072,16 +2088,20 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.fcp_cq[fcp_qidx]->entry_size, phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); - } while (++fcp_qidx < phba->cfg_fcp_eq_count); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); + } + } while (++fcp_qidx < phba->cfg_fcp_eq_count); + len += snprintf(pbuffer+len, + LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); + } /* Get mailbox queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Slow-path MBX MQ information:\n"); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.mbx_wq) { + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Associated CQID[%02d]:\n", phba->sli4_hba.mbx_wq->assoc_qid); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tWQID[%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", @@ -2090,14 +2110,16 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.mbx_wq->entry_size, phba->sli4_hba.mbx_wq->host_index, phba->sli4_hba.mbx_wq->hba_index); + } /* Get slow-path work queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Slow-path ELS WQ information:\n"); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.els_wq) { + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Associated CQID[%02d]:\n", phba->sli4_hba.els_wq->assoc_qid); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tWQID[%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n", @@ -2106,15 +2128,22 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.els_wq->entry_size, phba->sli4_hba.els_wq->host_index, phba->sli4_hba.els_wq->hba_index); + } /* Get fast-path work queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Fast-path FCP WQ information:\n"); - for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) { - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.fcp_wq) { + for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; + fcp_qidx++) { + if (!phba->sli4_hba.fcp_wq[fcp_qidx]) + continue; + len += snprintf(pbuffer+len, + LPFC_QUE_INFO_GET_BUF_SIZE-len, "Associated CQID[%02d]:\n", phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + len += snprintf(pbuffer+len, + LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tWQID[%02d], " "QE-COUNT[%04d], WQE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", @@ -2123,16 +2152,19 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.fcp_wq[fcp_qidx]->entry_size, phba->sli4_hba.fcp_wq[fcp_qidx]->host_index, phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index); + } + len += snprintf(pbuffer+len, + LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); } - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); /* Get receive queue information */ len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Slow-path RQ information:\n"); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + if (phba->sli4_hba.hdr_rq && phba->sli4_hba.dat_rq) { + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "Associated CQID[%02d]:\n", phba->sli4_hba.hdr_rq->assoc_qid); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tHQID[%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", @@ -2141,7 +2173,7 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.hdr_rq->entry_size, phba->sli4_hba.hdr_rq->host_index, phba->sli4_hba.hdr_rq->hba_index); - len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, + len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\tDQID[%02d], " "QE-COUNT[%04d], QE-SIZE[%04d], " "HOST-INDEX[%04d], PORT-INDEX[%04d]\n", @@ -2150,7 +2182,7 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, phba->sli4_hba.dat_rq->entry_size, phba->sli4_hba.dat_rq->host_index, phba->sli4_hba.dat_rq->hba_index); - + } return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); } @@ -2360,7 +2392,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, switch (quetp) { case LPFC_IDIAG_EQ: /* Slow-path event queue */ - if (phba->sli4_hba.sp_eq->queue_id == queid) { + if (phba->sli4_hba.sp_eq && + phba->sli4_hba.sp_eq->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( phba->sli4_hba.sp_eq, index, count); @@ -2370,23 +2403,29 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, goto pass_check; } /* Fast-path event queue */ - for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) { - if (phba->sli4_hba.fp_eq[qidx]->queue_id == queid) { - /* Sanity check */ - rc = lpfc_idiag_que_param_check( + if (phba->sli4_hba.fp_eq) { + for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) { + if (phba->sli4_hba.fp_eq[qidx] && + phba->sli4_hba.fp_eq[qidx]->queue_id == + queid) { + /* Sanity check */ + rc = lpfc_idiag_que_param_check( phba->sli4_hba.fp_eq[qidx], index, count); - if (rc) - goto error_out; - idiag.ptr_private = phba->sli4_hba.fp_eq[qidx]; - goto pass_check; + if (rc) + goto error_out; + idiag.ptr_private = + phba->sli4_hba.fp_eq[qidx]; + goto pass_check; + } } } goto error_out; break; case LPFC_IDIAG_CQ: /* MBX complete queue */ - if (phba->sli4_hba.mbx_cq->queue_id == queid) { + if (phba->sli4_hba.mbx_cq && + phba->sli4_hba.mbx_cq->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( phba->sli4_hba.mbx_cq, index, count); @@ -2396,7 +2435,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, goto pass_check; } /* ELS complete queue */ - if (phba->sli4_hba.els_cq->queue_id == queid) { + if (phba->sli4_hba.els_cq && + phba->sli4_hba.els_cq->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( phba->sli4_hba.els_cq, index, count); @@ -2406,25 +2446,30 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, goto pass_check; } /* FCP complete queue */ - qidx = 0; - do { - if (phba->sli4_hba.fcp_cq[qidx]->queue_id == queid) { - /* Sanity check */ - rc = lpfc_idiag_que_param_check( + if (phba->sli4_hba.fcp_cq) { + qidx = 0; + do { + if (phba->sli4_hba.fcp_cq[qidx] && + phba->sli4_hba.fcp_cq[qidx]->queue_id == + queid) { + /* Sanity check */ + rc = lpfc_idiag_que_param_check( phba->sli4_hba.fcp_cq[qidx], index, count); - if (rc) - goto error_out; - idiag.ptr_private = + if (rc) + goto error_out; + idiag.ptr_private = phba->sli4_hba.fcp_cq[qidx]; - goto pass_check; - } - } while (++qidx < phba->cfg_fcp_eq_count); + goto pass_check; + } + } while (++qidx < phba->cfg_fcp_eq_count); + } goto error_out; break; case LPFC_IDIAG_MQ: /* MBX work queue */ - if (phba->sli4_hba.mbx_wq->queue_id == queid) { + if (phba->sli4_hba.mbx_wq && + phba->sli4_hba.mbx_wq->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( phba->sli4_hba.mbx_wq, index, count); @@ -2433,10 +2478,12 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, idiag.ptr_private = phba->sli4_hba.mbx_wq; goto pass_check; } + goto error_out; break; case LPFC_IDIAG_WQ: /* ELS work queue */ - if (phba->sli4_hba.els_wq->queue_id == queid) { + if (phba->sli4_hba.els_wq && + phba->sli4_hba.els_wq->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( phba->sli4_hba.els_wq, index, count); @@ -2446,24 +2493,30 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, goto pass_check; } /* FCP work queue */ - for (qidx = 0; qidx < phba->cfg_fcp_wq_count; qidx++) { - if (phba->sli4_hba.fcp_wq[qidx]->queue_id == queid) { - /* Sanity check */ - rc = lpfc_idiag_que_param_check( + if (phba->sli4_hba.fcp_wq) { + for (qidx = 0; qidx < phba->cfg_fcp_wq_count; qidx++) { + if (!phba->sli4_hba.fcp_wq[qidx]) + continue; + if (phba->sli4_hba.fcp_wq[qidx]->queue_id == + queid) { + /* Sanity check */ + rc = lpfc_idiag_que_param_check( phba->sli4_hba.fcp_wq[qidx], index, count); - if (rc) - goto error_out; - idiag.ptr_private = - phba->sli4_hba.fcp_wq[qidx]; - goto pass_check; + if (rc) + goto error_out; + idiag.ptr_private = + phba->sli4_hba.fcp_wq[qidx]; + goto pass_check; + } } } goto error_out; break; case LPFC_IDIAG_RQ: /* HDR queue */ - if (phba->sli4_hba.hdr_rq->queue_id == queid) { + if (phba->sli4_hba.hdr_rq && + phba->sli4_hba.hdr_rq->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( phba->sli4_hba.hdr_rq, index, count); @@ -2473,7 +2526,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, goto pass_check; } /* DAT queue */ - if (phba->sli4_hba.dat_rq->queue_id == queid) { + if (phba->sli4_hba.dat_rq && + phba->sli4_hba.dat_rq->queue_id == queid) { /* Sanity check */ rc = lpfc_idiag_que_param_check( phba->sli4_hba.dat_rq, index, count); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6096c9a091d1..cb714d2342d4 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1417,7 +1417,10 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) uint32_t event_data; struct Scsi_Host *shost; uint32_t if_type; - struct lpfc_register portstat_reg; + struct lpfc_register portstat_reg = {0}; + uint32_t reg_err1, reg_err2; + uint32_t uerrlo_reg, uemasklo_reg; + uint32_t pci_rd_rc1, pci_rd_rc2; int rc; /* If the pci channel is offline, ignore possible errors, since @@ -1429,27 +1432,29 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) if (!phba->cfg_enable_hba_reset) return; - /* Send an internal error event to mgmt application */ - lpfc_board_errevt_to_mgmt(phba); - - /* For now, the actual action for SLI4 device handling is not - * specified yet, just treated it as adaptor hardware failure - */ - event_data = FC_REG_DUMP_EVENT; - shost = lpfc_shost_from_vport(vport); - fc_host_post_vendor_event(shost, fc_get_event_number(), - sizeof(event_data), (char *) &event_data, - SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); - if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); switch (if_type) { case LPFC_SLI_INTF_IF_TYPE_0: + pci_rd_rc1 = lpfc_readl( + phba->sli4_hba.u.if_type0.UERRLOregaddr, + &uerrlo_reg); + pci_rd_rc2 = lpfc_readl( + phba->sli4_hba.u.if_type0.UEMASKLOregaddr, + &uemasklo_reg); + /* consider PCI bus read error as pci_channel_offline */ + if (pci_rd_rc1 == -EIO && pci_rd_rc2 == -EIO) + return; lpfc_sli4_offline_eratt(phba); break; case LPFC_SLI_INTF_IF_TYPE_2: - portstat_reg.word0 = - readl(phba->sli4_hba.u.if_type2.STATUSregaddr); - + pci_rd_rc1 = lpfc_readl( + phba->sli4_hba.u.if_type2.STATUSregaddr, + &portstat_reg.word0); + /* consider PCI bus read error as pci_channel_offline */ + if (pci_rd_rc1 == -EIO) + return; + reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr); + reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr); if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) { /* TODO: Register for Overtemp async events. */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -1459,8 +1464,20 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) phba->over_temp_state = HBA_OVER_TEMP; spin_unlock_irq(&phba->hbalock); lpfc_sli4_offline_eratt(phba); - return; + break; } + if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && + reg_err2 == SLIPORT_ERR2_REG_FW_RESTART) + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3143 Port Down: Firmware Restarted\n"); + else if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && + reg_err2 == SLIPORT_ERR2_REG_FORCED_DUMP) + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3144 Port Down: Debug Dump\n"); + else if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && + reg_err2 == SLIPORT_ERR2_REG_FUNC_PROVISON) + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3145 Port Down: Provisioning\n"); /* * On error status condition, driver need to wait for port * ready before performing reset. @@ -1469,14 +1486,19 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) if (!rc) { /* need reset: attempt for port recovery */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2887 Port Error: Attempting " - "Port Recovery\n"); + "2887 Reset Needed: Attempting Port " + "Recovery...\n"); lpfc_offline_prep(phba); lpfc_offline(phba); lpfc_sli_brdrestart(phba); if (lpfc_online(phba) == 0) { lpfc_unblock_mgmt_io(phba); - return; + /* don't report event on forced debug dump */ + if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && + reg_err2 == SLIPORT_ERR2_REG_FORCED_DUMP) + return; + else + break; } /* fall through for not able to recover */ } @@ -1486,6 +1508,16 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) default: break; } + lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, + "3123 Report dump event to upper layer\n"); + /* Send an internal error event to mgmt application */ + lpfc_board_errevt_to_mgmt(phba); + + event_data = FC_REG_DUMP_EVENT; + shost = lpfc_shost_from_vport(vport); + fc_host_post_vendor_event(shost, fc_get_event_number(), + sizeof(event_data), (char *) &event_data, + SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); } /** @@ -6475,6 +6507,7 @@ out_free_fcp_wq: phba->sli4_hba.fcp_wq[fcp_wqidx] = NULL; } kfree(phba->sli4_hba.fcp_wq); + phba->sli4_hba.fcp_wq = NULL; out_free_els_wq: lpfc_sli4_queue_free(phba->sli4_hba.els_wq); phba->sli4_hba.els_wq = NULL; @@ -6487,6 +6520,7 @@ out_free_fcp_cq: phba->sli4_hba.fcp_cq[fcp_cqidx] = NULL; } kfree(phba->sli4_hba.fcp_cq); + phba->sli4_hba.fcp_cq = NULL; out_free_els_cq: lpfc_sli4_queue_free(phba->sli4_hba.els_cq); phba->sli4_hba.els_cq = NULL; @@ -6499,6 +6533,7 @@ out_free_fp_eq: phba->sli4_hba.fp_eq[fcp_eqidx] = NULL; } kfree(phba->sli4_hba.fp_eq); + phba->sli4_hba.fp_eq = NULL; out_free_sp_eq: lpfc_sli4_queue_free(phba->sli4_hba.sp_eq); phba->sli4_hba.sp_eq = NULL; @@ -6532,8 +6567,10 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba) phba->sli4_hba.els_wq = NULL; /* Release FCP work queue */ - for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) - lpfc_sli4_queue_free(phba->sli4_hba.fcp_wq[fcp_qidx]); + if (phba->sli4_hba.fcp_wq != NULL) + for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; + fcp_qidx++) + lpfc_sli4_queue_free(phba->sli4_hba.fcp_wq[fcp_qidx]); kfree(phba->sli4_hba.fcp_wq); phba->sli4_hba.fcp_wq = NULL; @@ -6553,15 +6590,18 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba) /* Release FCP response complete queue */ fcp_qidx = 0; - do - lpfc_sli4_queue_free(phba->sli4_hba.fcp_cq[fcp_qidx]); - while (++fcp_qidx < phba->cfg_fcp_eq_count); + if (phba->sli4_hba.fcp_cq != NULL) + do + lpfc_sli4_queue_free(phba->sli4_hba.fcp_cq[fcp_qidx]); + while (++fcp_qidx < phba->cfg_fcp_eq_count); kfree(phba->sli4_hba.fcp_cq); phba->sli4_hba.fcp_cq = NULL; /* Release fast-path event queue */ - for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) - lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]); + if (phba->sli4_hba.fp_eq != NULL) + for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; + fcp_qidx++) + lpfc_sli4_queue_free(phba->sli4_hba.fp_eq[fcp_qidx]); kfree(phba->sli4_hba.fp_eq); phba->sli4_hba.fp_eq = NULL; @@ -6614,6 +6654,11 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.sp_eq->queue_id); /* Set up fast-path event queue */ + if (!phba->sli4_hba.fp_eq) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3147 Fast-path EQs not allocated\n"); + goto out_destroy_sp_eq; + } for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) { if (!phba->sli4_hba.fp_eq[fcp_eqidx]) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -6678,6 +6723,12 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.sp_eq->queue_id); /* Set up fast-path FCP Response Complete Queue */ + if (!phba->sli4_hba.fcp_cq) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3148 Fast-path FCP CQ array not " + "allocated\n"); + goto out_destroy_els_cq; + } fcp_cqidx = 0; do { if (!phba->sli4_hba.fcp_cq[fcp_cqidx]) { @@ -6757,6 +6808,12 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.els_cq->queue_id); /* Set up fast-path FCP Work Queue */ + if (!phba->sli4_hba.fcp_wq) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "3149 Fast-path FCP WQ array not " + "allocated\n"); + goto out_destroy_els_wq; + } for (fcp_wqidx = 0; fcp_wqidx < phba->cfg_fcp_wq_count; fcp_wqidx++) { if (!phba->sli4_hba.fcp_wq[fcp_wqidx]) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -6818,18 +6875,21 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) out_destroy_fcp_wq: for (--fcp_wqidx; fcp_wqidx >= 0; fcp_wqidx--) lpfc_wq_destroy(phba, phba->sli4_hba.fcp_wq[fcp_wqidx]); +out_destroy_els_wq: lpfc_wq_destroy(phba, phba->sli4_hba.els_wq); out_destroy_mbx_wq: lpfc_mq_destroy(phba, phba->sli4_hba.mbx_wq); out_destroy_fcp_cq: for (--fcp_cqidx; fcp_cqidx >= 0; fcp_cqidx--) lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_cqidx]); +out_destroy_els_cq: lpfc_cq_destroy(phba, phba->sli4_hba.els_cq); out_destroy_mbx_cq: lpfc_cq_destroy(phba, phba->sli4_hba.mbx_cq); out_destroy_fp_eq: for (--fcp_eqidx; fcp_eqidx >= 0; fcp_eqidx--) lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_eqidx]); +out_destroy_sp_eq: lpfc_eq_destroy(phba, phba->sli4_hba.sp_eq); out_error: return rc; @@ -6866,13 +6926,18 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba) /* Unset ELS complete queue */ lpfc_cq_destroy(phba, phba->sli4_hba.els_cq); /* Unset FCP response complete queue */ - fcp_qidx = 0; - do { - lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_qidx]); - } while (++fcp_qidx < phba->cfg_fcp_eq_count); + if (phba->sli4_hba.fcp_cq) { + fcp_qidx = 0; + do { + lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_qidx]); + } while (++fcp_qidx < phba->cfg_fcp_eq_count); + } /* Unset fast-path event queue */ - for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) - lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_qidx]); + if (phba->sli4_hba.fp_eq) { + for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; + fcp_qidx++) + lpfc_eq_destroy(phba, phba->sli4_hba.fp_eq[fcp_qidx]); + } /* Unset slow-path event queue */ lpfc_eq_destroy(phba, phba->sli4_hba.sp_eq); } @@ -7411,22 +7476,25 @@ out: static void lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba) { - struct pci_dev *pdev; - - /* Obtain PCI device reference */ - if (!phba->pcidev) - return; - else - pdev = phba->pcidev; - - /* Free coherent DMA memory allocated */ - - /* Unmap I/O memory space */ - iounmap(phba->sli4_hba.drbl_regs_memmap_p); - iounmap(phba->sli4_hba.ctrl_regs_memmap_p); - iounmap(phba->sli4_hba.conf_regs_memmap_p); + uint32_t if_type; + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); - return; + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + iounmap(phba->sli4_hba.drbl_regs_memmap_p); + iounmap(phba->sli4_hba.ctrl_regs_memmap_p); + iounmap(phba->sli4_hba.conf_regs_memmap_p); + break; + case LPFC_SLI_INTF_IF_TYPE_2: + iounmap(phba->sli4_hba.conf_regs_memmap_p); + break; + case LPFC_SLI_INTF_IF_TYPE_1: + default: + dev_printk(KERN_ERR, &phba->pcidev->dev, + "FATAL - unsupported SLI4 interface type - %d\n", + if_type); + break; + } } /** diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 10d5b5e41499..ade763d3930a 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -389,7 +389,7 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba) { struct hbq_dmabuf *hbqbp; - hbqbp = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); + hbqbp = kzalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); if (!hbqbp) return NULL; @@ -441,7 +441,7 @@ lpfc_sli4_rb_alloc(struct lpfc_hba *phba) { struct hbq_dmabuf *dma_buf; - dma_buf = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); + dma_buf = kzalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); if (!dma_buf) return NULL; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 97bbafb21bc2..e27cb44b3ec2 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -89,10 +89,15 @@ lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) static uint32_t lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) { - union lpfc_wqe *temp_wqe = q->qe[q->host_index].wqe; + union lpfc_wqe *temp_wqe; struct lpfc_register doorbell; uint32_t host_index; + /* sanity check on queue memory */ + if (unlikely(!q)) + return -ENOMEM; + temp_wqe = q->qe[q->host_index].wqe; + /* If the host has not yet processed the next entry then we are done */ if (((q->host_index + 1) % q->entry_count) == q->hba_index) return -ENOMEM; @@ -134,6 +139,10 @@ lpfc_sli4_wq_release(struct lpfc_queue *q, uint32_t index) { uint32_t released = 0; + /* sanity check on queue memory */ + if (unlikely(!q)) + return 0; + if (q->hba_index == index) return 0; do { @@ -158,10 +167,15 @@ lpfc_sli4_wq_release(struct lpfc_queue *q, uint32_t index) static uint32_t lpfc_sli4_mq_put(struct lpfc_queue *q, struct lpfc_mqe *mqe) { - struct lpfc_mqe *temp_mqe = q->qe[q->host_index].mqe; + struct lpfc_mqe *temp_mqe; struct lpfc_register doorbell; uint32_t host_index; + /* sanity check on queue memory */ + if (unlikely(!q)) + return -ENOMEM; + temp_mqe = q->qe[q->host_index].mqe; + /* If the host has not yet processed the next entry then we are done */ if (((q->host_index + 1) % q->entry_count) == q->hba_index) return -ENOMEM; @@ -195,6 +209,10 @@ lpfc_sli4_mq_put(struct lpfc_queue *q, struct lpfc_mqe *mqe) static uint32_t lpfc_sli4_mq_release(struct lpfc_queue *q) { + /* sanity check on queue memory */ + if (unlikely(!q)) + return 0; + /* Clear the mailbox pointer for completion */ q->phba->mbox = NULL; q->hba_index = ((q->hba_index + 1) % q->entry_count); @@ -213,7 +231,12 @@ lpfc_sli4_mq_release(struct lpfc_queue *q) static struct lpfc_eqe * lpfc_sli4_eq_get(struct lpfc_queue *q) { - struct lpfc_eqe *eqe = q->qe[q->hba_index].eqe; + struct lpfc_eqe *eqe; + + /* sanity check on queue memory */ + if (unlikely(!q)) + return NULL; + eqe = q->qe[q->hba_index].eqe; /* If the next EQE is not valid then we are done */ if (!bf_get_le32(lpfc_eqe_valid, eqe)) @@ -248,6 +271,10 @@ lpfc_sli4_eq_release(struct lpfc_queue *q, bool arm) struct lpfc_eqe *temp_eqe; struct lpfc_register doorbell; + /* sanity check on queue memory */ + if (unlikely(!q)) + return 0; + /* while there are valid entries */ while (q->hba_index != q->host_index) { temp_eqe = q->qe[q->host_index].eqe; @@ -288,6 +315,10 @@ lpfc_sli4_cq_get(struct lpfc_queue *q) { struct lpfc_cqe *cqe; + /* sanity check on queue memory */ + if (unlikely(!q)) + return NULL; + /* If the next CQE is not valid then we are done */ if (!bf_get_le32(lpfc_cqe_valid, q->qe[q->hba_index].cqe)) return NULL; @@ -322,6 +353,9 @@ lpfc_sli4_cq_release(struct lpfc_queue *q, bool arm) struct lpfc_cqe *temp_qe; struct lpfc_register doorbell; + /* sanity check on queue memory */ + if (unlikely(!q)) + return 0; /* while there are valid entries */ while (q->hba_index != q->host_index) { temp_qe = q->qe[q->host_index].cqe; @@ -359,11 +393,17 @@ static int lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq, struct lpfc_rqe *hrqe, struct lpfc_rqe *drqe) { - struct lpfc_rqe *temp_hrqe = hq->qe[hq->host_index].rqe; - struct lpfc_rqe *temp_drqe = dq->qe[dq->host_index].rqe; + struct lpfc_rqe *temp_hrqe; + struct lpfc_rqe *temp_drqe; struct lpfc_register doorbell; int put_index = hq->host_index; + /* sanity check on queue memory */ + if (unlikely(!hq) || unlikely(!dq)) + return -ENOMEM; + temp_hrqe = hq->qe[hq->host_index].rqe; + temp_drqe = dq->qe[dq->host_index].rqe; + if (hq->type != LPFC_HRQ || dq->type != LPFC_DRQ) return -EINVAL; if (hq->host_index != dq->host_index) @@ -402,6 +442,10 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq, static uint32_t lpfc_sli4_rq_release(struct lpfc_queue *hq, struct lpfc_queue *dq) { + /* sanity check on queue memory */ + if (unlikely(!hq) || unlikely(!dq)) + return 0; + if ((hq->type != LPFC_HRQ) || (dq->type != LPFC_DRQ)) return 0; hq->hba_index = ((hq->hba_index + 1) % hq->entry_count); @@ -3851,7 +3895,6 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) { struct lpfc_sli *psli = &phba->sli; uint16_t cfg_value; - uint8_t qindx; /* Reset HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, @@ -3867,19 +3910,6 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~(LPFC_PROCESS_LA); phba->fcf.fcf_flag = 0; - /* Clean up the child queue list for the CQs */ - list_del_init(&phba->sli4_hba.mbx_wq->list); - list_del_init(&phba->sli4_hba.els_wq->list); - list_del_init(&phba->sli4_hba.hdr_rq->list); - list_del_init(&phba->sli4_hba.dat_rq->list); - list_del_init(&phba->sli4_hba.mbx_cq->list); - list_del_init(&phba->sli4_hba.els_cq->list); - for (qindx = 0; qindx < phba->cfg_fcp_wq_count; qindx++) - list_del_init(&phba->sli4_hba.fcp_wq[qindx]->list); - qindx = 0; - do - list_del_init(&phba->sli4_hba.fcp_cq[qindx]->list); - while (++qindx < phba->cfg_fcp_eq_count); spin_unlock_irq(&phba->hbalock); /* Now physically reset the device */ @@ -3892,6 +3922,7 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); /* Perform FCoE PCI function reset */ + lpfc_sli4_queue_destroy(phba); lpfc_pci_function_reset(phba); /* Restore PCI cmd register */ @@ -4869,14 +4900,19 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM); lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM); fcp_eqidx = 0; - do - lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[fcp_eqidx], - LPFC_QUEUE_REARM); - while (++fcp_eqidx < phba->cfg_fcp_eq_count); + if (phba->sli4_hba.fcp_cq) { + do + lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[fcp_eqidx], + LPFC_QUEUE_REARM); + while (++fcp_eqidx < phba->cfg_fcp_eq_count); + } lpfc_sli4_eq_release(phba->sli4_hba.sp_eq, LPFC_QUEUE_REARM); - for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) - lpfc_sli4_eq_release(phba->sli4_hba.fp_eq[fcp_eqidx], - LPFC_QUEUE_REARM); + if (phba->sli4_hba.fp_eq) { + for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; + fcp_eqidx++) + lpfc_sli4_eq_release(phba->sli4_hba.fp_eq[fcp_eqidx], + LPFC_QUEUE_REARM); + } } /** @@ -8083,6 +8119,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, */ if (piocb->iocb_flag & LPFC_IO_FCP) piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba); + if (unlikely(!phba->sli4_hba.fcp_wq)) + return IOCB_ERROR; if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx], &wqe)) return IOCB_ERROR; @@ -9900,7 +9938,7 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) phba->work_status[1] = readl(phba->sli4_hba.u.if_type2.ERR2regaddr); lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2885 Port Error Detected: " + "2885 Port Status Event: " "port status reg 0x%x, " "port smphr reg 0x%x, " "error 1=0x%x, error 2=0x%x\n", @@ -10906,6 +10944,9 @@ static void lpfc_sli4_sp_handle_rel_wcqe(struct lpfc_hba *phba, struct lpfc_wcqe_release *wcqe) { + /* sanity check on queue memory */ + if (unlikely(!phba->sli4_hba.els_wq)) + return; /* Check for the slow-path ELS work queue */ if (bf_get(lpfc_wcqe_r_wq_id, wcqe) == phba->sli4_hba.els_wq->queue_id) lpfc_sli4_wq_release(phba->sli4_hba.els_wq, @@ -10995,6 +11036,10 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) uint32_t status, rq_id; unsigned long iflags; + /* sanity check on queue memory */ + if (unlikely(!hrq) || unlikely(!drq)) + return workposted; + if (bf_get(lpfc_cqe_code, rcqe) == CQE_CODE_RECEIVE_V1) rq_id = bf_get(lpfc_rcqe_rq_id_v1, rcqe); else @@ -11129,6 +11174,9 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe) /* Search for completion queue pointer matching this cqid */ speq = phba->sli4_hba.sp_eq; + /* sanity check on queue memory */ + if (unlikely(!speq)) + return; list_for_each_entry(childq, &speq->child_list, list) { if (childq->queue_id == cqid) { cq = childq; @@ -11370,12 +11418,18 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, return; } + if (unlikely(!phba->sli4_hba.fcp_cq)) { + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, + "3146 Fast-path completion queues " + "does not exist\n"); + return; + } cq = phba->sli4_hba.fcp_cq[fcp_cqidx]; if (unlikely(!cq)) { if (phba->sli.sli_flag & LPFC_SLI_ACTIVE) lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0367 Fast-path completion queue " - "does not exist\n"); + "(%d) does not exist\n", fcp_cqidx); return; } @@ -11546,6 +11600,8 @@ lpfc_sli4_fp_intr_handler(int irq, void *dev_id) /* Get to the EQ struct associated with this vector */ fpeq = phba->sli4_hba.fp_eq[fcp_eqidx]; + if (unlikely(!fpeq)) + return IRQ_NONE; /* Check device state for handling interrupt */ if (unlikely(lpfc_intr_state_check(phba))) { @@ -11764,6 +11820,9 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax) uint16_t dmult; uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; + /* sanity check on queue memory */ + if (!eq) + return -ENODEV; if (!phba->sli4_hba.pc_sli4_params.supported) hw_page_size = SLI4_PAGE_SIZE; @@ -11880,6 +11939,9 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, union lpfc_sli4_cfg_shdr *shdr; uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; + /* sanity check on queue memory */ + if (!cq || !eq) + return -ENODEV; if (!phba->sli4_hba.pc_sli4_params.supported) hw_page_size = SLI4_PAGE_SIZE; @@ -12062,6 +12124,9 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, union lpfc_sli4_cfg_shdr *shdr; uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; + /* sanity check on queue memory */ + if (!mq || !cq) + return -ENODEV; if (!phba->sli4_hba.pc_sli4_params.supported) hw_page_size = SLI4_PAGE_SIZE; @@ -12212,6 +12277,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; struct dma_address *page; + /* sanity check on queue memory */ + if (!wq || !cq) + return -ENODEV; if (!phba->sli4_hba.pc_sli4_params.supported) hw_page_size = SLI4_PAGE_SIZE; @@ -12304,6 +12372,9 @@ lpfc_rq_adjust_repost(struct lpfc_hba *phba, struct lpfc_queue *rq, int qno) { uint32_t cnt; + /* sanity check on queue memory */ + if (!rq) + return; cnt = lpfc_hbq_defs[qno]->entry_count; /* Recalc repost for RQs based on buffers initially posted */ @@ -12349,6 +12420,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, union lpfc_sli4_cfg_shdr *shdr; uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz; + /* sanity check on queue memory */ + if (!hrq || !drq || !cq) + return -ENODEV; if (!phba->sli4_hba.pc_sli4_params.supported) hw_page_size = SLI4_PAGE_SIZE; @@ -12550,6 +12624,7 @@ lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq) uint32_t shdr_status, shdr_add_status; union lpfc_sli4_cfg_shdr *shdr; + /* sanity check on queue memory */ if (!eq) return -ENODEV; mbox = mempool_alloc(eq->phba->mbox_mem_pool, GFP_KERNEL); @@ -12605,6 +12680,7 @@ lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq) uint32_t shdr_status, shdr_add_status; union lpfc_sli4_cfg_shdr *shdr; + /* sanity check on queue memory */ if (!cq) return -ENODEV; mbox = mempool_alloc(cq->phba->mbox_mem_pool, GFP_KERNEL); @@ -12658,6 +12734,7 @@ lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq) uint32_t shdr_status, shdr_add_status; union lpfc_sli4_cfg_shdr *shdr; + /* sanity check on queue memory */ if (!mq) return -ENODEV; mbox = mempool_alloc(mq->phba->mbox_mem_pool, GFP_KERNEL); @@ -12711,6 +12788,7 @@ lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq) uint32_t shdr_status, shdr_add_status; union lpfc_sli4_cfg_shdr *shdr; + /* sanity check on queue memory */ if (!wq) return -ENODEV; mbox = mempool_alloc(wq->phba->mbox_mem_pool, GFP_KERNEL); @@ -12764,6 +12842,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq, uint32_t shdr_status, shdr_add_status; union lpfc_sli4_cfg_shdr *shdr; + /* sanity check on queue memory */ if (!hrq || !drq) return -ENODEV; mbox = mempool_alloc(hrq->phba->mbox_mem_pool, GFP_KERNEL); diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 7d444c444db4..3f266e2c54e0 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -420,7 +420,16 @@ struct lpfc_sli4_hba { void __iomem *STATUSregaddr; void __iomem *CTRLregaddr; void __iomem *ERR1regaddr; +#define SLIPORT_ERR1_REG_ERR_CODE_1 0x1 +#define SLIPORT_ERR1_REG_ERR_CODE_2 0x2 void __iomem *ERR2regaddr; +#define SLIPORT_ERR2_REG_FW_RESTART 0x0 +#define SLIPORT_ERR2_REG_FUNC_PROVISON 0x1 +#define SLIPORT_ERR2_REG_FORCED_DUMP 0x2 +#define SLIPORT_ERR2_REG_FAILURE_EQ 0x3 +#define SLIPORT_ERR2_REG_FAILURE_CQ 0x4 +#define SLIPORT_ERR2_REG_FAILURE_BUS 0x5 +#define SLIPORT_ERR2_REG_FAILURE_RQ 0x6 } if_type2; } u; -- cgit From 1b51197d0fd0c06877c6df1bba84ac4008a7fc60 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 13 Dec 2011 13:23:09 -0500 Subject: [SCSI] lpfc 8.3.28: Add Loopback support for SLI4 adapters - Add Basic support for SLI4 Loopback. (CR 124951, 125766, 124951, 125843, 125832, 125843) - Added missing protection in setting/clearing of phba->link_flag bit field (CR 125994) - Use link type and link number obtained from READ_CONFIG mailbox command. (CR 126264) Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_bsg.c | 358 +++++++++++++++++++++++++++++---------- drivers/scsi/lpfc/lpfc_crtn.h | 9 +- drivers/scsi/lpfc/lpfc_els.c | 125 +++++++++++--- drivers/scsi/lpfc/lpfc_hbadisc.c | 60 +++---- drivers/scsi/lpfc/lpfc_hw.h | 2 +- drivers/scsi/lpfc/lpfc_hw4.h | 7 +- drivers/scsi/lpfc/lpfc_init.c | 40 ++++- drivers/scsi/lpfc/lpfc_mbox.c | 8 + drivers/scsi/lpfc/lpfc_sli.c | 28 ++- 9 files changed, 470 insertions(+), 167 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index c13e54760cb1..56a86baece5b 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -916,9 +916,11 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } else { switch (cmd) { case ELX_LOOPBACK_DATA: - diag_cmd_data_free(phba, - (struct lpfc_dmabufext *) - dmabuf); + if (phba->sli_rev < + LPFC_SLI_REV4) + diag_cmd_data_free(phba, + (struct lpfc_dmabufext + *)dmabuf); break; case ELX_LOOPBACK_XRI_SETUP: if ((phba->sli_rev == @@ -1000,7 +1002,8 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, error_ct_unsol_exit: if (!list_empty(&head)) list_del(&head); - if (evt_req_id == SLI_CT_ELX_LOOPBACK) + if ((phba->sli_rev < LPFC_SLI_REV4) && + (evt_req_id == SLI_CT_ELX_LOOPBACK)) return 0; return 1; } @@ -1566,7 +1569,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) struct diag_mode_set *loopback_mode; uint32_t link_flags; uint32_t timeout; - LPFC_MBOXQ_t *pmboxq; + LPFC_MBOXQ_t *pmboxq = NULL; int mbxstatus = MBX_SUCCESS; int i = 0; int rc = 0; @@ -1615,7 +1618,6 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) rc = -ETIMEDOUT; goto loopback_mode_exit; } - msleep(10); } @@ -1635,7 +1637,9 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) rc = -ENODEV; else { + spin_lock_irq(&phba->hbalock); phba->link_flag |= LS_LOOPBACK_MODE; + spin_unlock_irq(&phba->hbalock); /* wait for the link attention interrupt */ msleep(100); @@ -1659,7 +1663,7 @@ loopback_mode_exit: /* * Let SLI layer release mboxq if mbox command completed after timeout. */ - if (mbxstatus != MBX_TIMEOUT) + if (pmboxq && mbxstatus != MBX_TIMEOUT) mempool_free(pmboxq, phba->mbox_mem_pool); job_error: @@ -1700,11 +1704,16 @@ lpfc_sli4_bsg_set_link_diag_state(struct lpfc_hba *phba, uint32_t diag) rc = -ENOMEM; goto link_diag_state_set_out; } + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3128 Set link to diagnostic state:x%x (x%x/x%x)\n", + diag, phba->sli4_hba.lnk_info.lnk_tp, + phba->sli4_hba.lnk_info.lnk_no); + link_diag_state = &pmboxq->u.mqe.un.link_diag_state; bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req, - phba->sli4_hba.link_state.number); + phba->sli4_hba.lnk_info.lnk_no); bf_set(lpfc_mbx_set_diag_state_link_type, &link_diag_state->u.req, - phba->sli4_hba.link_state.type); + phba->sli4_hba.lnk_info.lnk_tp); if (diag) bf_set(lpfc_mbx_set_diag_state_diag, &link_diag_state->u.req, 1); @@ -1726,6 +1735,79 @@ link_diag_state_set_out: return rc; } +/** + * lpfc_sli4_bsg_set_internal_loopback - set sli4 internal loopback diagnostic + * @phba: Pointer to HBA context object. + * + * This function is responsible for issuing a sli4 mailbox command for setting + * up internal loopback diagnostic. + */ +static int +lpfc_sli4_bsg_set_internal_loopback(struct lpfc_hba *phba) +{ + LPFC_MBOXQ_t *pmboxq; + uint32_t req_len, alloc_len; + struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback; + int mbxstatus = MBX_SUCCESS, rc = 0; + + pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!pmboxq) + return -ENOMEM; + req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) - + sizeof(struct lpfc_sli4_cfg_mhdr)); + alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, + LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK, + req_len, LPFC_SLI4_MBX_EMBED); + if (alloc_len != req_len) { + mempool_free(pmboxq, phba->mbox_mem_pool); + return -ENOMEM; + } + link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback; + bf_set(lpfc_mbx_set_diag_state_link_num, + &link_diag_loopback->u.req, phba->sli4_hba.lnk_info.lnk_no); + bf_set(lpfc_mbx_set_diag_state_link_type, + &link_diag_loopback->u.req, phba->sli4_hba.lnk_info.lnk_tp); + bf_set(lpfc_mbx_set_diag_lpbk_type, &link_diag_loopback->u.req, + LPFC_DIAG_LOOPBACK_TYPE_SERDES); + + mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO); + if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) { + lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, + "3127 Failed setup loopback mode mailbox " + "command, rc:x%x, status:x%x\n", mbxstatus, + pmboxq->u.mb.mbxStatus); + rc = -ENODEV; + } + if (pmboxq && (mbxstatus != MBX_TIMEOUT)) + mempool_free(pmboxq, phba->mbox_mem_pool); + return rc; +} + +/** + * lpfc_sli4_diag_fcport_reg_setup - setup port registrations for diagnostic + * @phba: Pointer to HBA context object. + * + * This function set up SLI4 FC port registrations for diagnostic run, which + * includes all the rpis, vfi, and also vpi. + */ +static int +lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba) +{ + int rc; + + if (phba->pport->fc_flag & FC_VFI_REGISTERED) { + lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, + "3136 Port still had vfi registered: " + "mydid:x%x, fcfi:%d, vfi:%d, vpi:%d\n", + phba->pport->fc_myDID, phba->fcf.fcfi, + phba->sli4_hba.vfi_ids[phba->pport->vfi], + phba->vpi_ids[phba->pport->vpi]); + return -EINVAL; + } + rc = lpfc_issue_reg_vfi(phba->pport); + return rc; +} + /** * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command * @phba: Pointer to HBA context object. @@ -1738,10 +1820,8 @@ static int lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) { struct diag_mode_set *loopback_mode; - uint32_t link_flags, timeout, req_len, alloc_len; - struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback; - LPFC_MBOXQ_t *pmboxq = NULL; - int mbxstatus = MBX_SUCCESS, i, rc = 0; + uint32_t link_flags, timeout; + int i, rc = 0; /* no data to return just the return code */ job->reply->reply_payload_rcv_len = 0; @@ -1762,65 +1842,100 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) if (rc) goto job_error; + /* indicate we are in loobpack diagnostic mode */ + spin_lock_irq(&phba->hbalock); + phba->link_flag |= LS_LOOPBACK_MODE; + spin_unlock_irq(&phba->hbalock); + + /* reset port to start frome scratch */ + rc = lpfc_selective_reset(phba); + if (rc) + goto job_error; + /* bring the link to diagnostic mode */ + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3129 Bring link to diagnostic state.\n"); loopback_mode = (struct diag_mode_set *) job->request->rqst_data.h_vendor.vendor_cmd; link_flags = loopback_mode->type; timeout = loopback_mode->timeout * 100; rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1); - if (rc) + if (rc) { + lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, + "3130 Failed to bring link to diagnostic " + "state, rc:x%x\n", rc); goto loopback_mode_exit; + } /* wait for link down before proceeding */ i = 0; while (phba->link_state != LPFC_LINK_DOWN) { if (i++ > timeout) { rc = -ETIMEDOUT; + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3131 Timeout waiting for link to " + "diagnostic mode, timeout:%d ms\n", + timeout * 10); goto loopback_mode_exit; } msleep(10); } + /* set up loopback mode */ - pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!pmboxq) { - rc = -ENOMEM; - goto loopback_mode_exit; - } - req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) - - sizeof(struct lpfc_sli4_cfg_mhdr)); - alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, - LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK, - req_len, LPFC_SLI4_MBX_EMBED); - if (alloc_len != req_len) { - rc = -ENOMEM; + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3132 Set up loopback mode:x%x\n", link_flags); + + if (link_flags == INTERNAL_LOOP_BACK) + rc = lpfc_sli4_bsg_set_internal_loopback(phba); + else if (link_flags == EXTERNAL_LOOP_BACK) + rc = lpfc_hba_init_link_fc_topology(phba, + FLAGS_TOPOLOGY_MODE_PT_PT, + MBX_NOWAIT); + else { + rc = -EINVAL; + lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, + "3141 Loopback mode:x%x not supported\n", + link_flags); goto loopback_mode_exit; } - link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback; - bf_set(lpfc_mbx_set_diag_state_link_num, - &link_diag_loopback->u.req, phba->sli4_hba.link_state.number); - bf_set(lpfc_mbx_set_diag_state_link_type, - &link_diag_loopback->u.req, phba->sli4_hba.link_state.type); - if (link_flags == INTERNAL_LOOP_BACK) - bf_set(lpfc_mbx_set_diag_lpbk_type, - &link_diag_loopback->u.req, - LPFC_DIAG_LOOPBACK_TYPE_INTERNAL); - else - bf_set(lpfc_mbx_set_diag_lpbk_type, - &link_diag_loopback->u.req, - LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL); - mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO); - if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) - rc = -ENODEV; - else { - phba->link_flag |= LS_LOOPBACK_MODE; + if (!rc) { /* wait for the link attention interrupt */ msleep(100); i = 0; + while (phba->link_state < LPFC_LINK_UP) { + if (i++ > timeout) { + rc = -ETIMEDOUT; + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3137 Timeout waiting for link up " + "in loopback mode, timeout:%d ms\n", + timeout * 10); + break; + } + msleep(10); + } + } + + /* port resource registration setup for loopback diagnostic */ + if (!rc) { + /* set up a none zero myDID for loopback test */ + phba->pport->fc_myDID = 1; + rc = lpfc_sli4_diag_fcport_reg_setup(phba); + } else + goto loopback_mode_exit; + + if (!rc) { + /* wait for the port ready */ + msleep(100); + i = 0; while (phba->link_state != LPFC_HBA_READY) { if (i++ > timeout) { rc = -ETIMEDOUT; + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3133 Timeout waiting for port " + "loopback mode ready, timeout:%d ms\n", + timeout * 10); break; } msleep(10); @@ -1828,14 +1943,14 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) } loopback_mode_exit: + /* clear loopback diagnostic mode */ + if (rc) { + spin_lock_irq(&phba->hbalock); + phba->link_flag &= ~LS_LOOPBACK_MODE; + spin_unlock_irq(&phba->hbalock); + } lpfc_bsg_diag_mode_exit(phba); - /* - * Let SLI layer release mboxq if mbox command completed after timeout. - */ - if (pmboxq && (mbxstatus != MBX_TIMEOUT)) - mempool_free(pmboxq, phba->mbox_mem_pool); - job_error: /* make error code available to userspace */ job->reply->result = rc; @@ -1879,7 +1994,6 @@ lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job) rc = -ENODEV; return rc; - } /** @@ -1895,7 +2009,9 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) struct Scsi_Host *shost; struct lpfc_vport *vport; struct lpfc_hba *phba; - int rc; + struct diag_mode_set *loopback_mode_end_cmd; + uint32_t timeout; + int rc, i; shost = job->shost; if (!shost) @@ -1913,11 +2029,47 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) LPFC_SLI_INTF_IF_TYPE_2) return -ENODEV; + /* clear loopback diagnostic mode */ + spin_lock_irq(&phba->hbalock); + phba->link_flag &= ~LS_LOOPBACK_MODE; + spin_unlock_irq(&phba->hbalock); + loopback_mode_end_cmd = (struct diag_mode_set *) + job->request->rqst_data.h_vendor.vendor_cmd; + timeout = loopback_mode_end_cmd->timeout * 100; + rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); + if (rc) { + lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, + "3139 Failed to bring link to diagnostic " + "state, rc:x%x\n", rc); + goto loopback_mode_end_exit; + } + + /* wait for link down before proceeding */ + i = 0; + while (phba->link_state != LPFC_LINK_DOWN) { + if (i++ > timeout) { + rc = -ETIMEDOUT; + lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, + "3140 Timeout waiting for link to " + "diagnostic mode_end, timeout:%d ms\n", + timeout * 10); + /* there is nothing much we can do here */ + break; + } + msleep(10); + } - if (!rc) - rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); + /* reset port resource registrations */ + rc = lpfc_selective_reset(phba); + phba->pport->fc_myDID = 0; +loopback_mode_end_exit: + /* make return code available to userspace */ + job->reply->result = rc; + /* complete the job back to userspace if no error */ + if (rc == 0) + job->job_done(job); return rc; } @@ -2012,9 +2164,9 @@ lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) } run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test; bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req, - phba->sli4_hba.link_state.number); + phba->sli4_hba.lnk_info.lnk_no); bf_set(lpfc_mbx_run_diag_test_link_type, &run_link_diag_test->u.req, - phba->sli4_hba.link_state.type); + phba->sli4_hba.lnk_info.lnk_tp); bf_set(lpfc_mbx_run_diag_test_test_id, &run_link_diag_test->u.req, link_diag_test_cmd->test_id); bf_set(lpfc_mbx_run_diag_test_loops, &run_link_diag_test->u.req, @@ -2091,10 +2243,18 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi) if (!mbox) return -ENOMEM; - if (phba->sli_rev == LPFC_SLI_REV4) + if (phba->sli_rev < LPFC_SLI_REV4) + status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID, + (uint8_t *)&phba->pport->fc_sparam, + mbox, *rpi); + else { *rpi = lpfc_sli4_alloc_rpi(phba); - status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID, - (uint8_t *)&phba->pport->fc_sparam, mbox, *rpi); + status = lpfc_reg_rpi(phba, phba->pport->vpi, + phba->pport->fc_myDID, + (uint8_t *)&phba->pport->fc_sparam, + mbox, *rpi); + } + if (status) { mempool_free(mbox, phba->mbox_mem_pool); if (phba->sli_rev == LPFC_SLI_REV4) @@ -2117,7 +2277,8 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi) return -ENODEV; } - *rpi = mbox->u.mb.un.varWords[0]; + if (phba->sli_rev < LPFC_SLI_REV4) + *rpi = mbox->u.mb.un.varWords[0]; lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys); kfree(dmabuff); @@ -2142,7 +2303,12 @@ static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi) if (mbox == NULL) return -ENOMEM; - lpfc_unreg_login(phba, 0, rpi, mbox); + if (phba->sli_rev < LPFC_SLI_REV4) + lpfc_unreg_login(phba, 0, rpi, mbox); + else + lpfc_unreg_login(phba, phba->pport->vpi, + phba->sli4_hba.rpi_ids[rpi], mbox); + status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) { @@ -2630,15 +2796,15 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) uint32_t full_size; size_t segment_len = 0, segment_offset = 0, current_offset = 0; uint16_t rpi = 0; - struct lpfc_iocbq *cmdiocbq, *rspiocbq; - IOCB_t *cmd, *rsp; + struct lpfc_iocbq *cmdiocbq, *rspiocbq = NULL; + IOCB_t *cmd, *rsp = NULL; struct lpfc_sli_ct_request *ctreq; struct lpfc_dmabuf *txbmp; struct ulp_bde64 *txbpl = NULL; struct lpfc_dmabufext *txbuffer = NULL; struct list_head head; struct lpfc_dmabuf *curr; - uint16_t txxri, rxxri; + uint16_t txxri = 0, rxxri; uint32_t num_bde; uint8_t *ptr = NULL, *rx_databuf = NULL; int rc = 0; @@ -2665,7 +2831,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) rc = -EINVAL; goto loopback_test_exit; } - diag_mode = (struct diag_mode_test *) job->request->rqst_data.h_vendor.vendor_cmd; @@ -2720,18 +2885,19 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) if (rc) goto loopback_test_exit; - rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri); - if (rc) { - lpfcdiag_loop_self_unreg(phba, rpi); - goto loopback_test_exit; - } + if (phba->sli_rev < LPFC_SLI_REV4) { + rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri); + if (rc) { + lpfcdiag_loop_self_unreg(phba, rpi); + goto loopback_test_exit; + } - rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size); - if (rc) { - lpfcdiag_loop_self_unreg(phba, rpi); - goto loopback_test_exit; + rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size); + if (rc) { + lpfcdiag_loop_self_unreg(phba, rpi); + goto loopback_test_exit; + } } - evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid, SLI_CT_ELX_LOOPBACK); if (!evt) { @@ -2746,7 +2912,8 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) spin_unlock_irqrestore(&phba->ct_ev_lock, flags); cmdiocbq = lpfc_sli_get_iocbq(phba); - rspiocbq = lpfc_sli_get_iocbq(phba); + if (phba->sli_rev < LPFC_SLI_REV4) + rspiocbq = lpfc_sli_get_iocbq(phba); txbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); if (txbmp) { @@ -2759,14 +2926,18 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) } } - if (!cmdiocbq || !rspiocbq || !txbmp || !txbpl || !txbuffer || - !txbmp->virt) { + if (!cmdiocbq || !txbmp || !txbpl || !txbuffer || !txbmp->virt) { + rc = -ENOMEM; + goto err_loopback_test_exit; + } + if ((phba->sli_rev < LPFC_SLI_REV4) && !rspiocbq) { rc = -ENOMEM; goto err_loopback_test_exit; } cmd = &cmdiocbq->iocb; - rsp = &rspiocbq->iocb; + if (phba->sli_rev < LPFC_SLI_REV4) + rsp = &rspiocbq->iocb; INIT_LIST_HEAD(&head); list_add_tail(&head, &txbuffer->dma.list); @@ -2796,7 +2967,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) list_del(&head); /* Build the XMIT_SEQUENCE iocb */ - num_bde = (uint32_t)txbuffer->flag; cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(txbmp->phys); @@ -2813,16 +2983,27 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) cmd->ulpBdeCount = 1; cmd->ulpLe = 1; cmd->ulpClass = CLASS3; - cmd->ulpContext = txxri; + if (phba->sli_rev < LPFC_SLI_REV4) { + cmd->ulpContext = txxri; + } else { + cmd->un.xseq64.bdl.ulpIoTag32 = 0; + cmd->un.ulpWord[3] = phba->sli4_hba.rpi_ids[rpi]; + cmdiocbq->context3 = txbmp; + cmdiocbq->sli4_xritag = NO_XRI; + cmd->unsli3.rcvsli3.ox_id = 0xffff; + } cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; cmdiocbq->vport = phba->pport; - iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, rspiocbq, (phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT); - if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) { + if ((iocb_stat != IOCB_SUCCESS) || ((phba->sli_rev < LPFC_SLI_REV4) && + (rsp->ulpStatus != IOCB_SUCCESS))) { + lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, + "3126 Failed loopback test issue iocb: " + "iocb_stat:x%x\n", iocb_stat); rc = -EIO; goto err_loopback_test_exit; } @@ -2832,9 +3013,12 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) evt->wq, !list_empty(&evt->events_to_see), ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ); evt->waiting = 0; - if (list_empty(&evt->events_to_see)) + if (list_empty(&evt->events_to_see)) { rc = (time_left) ? -EINTR : -ETIMEDOUT; - else { + lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, + "3125 Not receiving unsolicited event, " + "rc:x%x\n", rc); + } else { spin_lock_irqsave(&phba->ct_ev_lock, flags); list_move(evt->events_to_see.prev, &evt->events_to_get); evdat = list_entry(evt->events_to_get.prev, @@ -2891,7 +3075,7 @@ loopback_test_exit: job->reply->result = rc; job->dd_data = NULL; /* complete the job back to userspace if no error */ - if (rc == 0) + if (rc == IOCB_SUCCESS) job->job_done(job); return rc; } @@ -3078,7 +3262,9 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, && (mb->un.varWords[1] == 1)) { phba->wait_4_mlo_maint_flg = 1; } else if (mb->un.varWords[0] == SETVAR_MLORST) { + spin_lock_irq(&phba->hbalock); phba->link_flag &= ~LS_LOOPBACK_MODE; + spin_unlock_irq(&phba->hbalock); phba->fc_topology = LPFC_TOPOLOGY_PT_PT; } break; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index bcc021f3c8eb..26924b7a6cde 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -78,6 +78,7 @@ void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *, LPFC_MBOXQ_t *); +void lpfc_unregister_vfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_enqueue_node(struct lpfc_vport *, struct lpfc_nodelist *); void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *); struct lpfc_nodelist *lpfc_enable_node(struct lpfc_vport *, @@ -453,7 +454,11 @@ int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int); uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *); int lpfc_sli4_queue_create(struct lpfc_hba *); void lpfc_sli4_queue_destroy(struct lpfc_hba *); -int lpfc_sli4_read_config(struct lpfc_hba *phba); -int lpfc_scsi_buf_update(struct lpfc_hba *phba); void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *, struct sli4_wcqe_xri_aborted *); +int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t, uint32_t); +int lpfc_issue_reg_vfi(struct lpfc_vport *); +int lpfc_issue_unreg_vfi(struct lpfc_vport *); +int lpfc_selective_reset(struct lpfc_hba *); +int lpfc_sli4_read_config(struct lpfc_hba *phba); +int lpfc_scsi_buf_update(struct lpfc_hba *phba); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 0b662db23284..7afc757338de 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -421,13 +421,13 @@ fail: * @vport: pointer to a host virtual N_Port data structure. * * This routine issues a REG_VFI mailbox for the vfi, vpi, fcfi triplet for - * the @vport. This mailbox command is necessary for FCoE only. + * the @vport. This mailbox command is necessary for SLI4 port only. * * Return code * 0 - successfully issued REG_VFI for @vport * A failure code otherwise. **/ -static int +int lpfc_issue_reg_vfi(struct lpfc_vport *vport) { struct lpfc_hba *phba = vport->phba; @@ -438,10 +438,14 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) int rc = 0; sp = &phba->fc_fabparam; - ndlp = lpfc_findnode_did(vport, Fabric_DID); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { - rc = -ENODEV; - goto fail; + /* move forward in case of SLI4 FC port loopback test */ + if ((phba->sli_rev == LPFC_SLI_REV4) && + !(phba->link_flag & LS_LOOPBACK_MODE)) { + ndlp = lpfc_findnode_did(vport, Fabric_DID); + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + rc = -ENODEV; + goto fail; + } } dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); @@ -486,6 +490,54 @@ fail: return rc; } +/** + * lpfc_issue_unreg_vfi - Unregister VFI for this vport's fabric login + * @vport: pointer to a host virtual N_Port data structure. + * + * This routine issues a UNREG_VFI mailbox with the vfi, vpi, fcfi triplet for + * the @vport. This mailbox command is necessary for SLI4 port only. + * + * Return code + * 0 - successfully issued REG_VFI for @vport + * A failure code otherwise. + **/ +int +lpfc_issue_unreg_vfi(struct lpfc_vport *vport) +{ + struct lpfc_hba *phba = vport->phba; + struct Scsi_Host *shost; + LPFC_MBOXQ_t *mboxq; + int rc; + + mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mboxq) { + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, + "2556 UNREG_VFI mbox allocation failed" + "HBA state x%x\n", phba->pport->port_state); + return -ENOMEM; + } + + lpfc_unreg_vfi(mboxq, vport); + mboxq->vport = vport; + mboxq->mbox_cmpl = lpfc_unregister_vfi_cmpl; + + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, + "2557 UNREG_VFI issue mbox failed rc x%x " + "HBA state x%x\n", + rc, phba->pport->port_state); + mempool_free(mboxq, phba->mbox_mem_pool); + return -EIO; + } + + shost = lpfc_shost_from_vport(vport); + spin_lock_irq(shost->host_lock); + vport->fc_flag &= ~FC_VFI_REGISTERED; + spin_unlock_irq(shost->host_lock); + return 0; +} + /** * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean. * @vport: pointer to a host virtual N_Port data structure. @@ -615,7 +667,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, "1816 FLOGI NPIV supported, " "response data 0x%x\n", sp->cmn.response_multiple_NPort); + spin_lock_irq(&phba->hbalock); phba->link_flag |= LS_NPIV_FAB_SUPPORTED; + spin_unlock_irq(&phba->hbalock); } else { /* Because we asked f/w for NPIV it still expects us to call reg_vnpid atleast for the physcial host */ @@ -623,7 +677,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, LOG_ELS | LOG_VPORT, "1817 Fabric does not support NPIV " "- configuring single port mode.\n"); + spin_lock_irq(&phba->hbalock); phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; + spin_unlock_irq(&phba->hbalock); } } @@ -686,11 +742,16 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_do_scr_ns_plogi(phba, vport); } else if (vport->fc_flag & FC_VFI_REGISTERED) lpfc_issue_init_vpi(vport); - else + else { + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "3135 Need register VFI: (x%x/%x)\n", + vport->fc_prevDID, vport->fc_myDID); lpfc_issue_reg_vfi(vport); + } } return 0; } + /** * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port * @vport: pointer to a host virtual N_Port data structure. @@ -907,9 +968,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no * alpa map would take too long otherwise. */ - if (phba->alpa_map[0] == 0) { + if (phba->alpa_map[0] == 0) vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; - } if ((phba->sli_rev == LPFC_SLI_REV4) && (!(vport->fc_flag & FC_VFI_REGISTERED) || (vport->fc_prevDID != vport->fc_myDID))) { @@ -1164,8 +1224,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { icmd = &iocb->iocb; - if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR && - icmd->un.elsreq64.bdl.ulpIoTag32) { + if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) { ndlp = (struct lpfc_nodelist *)(iocb->context1); if (ndlp && NLP_CHK_NODE_ACT(ndlp) && (ndlp->nlp_DID == Fabric_DID)) @@ -4879,23 +4938,31 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, sizeof(struct lpfc_name)); if (!rc) { - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mbox) + if (phba->sli_rev < LPFC_SLI_REV4) { + mbox = mempool_alloc(phba->mbox_mem_pool, + GFP_KERNEL); + if (!mbox) + return 1; + lpfc_linkdown(phba); + lpfc_init_link(phba, mbox, + phba->cfg_topology, + phba->cfg_link_speed); + mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0; + mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + mbox->vport = vport; + rc = lpfc_sli_issue_mbox(phba, mbox, + MBX_NOWAIT); + lpfc_set_loopback_flag(phba); + if (rc == MBX_NOT_FINISHED) + mempool_free(mbox, phba->mbox_mem_pool); return 1; - - lpfc_linkdown(phba); - lpfc_init_link(phba, mbox, - phba->cfg_topology, - phba->cfg_link_speed); - mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0; - mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - mbox->vport = vport; - rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); - lpfc_set_loopback_flag(phba); - if (rc == MBX_NOT_FINISHED) { - mempool_free(mbox, phba->mbox_mem_pool); + } else { + /* abort the flogi coming back to ourselves + * due to external loopback on the port. + */ + lpfc_els_abort_flogi(phba); + return 0; } - return 1; } else if (rc > 0) { /* greater than */ spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_PT2PT_PLOGI; @@ -5850,8 +5917,12 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, vport->fc_myDID = vport->fc_prevDID; if (phba->sli_rev < LPFC_SLI_REV4) lpfc_issue_fabric_reglogin(vport); - else + else { + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "3138 Need register VFI: (x%x/%x)\n", + vport->fc_prevDID, vport->fc_myDID); lpfc_issue_reg_vfi(vport); + } } } return 0; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index d96498581ebe..678a4b11059c 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1074,6 +1074,12 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mempool_free(pmb, phba->mbox_mem_pool); + /* don't perform discovery for SLI4 loopback diagnostic test */ + if ((phba->sli_rev == LPFC_SLI_REV4) && + !(phba->hba_flag & HBA_FCOE_MODE) && + (phba->link_flag & LS_LOOPBACK_MODE)) + return; + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP && vport->fc_flag & FC_PUBLIC_LOOP && !(vport->fc_flag & FC_LBIT)) { @@ -2847,10 +2853,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) lpfc_disc_list_loopmap(vport); /* Start discovery */ lpfc_disc_start(vport); - goto fail_free_mem; + goto out_free_mem; } lpfc_vport_set_state(vport, FC_VPORT_FAILED); - goto fail_free_mem; + goto out_free_mem; } /* The VPI is implicitly registered when the VFI is registered */ spin_lock_irq(shost->host_lock); @@ -2860,6 +2866,13 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI; spin_unlock_irq(shost->host_lock); + /* In case SLI4 FC loopback test, we are ready */ + if ((phba->sli_rev == LPFC_SLI_REV4) && + (phba->link_flag & LS_LOOPBACK_MODE)) { + phba->link_state = LPFC_HBA_READY; + goto out_free_mem; + } + if (vport->port_state == LPFC_FABRIC_CFG_LINK) { /* For private loop just start discovery and we are done. */ if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && @@ -2874,7 +2887,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) } } -fail_free_mem: +out_free_mem: mempool_free(mboxq, phba->mbox_mem_pool); lpfc_mbuf_free(phba, dmabuf->virt, dmabuf->phys); kfree(dmabuf); @@ -3235,15 +3248,14 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } else if (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_DOWN) { phba->fc_stat.LinkDown++; - if (phba->link_flag & LS_LOOPBACK_MODE) { + if (phba->link_flag & LS_LOOPBACK_MODE) lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "1308 Link Down Event in loop back mode " "x%x received " "Data: x%x x%x x%x\n", la->eventTag, phba->fc_eventTag, phba->pport->port_state, vport->fc_flag); - } - else { + else lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "1305 Link Down Event x%x received " "Data: x%x x%x x%x x%x x%x\n", @@ -3251,7 +3263,6 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) phba->pport->port_state, vport->fc_flag, bf_get(lpfc_mbx_read_top_mm, la), bf_get(lpfc_mbx_read_top_fa, la)); - } lpfc_mbx_issue_link_down(phba); } if ((bf_get(lpfc_mbx_read_top_mm, la)) && @@ -5682,7 +5693,7 @@ out: * * This function frees memory associated with the mailbox command. */ -static void +void lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { struct lpfc_vport *vport = mboxq->vport; @@ -5734,7 +5745,6 @@ lpfc_unregister_fcfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) int lpfc_unregister_fcf_prep(struct lpfc_hba *phba) { - LPFC_MBOXQ_t *mbox; struct lpfc_vport **vports; struct lpfc_nodelist *ndlp; struct Scsi_Host *shost; @@ -5770,35 +5780,9 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) /* Cleanup any outstanding ELS commands */ lpfc_els_flush_all_cmd(phba); - /* Unregister VFI */ - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, - "2556 UNREG_VFI mbox allocation failed" - "HBA state x%x\n", phba->pport->port_state); - return -ENOMEM; - } - - lpfc_unreg_vfi(mbox, phba->pport); - mbox->vport = phba->pport; - mbox->mbox_cmpl = lpfc_unregister_vfi_cmpl; - - rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, - "2557 UNREG_VFI issue mbox failed rc x%x " - "HBA state x%x\n", - rc, phba->pport->port_state); - mempool_free(mbox, phba->mbox_mem_pool); - return -EIO; - } - - shost = lpfc_shost_from_vport(phba->pport); - spin_lock_irq(shost->host_lock); - phba->pport->fc_flag &= ~FC_VFI_REGISTERED; - spin_unlock_irq(shost->host_lock); - - return 0; + /* Unregister the physical port VFI */ + rc = lpfc_issue_unreg_vfi(phba->pport); + return rc; } /** diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 73fc5318641b..7245bead3755 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1858,8 +1858,8 @@ typedef struct { uint8_t fabric_AL_PA; /* If using a Fabric Assigned AL_PA */ #endif -#define FLAGS_LOCAL_LB 0x01 /* link_flags (=1) ENDEC loopback */ #define FLAGS_TOPOLOGY_MODE_LOOP_PT 0x00 /* Attempt loop then pt-pt */ +#define FLAGS_LOCAL_LB 0x01 /* link_flags (=1) ENDEC loopback */ #define FLAGS_TOPOLOGY_MODE_PT_PT 0x02 /* Attempt pt-pt only */ #define FLAGS_TOPOLOGY_MODE_LOOP 0x04 /* Attempt loop only */ #define FLAGS_TOPOLOGY_MODE_PT_LOOP 0x06 /* Attempt pt-pt then loop */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 43c4c56f9e68..e5bfa7f334e3 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1351,11 +1351,11 @@ struct lpfc_mbx_set_link_diag_loopback { struct { uint32_t word0; #define lpfc_mbx_set_diag_lpbk_type_SHIFT 0 -#define lpfc_mbx_set_diag_lpbk_type_MASK 0x00000001 +#define lpfc_mbx_set_diag_lpbk_type_MASK 0x00000003 #define lpfc_mbx_set_diag_lpbk_type_WORD word0 #define LPFC_DIAG_LOOPBACK_TYPE_DISABLE 0x0 #define LPFC_DIAG_LOOPBACK_TYPE_INTERNAL 0x1 -#define LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL 0x2 +#define LPFC_DIAG_LOOPBACK_TYPE_SERDES 0x2 #define lpfc_mbx_set_diag_lpbk_link_num_SHIFT 16 #define lpfc_mbx_set_diag_lpbk_link_num_MASK 0x0000003F #define lpfc_mbx_set_diag_lpbk_link_num_WORD word0 @@ -3324,6 +3324,9 @@ struct wqe_rctl_dfctl { #define wqe_la_SHIFT 3 #define wqe_la_MASK 0x000000001 #define wqe_la_WORD word5 +#define wqe_xo_SHIFT 6 +#define wqe_xo_MASK 0x000000001 +#define wqe_xo_WORD word5 #define wqe_ls_SHIFT 7 #define wqe_ls_MASK 0x000000001 #define wqe_ls_WORD word5 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index cb714d2342d4..dfea2dada02c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -627,6 +627,28 @@ lpfc_config_port_post(struct lpfc_hba *phba) **/ int lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag) +{ + return lpfc_hba_init_link_fc_topology(phba, phba->cfg_topology, flag); +} + +/** + * lpfc_hba_init_link_fc_topology - Initialize FC link with desired topology + * @phba: pointer to lpfc hba data structure. + * @fc_topology: desired fc topology. + * @flag: mailbox command issue mode - either MBX_POLL or MBX_NOWAIT + * + * This routine will issue the INIT_LINK mailbox command call. + * It is available to other drivers through the lpfc_hba data + * structure for use as a delayed link up mechanism with the + * module parameter lpfc_suppress_link_up. + * + * Return code + * 0 - success + * Any other value - error + **/ +int +lpfc_hba_init_link_fc_topology(struct lpfc_hba *phba, uint32_t fc_topology, + uint32_t flag) { struct lpfc_vport *vport = phba->pport; LPFC_MBOXQ_t *pmb; @@ -661,9 +683,10 @@ lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag) phba->cfg_link_speed); phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; } - lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); + lpfc_init_link(phba, pmb, fc_topology, phba->cfg_link_speed); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - lpfc_set_loopback_flag(phba); + if (phba->sli_rev < LPFC_SLI_REV4) + lpfc_set_loopback_flag(phba); rc = lpfc_sli_issue_mbox(phba, pmb, flag); if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -6654,9 +6677,10 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) phba->sli4_hba.sp_eq->queue_id); /* Set up fast-path event queue */ - if (!phba->sli4_hba.fp_eq) { + if (phba->cfg_fcp_eq_count && !phba->sli4_hba.fp_eq) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3147 Fast-path EQs not allocated\n"); + rc = -ENOMEM; goto out_destroy_sp_eq; } for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_eq_count; fcp_eqidx++) { @@ -6664,6 +6688,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0522 Fast-path EQ (%d) not " "allocated\n", fcp_eqidx); + rc = -ENOMEM; goto out_destroy_fp_eq; } rc = lpfc_eq_create(phba, phba->sli4_hba.fp_eq[fcp_eqidx], @@ -6688,6 +6713,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) if (!phba->sli4_hba.mbx_cq) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0528 Mailbox CQ not allocated\n"); + rc = -ENOMEM; goto out_destroy_fp_eq; } rc = lpfc_cq_create(phba, phba->sli4_hba.mbx_cq, phba->sli4_hba.sp_eq, @@ -6707,6 +6733,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) if (!phba->sli4_hba.els_cq) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0530 ELS CQ not allocated\n"); + rc = -ENOMEM; goto out_destroy_mbx_cq; } rc = lpfc_cq_create(phba, phba->sli4_hba.els_cq, phba->sli4_hba.sp_eq, @@ -6727,6 +6754,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3148 Fast-path FCP CQ array not " "allocated\n"); + rc = -ENOMEM; goto out_destroy_els_cq; } fcp_cqidx = 0; @@ -6735,6 +6763,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0526 Fast-path FCP CQ (%d) not " "allocated\n", fcp_cqidx); + rc = -ENOMEM; goto out_destroy_fcp_cq; } if (phba->cfg_fcp_eq_count) @@ -6773,6 +6802,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) if (!phba->sli4_hba.mbx_wq) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0538 Slow-path MQ not allocated\n"); + rc = -ENOMEM; goto out_destroy_fcp_cq; } rc = lpfc_mq_create(phba, phba->sli4_hba.mbx_wq, @@ -6792,6 +6822,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) if (!phba->sli4_hba.els_wq) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0536 Slow-path ELS WQ not allocated\n"); + rc = -ENOMEM; goto out_destroy_mbx_wq; } rc = lpfc_wq_create(phba, phba->sli4_hba.els_wq, @@ -6812,6 +6843,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "3149 Fast-path FCP WQ array not " "allocated\n"); + rc = -ENOMEM; goto out_destroy_els_wq; } for (fcp_wqidx = 0; fcp_wqidx < phba->cfg_fcp_wq_count; fcp_wqidx++) { @@ -6819,6 +6851,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0534 Fast-path FCP WQ (%d) not " "allocated\n", fcp_wqidx); + rc = -ENOMEM; goto out_destroy_fcp_wq; } rc = lpfc_wq_create(phba, phba->sli4_hba.fcp_wq[fcp_wqidx], @@ -6849,6 +6882,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) if (!phba->sli4_hba.hdr_rq || !phba->sli4_hba.dat_rq) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0540 Receive Queue not allocated\n"); + rc = -ENOMEM; goto out_destroy_fcp_wq; } diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 328782efc839..20336f09fb3c 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -2133,6 +2133,14 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam); reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; bf_set(lpfc_reg_vfi_nport_id, reg_vfi, vport->fc_myDID); + lpfc_printf_vlog(vport, KERN_INFO, LOG_MBOX, + "3134 Register VFI, mydid:x%x, fcfi:%d, " + " vfi:%d, vpi:%d, fc_pname:%x%x\n", + vport->fc_myDID, + vport->phba->fcf.fcfi, + vport->phba->sli4_hba.vfi_ids[vport->vfi], + vport->phba->vpi_ids[vport->vpi], + reg_vfi->wwn[0], reg_vfi->wwn[1]); } /** diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e27cb44b3ec2..23a27592388c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -3619,8 +3619,8 @@ lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask) * lpfc_reset_barrier - Make HBA ready for HBA reset * @phba: Pointer to HBA context object. * - * This function is called before resetting an HBA. This - * function requests HBA to quiesce DMAs before a reset. + * This function is called before resetting an HBA. This function is called + * with hbalock held and requests HBA to quiesce DMAs before a reset. **/ void lpfc_reset_barrier(struct lpfc_hba *phba) { @@ -6267,9 +6267,12 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) goto out_unset_queue; } } else if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK) { - rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); - if (rc) - goto out_unset_queue; + /* don't perform init_link on SLI4 FC port loopback test */ + if (!(phba->link_flag & LS_LOOPBACK_MODE)) { + rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); + if (rc) + goto out_unset_queue; + } } mempool_free(mboxq, phba->mbox_mem_pool); return rc; @@ -7540,6 +7543,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, struct ulp_bde64 *bpl = NULL; struct ulp_bde64 bde; struct sli4_sge *sgl = NULL; + struct lpfc_dmabuf *dmabuf; IOCB_t *icmd; int numBdes = 0; int i = 0; @@ -7558,9 +7562,12 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, * have not been byteswapped yet so there is no * need to swap them back. */ - bpl = (struct ulp_bde64 *) - ((struct lpfc_dmabuf *)piocbq->context3)->virt; + if (piocbq->context3) + dmabuf = (struct lpfc_dmabuf *)piocbq->context3; + else + return xritag; + bpl = (struct ulp_bde64 *)dmabuf->virt; if (!bpl) return xritag; @@ -7670,6 +7677,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, struct ulp_bde64 bde; struct lpfc_nodelist *ndlp; uint32_t *pcmd; + uint32_t if_type; fip = phba->hba_flag & HBA_FIP_SUPPORT; /* The fcp commands will set command type */ @@ -7743,7 +7751,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, >> LPFC_FIP_ELS_ID_SHIFT); pcmd = (uint32_t *) (((struct lpfc_dmabuf *) iocbq->context2)->virt); - if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { + if_type = bf_get(lpfc_sli_intf_if_type, + &phba->sli4_hba.sli_intf); + if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { if (pcmd && (*pcmd == ELS_CMD_FLOGI || *pcmd == ELS_CMD_SCR || *pcmd == ELS_CMD_PLOGI)) { @@ -7776,6 +7786,8 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, /* The entire sequence is transmitted for this IOCB */ xmit_len = total_len; cmnd = CMD_XMIT_SEQUENCE64_CR; + if (phba->link_flag & LS_LOOPBACK_MODE) + bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1); case CMD_XMIT_SEQUENCE64_CR: /* word3 iocb=io_tag32 wqe=reserved */ wqe->xmit_sequence.rsvd3 = 0; -- cgit From 5c41dc3a79150e93e5d050871a10b761be8281a1 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 13 Dec 2011 13:23:28 -0500 Subject: [SCSI] lpfc 8.3.28: Update driver version to 8.3.28 Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index b0630e37f1ef..dd044d01a07f 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.27" +#define LPFC_DRIVER_VERSION "8.3.28" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" -- cgit From fd778461524849afd035679030ae8e8873c72b81 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Jan 2012 12:25:16 -0500 Subject: security: remove the security_netlink_recv hook as it is equivalent to capable() Once upon a time netlink was not sync and we had to get the effective capabilities from the skb that was being received. Today we instead get the capabilities from the current task. This has rendered the entire purpose of the hook moot as it is now functionally equivalent to the capable() call. Signed-off-by: Eric Paris --- drivers/scsi/scsi_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index 26a8a45584ef..feee1cc39ea0 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c @@ -111,7 +111,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb) goto next_msg; } - if (security_netlink_recv(skb, CAP_SYS_ADMIN)) { + if (!capable(CAP_SYS_ADMIN)) { err = -EPERM; goto next_msg; } -- cgit From fb51ccbf217c1c994607b6519c7d85250928553d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 4 Nov 2011 09:45:59 +0100 Subject: PCI: Rework config space blocking services pci_block_user_cfg_access was designed for the use case that a single context, the IPR driver, temporarily delays user space accesses to the config space via sysfs. This assumption became invalid by the time pci_dev_reset was added as locking instance. Today, if you run two loops in parallel that reset the same device via sysfs, you end up with a kernel BUG as pci_block_user_cfg_access detect the broken assumption. This reworks the pci_block_user_cfg_access to a sleeping service pci_cfg_access_lock and an atomic-compatible variant called pci_cfg_access_trylock. The former not only blocks user space access as before but also waits if access was already locked. The latter service just returns false in this case, allowing the caller to resolve the conflict instead of raising a BUG. Adaptions of the ipr driver were originally written by Brian King. Acked-by: Brian King Acked-by: Michael S. Tsirkin Signed-off-by: Jan Kiszka Signed-off-by: Jesse Barnes --- drivers/scsi/ipr.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++------ drivers/scsi/ipr.h | 1 + 2 files changed, 61 insertions(+), 7 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index fd860d952b28..67b169b7a5be 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7638,8 +7638,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) **/ static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd) { + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + ENTER; - pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); + if (ioa_cfg->cfg_locked) + pci_cfg_access_unlock(ioa_cfg->pdev); + ioa_cfg->cfg_locked = 0; ipr_cmd->job_step = ipr_reset_restore_cfg_space; LEAVE; return IPR_RC_JOB_CONTINUE; @@ -7660,8 +7664,6 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) int rc = PCIBIOS_SUCCESSFUL; ENTER; - pci_block_user_cfg_access(ioa_cfg->pdev); - if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO) writel(IPR_UPROCI_SIS64_START_BIST, ioa_cfg->regs.set_uproc_interrupt_reg32); @@ -7673,7 +7675,9 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); rc = IPR_RC_JOB_RETURN; } else { - pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); + if (ioa_cfg->cfg_locked) + pci_cfg_access_unlock(ipr_cmd->ioa_cfg->pdev); + ioa_cfg->cfg_locked = 0; ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); rc = IPR_RC_JOB_CONTINUE; } @@ -7716,7 +7720,6 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd) struct pci_dev *pdev = ioa_cfg->pdev; ENTER; - pci_block_user_cfg_access(pdev); pci_set_pcie_reset_state(pdev, pcie_warm_reset); ipr_cmd->job_step = ipr_reset_slot_reset_done; ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT); @@ -7724,6 +7727,56 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd) return IPR_RC_JOB_RETURN; } +/** + * ipr_reset_block_config_access_wait - Wait for permission to block config access + * @ipr_cmd: ipr command struct + * + * Description: This attempts to block config access to the IOA. + * + * Return value: + * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN + **/ +static int ipr_reset_block_config_access_wait(struct ipr_cmnd *ipr_cmd) +{ + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + int rc = IPR_RC_JOB_CONTINUE; + + if (pci_cfg_access_trylock(ioa_cfg->pdev)) { + ioa_cfg->cfg_locked = 1; + ipr_cmd->job_step = ioa_cfg->reset; + } else { + if (ipr_cmd->u.time_left) { + rc = IPR_RC_JOB_RETURN; + ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; + ipr_reset_start_timer(ipr_cmd, + IPR_CHECK_FOR_RESET_TIMEOUT); + } else { + ipr_cmd->job_step = ioa_cfg->reset; + dev_err(&ioa_cfg->pdev->dev, + "Timed out waiting to lock config access. Resetting anyway.\n"); + } + } + + return rc; +} + +/** + * ipr_reset_block_config_access - Block config access to the IOA + * @ipr_cmd: ipr command struct + * + * Description: This attempts to block config access to the IOA + * + * Return value: + * IPR_RC_JOB_CONTINUE + **/ +static int ipr_reset_block_config_access(struct ipr_cmnd *ipr_cmd) +{ + ipr_cmd->ioa_cfg->cfg_locked = 0; + ipr_cmd->job_step = ipr_reset_block_config_access_wait; + ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT; + return IPR_RC_JOB_CONTINUE; +} + /** * ipr_reset_allowed - Query whether or not IOA can be reset * @ioa_cfg: ioa config struct @@ -7763,7 +7816,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd) ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT); } else { - ipr_cmd->job_step = ioa_cfg->reset; + ipr_cmd->job_step = ipr_reset_block_config_access; rc = IPR_RC_JOB_CONTINUE; } @@ -7796,7 +7849,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd) writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg32); ipr_cmd->job_step = ipr_reset_wait_to_start_bist; } else { - ipr_cmd->job_step = ioa_cfg->reset; + ipr_cmd->job_step = ipr_reset_block_config_access; } ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT; diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index ac84736c1b9c..b13f9cc12279 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1387,6 +1387,7 @@ struct ipr_ioa_cfg { u8 msi_received:1; u8 sis64:1; u8 dump_timeout:1; + u8 cfg_locked:1; u8 revid; -- cgit From 7dd72f5189b257f927cc3b35d98643a5c392f5c3 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 8 Jan 2012 22:44:19 +0100 Subject: drivers/scsi/aacraid/commctrl.c: fix mem leak in aac_send_raw_srb() We leak in drivers/scsi/aacraid/commctrl.c::aac_send_raw_srb() : We allocate memory: ... struct user_sgmap* usg; usg = kmalloc(actual_fibsize - sizeof(struct aac_srb) + sizeof(struct sgmap), GFP_KERNEL); and then neglect to free it: ... for (i = 0; i < usg->count; i++) { u64 addr; void* p; if (usg->sg[i].count > ((dev->adapter_info.options & AAC_OPT_NEW_COMM) ? (dev->scsi_host_ptr->max_sectors << 9) : 65536)) { rcode = -EINVAL; goto cleanup; ... this 'goto' makes 'usg' go out of scope and leak the memory we allocated. Other exits properly kfree(usg), it's just here it is neglected. Signed-off-by: Jesper Juhl Cc: James Bottomley Cc: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/aacraid/commctrl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 8a0b33033177..0bd38da4ada0 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -650,6 +650,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) AAC_OPT_NEW_COMM) ? (dev->scsi_host_ptr->max_sectors << 9) : 65536)) { + kfree(usg); rcode = -EINVAL; goto cleanup; } -- cgit From ae0751ffc77e7f21629970fdab5528c573e637f8 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 5 Dec 2011 09:20:24 +0800 Subject: [SCSI] add flag to skip the runtime PM calls on the host With previous change, now the ata port runtime suspend will happen as: disk suspend --> scsi target suspend --> scsi host suspend --> ata port suspend ata port(parent device) suspend need to schedule scsi EH which will resume scsi host(child device). Then the child device resume will in turn make parent device resume first. This is kind of recursive. This patch adds a new flag Scsi_Host::eh_noresume. ata port will set this flag to skip the runtime PM calls on scsi host. Acked-by: Alan Stern Signed-off-by: Lin Ming Signed-off-by: Jeff Garzik --- drivers/scsi/scsi_error.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index dc6131e6a1ba..5f84a148eb14 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1812,7 +1812,7 @@ int scsi_error_handler(void *data) * what we need to do to get it up and online again (if we can). * If we fail, we end up taking the thing offline. */ - if (scsi_autopm_get_host(shost) != 0) { + if (!shost->eh_noresume && scsi_autopm_get_host(shost) != 0) { SCSI_LOG_ERROR_RECOVERY(1, printk(KERN_ERR "Error handler scsi_eh_%d " "unable to autoresume\n", @@ -1833,7 +1833,8 @@ int scsi_error_handler(void *data) * which are still online. */ scsi_restart_operations(shost); - scsi_autopm_put_host(shost); + if (!shost->eh_noresume) + scsi_autopm_put_host(shost); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); -- cgit From 286405167e815adc4ae0132214246a350b0208bc Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 5 Dec 2011 09:20:25 +0800 Subject: [SCSI] check runtime PM status in system PM The only high-level SCSI driver that currently implements runtime PM is sd, and sd treats runtime suspend exactly the same as the SUSPEND and HIBERNATE stages of system sleep, but not the same as the FREEZE stage. Therefore, when entering the SUSPEND or HIBERNATE stages of system sleep, we can skip the callback to the driver if the device is already in runtime suspend. When entering the FREEZE stage, however, we should first issue a runtime resume. The overhead of doing this is negligible, because a suspended drive would be spun up during the THAW stage of hibernation anyway. Signed-off-by: Lin Ming Signed-off-by: Alan Stern Signed-off-by: Jeff Garzik --- drivers/scsi/scsi_pm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index d329f8b12e2b..a633076e5622 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -49,8 +49,22 @@ static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg) { int err = 0; - if (scsi_is_sdev_device(dev)) + if (scsi_is_sdev_device(dev)) { + /* + * sd is the only high-level SCSI driver to implement runtime + * PM, and sd treats runtime suspend, system suspend, and + * system hibernate identically (but not system freeze). + */ + if (pm_runtime_suspended(dev)) { + if (msg.event == PM_EVENT_SUSPEND || + msg.event == PM_EVENT_HIBERNATE) + return 0; /* already suspended */ + + /* wake up device so that FREEZE will succeed */ + pm_runtime_resume(dev); + } err = scsi_dev_type_suspend(dev, msg); + } return err; } -- cgit From 54f57588463db1105f4a93b2902a6f95cb8f796a Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Mon, 5 Dec 2011 09:20:26 +0800 Subject: [SCSI] sd: check runtime PM status in sd_shutdown sd_shutdown is called during reboot/poweroff. It may fail if parent device, for example, ata port, was runtime suspended. Fix it by checking runtime PM status of sd. Exit immediately if sd was runtime suspended already. Acked-by: Alan Stern Signed-off-by: Lin Ming Signed-off-by: Jeff Garzik --- drivers/scsi/sd.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index fa3a5918009c..7b3f8075e2a5 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -2741,6 +2742,9 @@ static void sd_shutdown(struct device *dev) if (!sdkp) return; /* this can happen */ + if (pm_runtime_suspended(dev)) + goto exit; + if (sdkp->WCE) { sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); sd_sync_cache(sdkp); @@ -2751,6 +2755,7 @@ static void sd_shutdown(struct device *dev) sd_start_stop_device(sdkp, 0); } +exit: scsi_disk_put(sdkp); } -- cgit From 28fd00d42cca178638f51c08efa986a777c24a4b Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 22 Dec 2011 14:50:47 +0800 Subject: [SCSI] runtime resume parent for child's system-resume [Patch description from Alan Stern] If a child device was runtime-suspended when a system suspend began, then there will be nothing to prevent its parent from runtime-suspending as soon as it is woken up during the system resume. Then when the time comes to resume the child, the resume will fail because the parent is already back at low power. On the other hand, there are some devices which should remain at low power across an entire suspend-resume cycle. The details depend on the device and the platform. This suggests that the PM core is not the right place to solve the problem. One possible solution is for the subsystem or device driver to call pm_runtime_get_sync(dev->parent) at the start of the system-resume procedure and pm_runtime_put_sync(dev->parent) at the end. Acked-by: Alan Stern Signed-off-by: Lin Ming Signed-off-by: Jeff Garzik --- drivers/scsi/scsi_pm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index a633076e5622..bf8bf79e6a1f 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c @@ -72,8 +72,17 @@ static int scsi_bus_resume_common(struct device *dev) { int err = 0; - if (scsi_is_sdev_device(dev)) + if (scsi_is_sdev_device(dev)) { + /* + * Parent device may have runtime suspended as soon as + * it is woken up during the system resume. + * + * Resume it on behalf of child. + */ + pm_runtime_get_sync(dev->parent); err = scsi_dev_type_resume(dev); + pm_runtime_put_sync(dev->parent); + } if (err == 0) { pm_runtime_disable(dev); -- cgit From 9fc397fc0878c9540af20cbffc4d546541fe8b23 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 18 Nov 2011 01:44:27 +0100 Subject: [SCSI] scsi_dh_rdac: Fix error path If create_singlethread_workqueue() failes, rdac_init should fail too. Signed-off-by: Richard Weinberger Acked-by: "Moger, Babu" Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_rdac.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 841ebf4a6788..53a31c753cb1 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -953,6 +953,8 @@ static int __init rdac_init(void) if (!kmpath_rdacd) { scsi_unregister_device_handler(&rdac_dh); printk(KERN_ERR "kmpath_rdacd creation failed.\n"); + + r = -EINVAL; } done: return r; -- cgit From cced5041ed5a2d1352186510944b0ddfbdbe4c0b Mon Sep 17 00:00:00 2001 From: Stratos Psomadakis Date: Sun, 4 Dec 2011 02:23:54 +0200 Subject: [SCSI] sym53c8xx: Fix NULL pointer dereference in slave_destroy sym53c8xx_slave_destroy unconditionally assumes that sym53c8xx_slave_alloc has succesesfully allocated a sym_lcb. This can lead to a NULL pointer dereference (exposed by commit 4e6c82b). Signed-off-by: Stratos Psomadakis Cc: stable@vger.kernel.org Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_glue.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index b4543f575f46..36d1ed7817eb 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev) struct sym_lcb *lp = sym_lp(tp, sdev->lun); unsigned long flags; + /* if slave_alloc returned before allocating a sym_lcb, return */ + if (!lp) + return; + spin_lock_irqsave(np->s.host->host_lock, flags); if (lp->busy_itlq || lp->busy_itl) { -- cgit From 00c4a09bb0840457f5f8f5753a562e5e19a91baf Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Wed, 14 Dec 2011 13:46:23 -0200 Subject: [SCSI] libcxgbi: do not print a message when memory allocation fails In alloc_pdu, libcxgbi tries to allocate a skb with GFP_ATOMIC, which may potentially fail. When it happens, the current code prints a warning message. When the system is under IO stress, this failure may happen lots of times and it usually scares users. Instead of printing the warning message, the code now increases the tx_dropped statistics for the ethernet interface wich is doing the iscsi task. Signed-off-by: Thadeu Lima de Souza Cascardo Acked-by: Karen Xie Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/cxgbi/libcxgbi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index c5360ffb4bed..d3ff9cd40234 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -1868,8 +1868,9 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC); if (!tdata->skb) { - pr_warn("alloc skb %u+%u, opcode 0x%x failed.\n", - cdev->skb_tx_rsvd, headroom, opcode); + struct cxgbi_sock *csk = cconn->cep->csk; + struct net_device *ndev = cdev->ports[csk->port_id]; + ndev->stats.tx_dropped++; return -ENOMEM; } -- cgit From 4a4bc2e90c1c689bf929914256310361d4012df1 Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Fri, 16 Dec 2011 01:58:55 -0800 Subject: [SCSI] qla4xxx: cleanup, make qla4xxx_build_ddb_list short Make qla4xxx_build_ddb_list shorter by adding more helper functions. Signed-off-by: Lalit Chandivade Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 399 +++++++++++++++++++++++++----------------- 1 file changed, 237 insertions(+), 162 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ec393a00c038..87e3699d7ea2 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2078,7 +2078,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) } } -void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) +static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) { struct iscsi_session *sess; struct ddb_entry *ddb_entry; @@ -3826,16 +3826,14 @@ exit_check: return ret; } -static void qla4xxx_free_nt_list(struct list_head *list_nt) +static void qla4xxx_free_ddb_list(struct list_head *list_ddb) { - struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp; + struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; - /* Free up the normaltargets list */ - list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { - list_del_init(&nt_ddb_idx->list); - vfree(nt_ddb_idx); + list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) { + list_del_init(&ddb_idx->list); + vfree(ddb_idx); } - } static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha, @@ -3934,7 +3932,6 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha) ip_state == IP_ADDRSTATE_DEPRICATED || ip_state == IP_ADDRSTATE_DISABLING) ip_idx[idx] = -1; - } /* Break if all IP states checked */ @@ -3947,52 +3944,34 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha) } while (time_after(wtime, jiffies)); } -void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) +static void qla4xxx_build_st_list(struct scsi_qla_host *ha, + struct list_head *list_st) { + struct qla_ddb_index *st_ddb_idx; int max_ddbs; + int fw_idx_size; + struct dev_db_entry *fw_ddb_entry; + dma_addr_t fw_ddb_dma; int ret; uint32_t idx = 0, next_idx = 0; uint32_t state = 0, conn_err = 0; - uint16_t conn_id; - struct dev_db_entry *fw_ddb_entry; - struct ddb_entry *ddb_entry = NULL; - dma_addr_t fw_ddb_dma; - struct iscsi_cls_session *cls_sess; - struct iscsi_session *sess; - struct iscsi_cls_conn *cls_conn; - struct iscsi_endpoint *ep; - uint16_t cmds_max = 32, tmo = 0; - uint32_t initial_cmdsn = 0; - struct list_head list_st, list_nt; /* List of sendtargets */ - struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp; - int fw_idx_size; - unsigned long wtime; - struct qla_ddb_index *nt_ddb_idx; - - if (!test_bit(AF_LINK_UP, &ha->flags)) { - set_bit(AF_BUILD_DDB_LIST, &ha->flags); - ha->is_reset = is_reset; - return; - } - max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : - MAX_DEV_DB_ENTRIES; + uint16_t conn_id = 0; fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, &fw_ddb_dma); if (fw_ddb_entry == NULL) { DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); - goto exit_ddb_list; + goto exit_st_list; } - INIT_LIST_HEAD(&list_st); - INIT_LIST_HEAD(&list_nt); + max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : + MAX_DEV_DB_ENTRIES; fw_idx_size = sizeof(struct qla_ddb_index); for (idx = 0; idx < max_ddbs; idx = next_idx) { - ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, - fw_ddb_dma, NULL, - &next_idx, &state, &conn_err, - NULL, &conn_id); + ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma, + NULL, &next_idx, &state, + &conn_err, NULL, &conn_id); if (ret == QLA_ERROR) break; @@ -4009,59 +3988,155 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) st_ddb_idx->fw_ddb_idx = idx; - list_add_tail(&st_ddb_idx->list, &list_st); + list_add_tail(&st_ddb_idx->list, list_st); continue_next_st: if (next_idx == 0) break; } - /* Before issuing conn open mbox, ensure all IPs states are configured - * Note, conn open fails if IPs are not configured +exit_st_list: + if (fw_ddb_entry) + dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); +} + +/** + * qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list + * @ha: pointer to adapter structure + * @list_ddb: List from which failed ddb to be removed + * + * Iterate over the list of DDBs and find and remove DDBs that are either in + * no connection active state or failed state + **/ +static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha, + struct list_head *list_ddb) +{ + struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; + uint32_t next_idx = 0; + uint32_t state = 0, conn_err = 0; + int ret; + + list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) { + ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx, + NULL, 0, NULL, &next_idx, &state, + &conn_err, NULL, NULL); + if (ret == QLA_ERROR) + continue; + + if (state == DDB_DS_NO_CONNECTION_ACTIVE || + state == DDB_DS_SESSION_FAILED) { + list_del_init(&ddb_idx->list); + vfree(ddb_idx); + } + } +} + +static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, + struct dev_db_entry *fw_ddb_entry, + int is_reset) +{ + struct iscsi_cls_session *cls_sess; + struct iscsi_session *sess; + struct iscsi_cls_conn *cls_conn; + struct iscsi_endpoint *ep; + uint16_t cmds_max = 32; + uint16_t conn_id = 0; + uint32_t initial_cmdsn = 0; + int ret = QLA_SUCCESS; + + struct ddb_entry *ddb_entry = NULL; + + /* Create session object, with INVALID_ENTRY, + * the targer_id would get set when we issue the login */ - qla4xxx_wait_for_ip_configuration(ha); + cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host, + cmds_max, sizeof(struct ddb_entry), + sizeof(struct ql4_task_data), + initial_cmdsn, INVALID_ENTRY); + if (!cls_sess) { + ret = QLA_ERROR; + goto exit_setup; + } - /* Go thru the STs and fire the sendtargets by issuing conn open mbx */ - list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) { - qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx); + /* + * so calling module_put function to decrement the + * reference count. + **/ + module_put(qla4xxx_iscsi_transport.owner); + sess = cls_sess->dd_data; + ddb_entry = sess->dd_data; + ddb_entry->sess = cls_sess; + + cls_sess->recovery_tmo = ql4xsess_recovery_tmo; + memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry, + sizeof(struct dev_db_entry)); + + qla4xxx_setup_flash_ddb_entry(ha, ddb_entry); + + cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id); + + if (!cls_conn) { + ret = QLA_ERROR; + goto exit_setup; } - /* Wait to ensure all sendtargets are done for min 12 sec wait */ - tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout); - DEBUG2(ql4_printk(KERN_INFO, ha, - "Default time to wait for build ddb %d\n", tmo)); + ddb_entry->conn = cls_conn; - wtime = jiffies + (HZ * tmo); - do { - list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, - list) { - ret = qla4xxx_get_fwddb_entry(ha, - st_ddb_idx->fw_ddb_idx, - NULL, 0, NULL, &next_idx, - &state, &conn_err, NULL, - NULL); - if (ret == QLA_ERROR) - continue; + /* Setup ep, for displaying attributes in sysfs */ + ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry); + if (ep) { + ep->conn = cls_conn; + cls_conn->ep = ep; + } else { + DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n")); + ret = QLA_ERROR; + goto exit_setup; + } - if (state == DDB_DS_NO_CONNECTION_ACTIVE || - state == DDB_DS_SESSION_FAILED) { - list_del_init(&st_ddb_idx->list); - vfree(st_ddb_idx); - } - } - schedule_timeout_uninterruptible(HZ / 10); - } while (time_after(wtime, jiffies)); + /* Update sess/conn params */ + qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); - /* Free up the sendtargets list */ - list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) { - list_del_init(&st_ddb_idx->list); - vfree(st_ddb_idx); + if (is_reset == RESET_ADAPTER) { + iscsi_block_session(cls_sess); + /* Use the relogin path to discover new devices + * by short-circuting the logic of setting + * timer to relogin - instead set the flags + * to initiate login right away. + */ + set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); + set_bit(DF_RELOGIN, &ddb_entry->flags); } +exit_setup: + return ret; +} + +static void qla4xxx_build_nt_list(struct scsi_qla_host *ha, + struct list_head *list_nt, int is_reset) +{ + struct dev_db_entry *fw_ddb_entry; + dma_addr_t fw_ddb_dma; + int max_ddbs; + int fw_idx_size; + int ret; + uint32_t idx = 0, next_idx = 0; + uint32_t state = 0, conn_err = 0; + uint16_t conn_id = 0; + struct qla_ddb_index *nt_ddb_idx; + + fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, + &fw_ddb_dma); + if (fw_ddb_entry == NULL) { + DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); + goto exit_nt_list; + } + max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : + MAX_DEV_DB_ENTRIES; + fw_idx_size = sizeof(struct qla_ddb_index); + for (idx = 0; idx < max_ddbs; idx = next_idx) { - ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, - fw_ddb_dma, NULL, - &next_idx, &state, &conn_err, - NULL, &conn_id); + ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma, + NULL, &next_idx, &state, + &conn_err, NULL, &conn_id); if (ret == QLA_ERROR) break; @@ -4072,107 +4147,107 @@ continue_next_st: if (strlen((char *) fw_ddb_entry->iscsi_name) == 0) goto continue_next_nt; - if (state == DDB_DS_NO_CONNECTION_ACTIVE || - state == DDB_DS_SESSION_FAILED) { - DEBUG2(ql4_printk(KERN_INFO, ha, - "Adding DDB to session = 0x%x\n", - idx)); - if (is_reset == INIT_ADAPTER) { - nt_ddb_idx = vmalloc(fw_idx_size); - if (!nt_ddb_idx) - break; - - nt_ddb_idx->fw_ddb_idx = idx; - - memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry, - sizeof(struct dev_db_entry)); - - if (qla4xxx_is_flash_ddb_exists(ha, &list_nt, - fw_ddb_entry) == QLA_SUCCESS) { - vfree(nt_ddb_idx); - goto continue_next_nt; - } - list_add_tail(&nt_ddb_idx->list, &list_nt); - } else if (is_reset == RESET_ADAPTER) { - if (qla4xxx_is_session_exists(ha, - fw_ddb_entry) == QLA_SUCCESS) - goto continue_next_nt; - } + if (!(state == DDB_DS_NO_CONNECTION_ACTIVE || + state == DDB_DS_SESSION_FAILED)) + goto continue_next_nt; - /* Create session object, with INVALID_ENTRY, - * the targer_id would get set when we issue the login - */ - cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, - ha->host, cmds_max, - sizeof(struct ddb_entry), - sizeof(struct ql4_task_data), - initial_cmdsn, INVALID_ENTRY); - if (!cls_sess) - goto exit_ddb_list; + DEBUG2(ql4_printk(KERN_INFO, ha, + "Adding DDB to session = 0x%x\n", idx)); + if (is_reset == INIT_ADAPTER) { + nt_ddb_idx = vmalloc(fw_idx_size); + if (!nt_ddb_idx) + break; - /* - * iscsi_session_setup increments the driver reference - * count which wouldn't let the driver to be unloaded. - * so calling module_put function to decrement the - * reference count. - **/ - module_put(qla4xxx_iscsi_transport.owner); - sess = cls_sess->dd_data; - ddb_entry = sess->dd_data; - ddb_entry->sess = cls_sess; + nt_ddb_idx->fw_ddb_idx = idx; - cls_sess->recovery_tmo = ql4xsess_recovery_tmo; - memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry, + memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry, sizeof(struct dev_db_entry)); - qla4xxx_setup_flash_ddb_entry(ha, ddb_entry); - - cls_conn = iscsi_conn_setup(cls_sess, - sizeof(struct qla_conn), - conn_id); - if (!cls_conn) - goto exit_ddb_list; - - ddb_entry->conn = cls_conn; - - /* Setup ep, for displaying attributes in sysfs */ - ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry); - if (ep) { - ep->conn = cls_conn; - cls_conn->ep = ep; - } else { - DEBUG2(ql4_printk(KERN_ERR, ha, - "Unable to get ep\n")); - } - - /* Update sess/conn params */ - qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, - cls_conn); - - if (is_reset == RESET_ADAPTER) { - iscsi_block_session(cls_sess); - /* Use the relogin path to discover new devices - * by short-circuting the logic of setting - * timer to relogin - instead set the flags - * to initiate login right away. - */ - set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); - set_bit(DF_RELOGIN, &ddb_entry->flags); + if (qla4xxx_is_flash_ddb_exists(ha, list_nt, + fw_ddb_entry) == QLA_SUCCESS) { + vfree(nt_ddb_idx); + goto continue_next_nt; } + list_add_tail(&nt_ddb_idx->list, list_nt); + } else if (is_reset == RESET_ADAPTER) { + if (qla4xxx_is_session_exists(ha, fw_ddb_entry) == + QLA_SUCCESS) + goto continue_next_nt; } + + ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset); + if (ret == QLA_ERROR) + goto exit_nt_list; + continue_next_nt: if (next_idx == 0) break; } -exit_ddb_list: - qla4xxx_free_nt_list(&list_nt); + +exit_nt_list: if (fw_ddb_entry) dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); +} + +/** + * qla4xxx_build_ddb_list - Build ddb list and setup sessions + * @ha: pointer to adapter structure + * @is_reset: Is this init path or reset path + * + * Create a list of sendtargets (st) from firmware DDBs, issue send targets + * using connection open, then create the list of normal targets (nt) + * from firmware DDBs. Based on the list of nt setup session and connection + * objects. + **/ +void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) +{ + uint16_t tmo = 0; + struct list_head list_st, list_nt; + struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp; + unsigned long wtime; + + if (!test_bit(AF_LINK_UP, &ha->flags)) { + set_bit(AF_BUILD_DDB_LIST, &ha->flags); + ha->is_reset = is_reset; + return; + } + + INIT_LIST_HEAD(&list_st); + INIT_LIST_HEAD(&list_nt); + + qla4xxx_build_st_list(ha, &list_st); + + /* Before issuing conn open mbox, ensure all IPs states are configured + * Note, conn open fails if IPs are not configured + */ + qla4xxx_wait_for_ip_configuration(ha); + + /* Go thru the STs and fire the sendtargets by issuing conn open mbx */ + list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) { + qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx); + } + + /* Wait to ensure all sendtargets are done for min 12 sec wait */ + tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout); + DEBUG2(ql4_printk(KERN_INFO, ha, + "Default time to wait for build ddb %d\n", tmo)); + + wtime = jiffies + (HZ * tmo); + do { + qla4xxx_remove_failed_ddb(ha, &list_st); + schedule_timeout_uninterruptible(HZ / 10); + } while (time_after(wtime, jiffies)); + + /* Free up the sendtargets list */ + qla4xxx_free_ddb_list(&list_st); + + qla4xxx_build_nt_list(ha, &list_nt, is_reset); + + qla4xxx_free_ddb_list(&list_nt); qla4xxx_free_ddb_index(ha); } - /** * qla4xxx_probe_adapter - callback function to probe HBA * @pdev: pointer to pci_dev structure -- cgit From c28eaaca7acea214937fb9b3ae45e001d49947bf Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Sun, 18 Dec 2011 21:40:44 -0800 Subject: [SCSI] qla4xxx: Limit the ACB Default Timeout value to 12s A wrong default timeout value programmed in the adapter causes driver to wait for that much time while waiting for target discoveries to complete. This could add huge delays during the driver load time. To avoid this, limit the default timeout value to 12 seconds if the default timeout value set in adapter is less than 12 seconds and greater than 120 seconds. Signed-off-by: Nilesh Javali Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 87e3699d7ea2..09b28f8513a0 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1630,7 +1630,9 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, /* Update timers after login */ ddb_entry->default_relogin_timeout = - le16_to_cpu(fw_ddb_entry->def_timeout); + (le16_to_cpu(fw_ddb_entry->def_timeout) > LOGIN_TOV) && + (le16_to_cpu(fw_ddb_entry->def_timeout) < LOGIN_TOV * 10) ? + le16_to_cpu(fw_ddb_entry->def_timeout) : LOGIN_TOV; ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); @@ -3882,6 +3884,8 @@ static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx) static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry) { + uint16_t def_timeout; + ddb_entry->ddb_type = FLASH_DDB; ddb_entry->fw_ddb_index = INVALID_ENTRY; ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE; @@ -3892,9 +3896,10 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha, atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); atomic_set(&ddb_entry->relogin_timer, 0); atomic_set(&ddb_entry->relogin_retry_count, 0); - + def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout); ddb_entry->default_relogin_timeout = - le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout); + (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ? + def_timeout : LOGIN_TOV; ddb_entry->default_time2wait = le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait); } @@ -4228,7 +4233,10 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) } /* Wait to ensure all sendtargets are done for min 12 sec wait */ - tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout); + tmo = ((ha->def_timeout > LOGIN_TOV) && + (ha->def_timeout < LOGIN_TOV * 10) ? + ha->def_timeout : LOGIN_TOV); + DEBUG2(ql4_printk(KERN_INFO, ha, "Default time to wait for build ddb %d\n", tmo)); -- cgit From f1f2e60e1a2320d0ce11102b72b15d5dedb29fe2 Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Fri, 16 Dec 2011 01:58:57 -0800 Subject: [SCSI] qla4xxx: Break the loop if the sendtargets list was empty Signed-off-by: Nilesh Javali Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 09b28f8513a0..ae5d512bf43b 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -4242,6 +4242,9 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) wtime = jiffies + (HZ * tmo); do { + if (list_empty(&list_st)) + break; + qla4xxx_remove_failed_ddb(ha, &list_st); schedule_timeout_uninterruptible(HZ / 10); } while (time_after(wtime, jiffies)); -- cgit From 368d45cc61c062a1291d0b29257a0697d6aeabd9 Mon Sep 17 00:00:00 2001 From: Manish Rangankar Date: Fri, 16 Dec 2011 01:58:58 -0800 Subject: [SCSI] qla4xxx: Fixed BFS with sendtargets as boot index. If ql4xdisablesysfsboot = 0 and sendtargets entry as boot index then driver does export sendtarget entries in sysfs but iscsistart does not do discovery. So in this case let driver do the discovery and login to the targets. Signed-off-by: Manish Rangankar Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ae5d512bf43b..0048a3facd7a 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -3980,9 +3980,6 @@ static void qla4xxx_build_st_list(struct scsi_qla_host *ha, if (ret == QLA_ERROR) break; - if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS) - goto continue_next_st; - /* Check if ST, add to the list_st */ if (strlen((char *) fw_ddb_entry->iscsi_name) != 0) goto continue_next_st; -- cgit From 3a19cbf530648a63fb3f73630046c561f70c6b71 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Fri, 16 Dec 2011 01:58:59 -0800 Subject: [SCSI] qla4xxx: Update driver version to 5.02.00-k11 Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 26a3fa34a33c..7d04eb05c45e 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k10" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k11" -- cgit From f1633011e4fcb65bf65aebeaf4024efdc4c49d6e Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 16 Dec 2011 14:24:49 -0800 Subject: [SCSI] fcoe: remove double check if skb is nonlinear skb_linearize already has a check for skb_is_nonlinear, there is no need to duplicate the check in fcoe.c. This patch simply removes the unnecessary check and calls skb_linearize unconditionally. Reported-by: patrick kelle Signed-off-by: Robert Love Acked-by: patrick kelle Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 8d67467dd9ce..e535f95e4772 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1671,8 +1671,7 @@ static void fcoe_recv_frame(struct sk_buff *skb) skb->dev ? skb->dev->name : ""); port = lport_priv(lport); - if (skb_is_nonlinear(skb)) - skb_linearize(skb); /* not ideal */ + skb_linearize(skb); /* check for skb_is_nonlinear is within skb_linearize */ /* * Frame length checks and setting up the header pointers -- cgit From 6bc6204e3b7f4ac235e98e362714213369d6a012 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Tue, 20 Dec 2011 18:54:30 -0800 Subject: [SCSI] bfa: Fix possible NULL pointer dereference in lunmask add/delete. Patch fixes the possible NULL pointer dereference when we try to add or delete a rpwwn to the lunmask config which is not zoned to this port. Check if the FCS rport is not NULL before de-referencing it. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcpim.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index e07bd4745d8b..846f15b6e1d8 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -2647,7 +2647,8 @@ bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn, if (port) { *pwwn = port->port_cfg.pwwn; rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn); - rp = rp_fcs->bfa_rport; + if (rp_fcs) + rp = rp_fcs->bfa_rport; } lunm_list = bfa_get_lun_mask_list(bfa); @@ -2715,7 +2716,8 @@ bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn, if (port) { *pwwn = port->port_cfg.pwwn; rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn); - rp = rp_fcs->bfa_rport; + if (rp_fcs) + rp = rp_fcs->bfa_rport; } } -- cgit From 8ca2dd87e7f29df99389e9dc41f7a45a35223672 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Tue, 20 Dec 2011 18:55:07 -0800 Subject: [SCSI] bfa: Revert back the current LUN Masking Implementation. This patch reverts the current LUN Masking Implementation. We re-implemented this feature using the SCSI Slave Callout's as per the review comments. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_defs_svc.h | 7 +- drivers/scsi/bfa/bfa_fc.h | 155 --------------- drivers/scsi/bfa/bfa_fcpim.c | 410 +--------------------------------------- drivers/scsi/bfa/bfa_fcpim.h | 7 - drivers/scsi/bfa/bfa_svc.h | 5 - 5 files changed, 2 insertions(+), 582 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index 78963be2c4fb..cb07c628b2f1 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -673,12 +673,7 @@ struct bfa_itnim_iostats_s { u32 tm_iocdowns; /* TM cleaned-up due to IOC down */ u32 tm_cleanups; /* TM cleanup requests */ u32 tm_cleanup_comps; /* TM cleanup completions */ - u32 lm_lun_across_sg; /* LM lun is across sg data buf */ - u32 lm_lun_not_sup; /* LM lun not supported */ - u32 lm_rpl_data_changed; /* LM report-lun data changed */ - u32 lm_wire_residue_changed; /* LM report-lun rsp residue changed */ - u32 lm_small_buf_addresidue; /* LM buf smaller than reported cnt */ - u32 lm_lun_not_rdy; /* LM lun not ready */ + u32 rsvd[6]; }; /* Modify char* port_stt[] in bfal_port.c if a new state was added */ diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index 50b6a1c86195..8d0b88f67a38 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h @@ -56,161 +56,6 @@ struct scsi_cdb_s { #define SCSI_MAX_ALLOC_LEN 0xFF /* maximum allocarion length */ -#define SCSI_SENSE_CUR_ERR 0x70 -#define SCSI_SENSE_DEF_ERR 0x71 - -/* - * SCSI additional sense codes - */ -#define SCSI_ASC_LUN_NOT_READY 0x04 -#define SCSI_ASC_LUN_NOT_SUPPORTED 0x25 -#define SCSI_ASC_TOCC 0x3F - -/* - * SCSI additional sense code qualifiers - */ -#define SCSI_ASCQ_MAN_INTR_REQ 0x03 /* manual intervention req */ -#define SCSI_ASCQ_RL_DATA_CHANGED 0x0E /* report luns data changed */ - -/* - * Methods of reporting informational exceptions - */ -#define SCSI_MP_IEC_UNIT_ATTN 0x2 /* generate unit attention */ - -struct scsi_report_luns_data_s { - u32 lun_list_length; /* length of LUN list length */ - u32 reserved; - struct scsi_lun lun[1]; /* first LUN in lun list */ -}; - -struct scsi_inquiry_vendor_s { - u8 vendor_id[8]; -}; - -struct scsi_inquiry_prodid_s { - u8 product_id[16]; -}; - -struct scsi_inquiry_prodrev_s { - u8 product_rev[4]; -}; - -struct scsi_inquiry_data_s { -#ifdef __BIG_ENDIAN - u8 peripheral_qual:3; /* peripheral qualifier */ - u8 device_type:5; /* peripheral device type */ - u8 rmb:1; /* removable medium bit */ - u8 device_type_mod:7; /* device type modifier */ - u8 version; - u8 aenc:1; /* async evt notification capability */ - u8 trm_iop:1; /* terminate I/O process */ - u8 norm_aca:1; /* normal ACA supported */ - u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */ - u8 rsp_data_format:4; - u8 additional_len; - u8 sccs:1; - u8 reserved1:7; - u8 reserved2:1; - u8 enc_serv:1; /* enclosure service component */ - u8 reserved3:1; - u8 multi_port:1; /* multi-port device */ - u8 m_chngr:1; /* device in medium transport element */ - u8 ack_req_q:1; /* SIP specific bit */ - u8 addr32:1; /* SIP specific bit */ - u8 addr16:1; /* SIP specific bit */ - u8 rel_adr:1; /* relative address */ - u8 w_bus32:1; - u8 w_bus16:1; - u8 synchronous:1; - u8 linked_commands:1; - u8 trans_dis:1; - u8 cmd_queue:1; /* command queueing supported */ - u8 soft_reset:1; /* soft reset alternative (VS) */ -#else - u8 device_type:5; /* peripheral device type */ - u8 peripheral_qual:3; /* peripheral qualifier */ - u8 device_type_mod:7; /* device type modifier */ - u8 rmb:1; /* removable medium bit */ - u8 version; - u8 rsp_data_format:4; - u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */ - u8 norm_aca:1; /* normal ACA supported */ - u8 terminate_iop:1;/* terminate I/O process */ - u8 aenc:1; /* async evt notification capability */ - u8 additional_len; - u8 reserved1:7; - u8 sccs:1; - u8 addr16:1; /* SIP specific bit */ - u8 addr32:1; /* SIP specific bit */ - u8 ack_req_q:1; /* SIP specific bit */ - u8 m_chngr:1; /* device in medium transport element */ - u8 multi_port:1; /* multi-port device */ - u8 reserved3:1; /* TBD - Vendor Specific */ - u8 enc_serv:1; /* enclosure service component */ - u8 reserved2:1; - u8 soft_seset:1; /* soft reset alternative (VS) */ - u8 cmd_queue:1; /* command queueing supported */ - u8 trans_dis:1; - u8 linked_commands:1; - u8 synchronous:1; - u8 w_bus16:1; - u8 w_bus32:1; - u8 rel_adr:1; /* relative address */ -#endif - struct scsi_inquiry_vendor_s vendor_id; - struct scsi_inquiry_prodid_s product_id; - struct scsi_inquiry_prodrev_s product_rev; - u8 vendor_specific[20]; - u8 reserved4[40]; -}; - -/* - * SCSI sense data format - */ -struct scsi_sense_s { -#ifdef __BIG_ENDIAN - u8 valid:1; - u8 rsp_code:7; -#else - u8 rsp_code:7; - u8 valid:1; -#endif - u8 seg_num; -#ifdef __BIG_ENDIAN - u8 file_mark:1; - u8 eom:1; /* end of media */ - u8 ili:1; /* incorrect length indicator */ - u8 reserved:1; - u8 sense_key:4; -#else - u8 sense_key:4; - u8 reserved:1; - u8 ili:1; /* incorrect length indicator */ - u8 eom:1; /* end of media */ - u8 file_mark:1; -#endif - u8 information[4]; /* device-type or cmd specific info */ - u8 add_sense_length; /* additional sense length */ - u8 command_info[4];/* command specific information */ - u8 asc; /* additional sense code */ - u8 ascq; /* additional sense code qualifier */ - u8 fru_code; /* field replaceable unit code */ -#ifdef __BIG_ENDIAN - u8 sksv:1; /* sense key specific valid */ - u8 c_d:1; /* command/data bit */ - u8 res1:2; - u8 bpv:1; /* bit pointer valid */ - u8 bpointer:3; /* bit pointer */ -#else - u8 bpointer:3; /* bit pointer */ - u8 bpv:1; /* bit pointer valid */ - u8 res1:2; - u8 c_d:1; /* command/data bit */ - u8 sksv:1; /* sense key specific valid */ -#endif - u8 fpointer[2]; /* field pointer */ -}; - /* * Fibre Channel Header Structure (FCHS) definition */ diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 846f15b6e1d8..f0f80e282e39 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -24,8 +24,6 @@ BFA_TRC_FILE(HAL, FCPIM); * BFA ITNIM Related definitions */ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim); -static bfa_boolean_t bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim); -static bfa_boolean_t bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim); static void bfa_ioim_lm_init(struct bfa_s *bfa); #define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \ @@ -60,14 +58,6 @@ static void bfa_ioim_lm_init(struct bfa_s *bfa); } \ } while (0) -#define bfa_ioim_rp_wwn(__ioim) \ - (((struct bfa_fcs_rport_s *) \ - (__ioim)->itnim->rport->rport_drv)->pwwn) - -#define bfa_ioim_lp_wwn(__ioim) \ - ((BFA_LPS_FROM_TAG(BFA_LPS_MOD((__ioim)->bfa), \ - (__ioim)->itnim->rport->rport_info.lp_tag))->pwwn) \ - #define bfa_itnim_sler_cb(__itnim) do { \ if ((__itnim)->bfa->fcs) \ bfa_cb_itnim_sler((__itnim)->ditn); \ @@ -77,13 +67,6 @@ static void bfa_ioim_lm_init(struct bfa_s *bfa); } \ } while (0) -enum bfa_ioim_lm_status { - BFA_IOIM_LM_PRESENT = 1, - BFA_IOIM_LM_LUN_NOT_SUP = 2, - BFA_IOIM_LM_RPL_DATA_CHANGED = 3, - BFA_IOIM_LM_LUN_NOT_RDY = 4, -}; - enum bfa_ioim_lm_ua_status { BFA_IOIM_LM_UA_RESET = 0, BFA_IOIM_LM_UA_SET = 1, @@ -145,9 +128,6 @@ enum bfa_ioim_event { BFA_IOIM_SM_TMDONE = 16, /* IO cleanup from tskim */ BFA_IOIM_SM_HWFAIL = 17, /* IOC h/w failure event */ BFA_IOIM_SM_IOTOV = 18, /* ITN offline TOV */ - BFA_IOIM_SM_LM_LUN_NOT_SUP = 19,/* lunmask lun not supported */ - BFA_IOIM_SM_LM_RPL_DC = 20, /* lunmask report-lun data changed */ - BFA_IOIM_SM_LM_LUN_NOT_RDY = 21,/* lunmask lun not ready */ }; @@ -245,9 +225,6 @@ static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete); static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete); static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete); static bfa_boolean_t bfa_ioim_is_abortable(struct bfa_ioim_s *ioim); -static void __bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete); -static void __bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete); -static void __bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete); /* * forward declaration of BFA IO state machine @@ -445,12 +422,6 @@ bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats, bfa_fcpim_add_iostats(lstats, rstats, output_reqs); bfa_fcpim_add_iostats(lstats, rstats, rd_throughput); bfa_fcpim_add_iostats(lstats, rstats, wr_throughput); - bfa_fcpim_add_iostats(lstats, rstats, lm_lun_across_sg); - bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_sup); - bfa_fcpim_add_iostats(lstats, rstats, lm_rpl_data_changed); - bfa_fcpim_add_iostats(lstats, rstats, lm_wire_residue_changed); - bfa_fcpim_add_iostats(lstats, rstats, lm_small_buf_addresidue); - bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_rdy); } bfa_status_t @@ -1580,27 +1551,6 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) __bfa_cb_ioim_abort, ioim); break; - case BFA_IOIM_SM_LM_LUN_NOT_SUP: - bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); - bfa_ioim_move_to_comp_q(ioim); - bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, - __bfa_cb_ioim_lm_lun_not_sup, ioim); - break; - - case BFA_IOIM_SM_LM_RPL_DC: - bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); - bfa_ioim_move_to_comp_q(ioim); - bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, - __bfa_cb_ioim_lm_rpl_dc, ioim); - break; - - case BFA_IOIM_SM_LM_LUN_NOT_RDY: - bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); - bfa_ioim_move_to_comp_q(ioim); - bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, - __bfa_cb_ioim_lm_lun_not_rdy, ioim); - break; - default: bfa_sm_fault(ioim->bfa, event); } @@ -2160,243 +2110,6 @@ bfa_ioim_lm_init(struct bfa_s *bfa) } } -/* - * Validate LUN for LUN masking - */ -static enum bfa_ioim_lm_status -bfa_ioim_lm_check(struct bfa_ioim_s *ioim, struct bfa_lps_s *lps, - struct bfa_rport_s *rp, struct scsi_lun lun) -{ - u8 i; - struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa); - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio; - struct scsi_cdb_s *cdb = (struct scsi_cdb_s *)cmnd->cmnd; - - if ((cdb->scsi_cdb[0] == REPORT_LUNS) && - (scsilun_to_int((struct scsi_lun *)&lun) == 0)) { - ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data; - return BFA_IOIM_LM_PRESENT; - } - - for (i = 0; i < MAX_LUN_MASK_CFG; i++) { - - if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE) - continue; - - if ((scsilun_to_int((struct scsi_lun *)&lun_list[i].lun) == - scsilun_to_int((struct scsi_lun *)&lun)) - && (rp->rport_tag == lun_list[i].rp_tag) - && ((u8)ioim->itnim->rport->rport_info.lp_tag == - lun_list[i].lp_tag)) { - bfa_trc(ioim->bfa, lun_list[i].rp_tag); - bfa_trc(ioim->bfa, lun_list[i].lp_tag); - bfa_trc(ioim->bfa, scsilun_to_int( - (struct scsi_lun *)&lun_list[i].lun)); - - if ((lun_list[i].ua == BFA_IOIM_LM_UA_SET) && - ((cdb->scsi_cdb[0] != INQUIRY) || - (cdb->scsi_cdb[0] != REPORT_LUNS))) { - lun_list[i].ua = BFA_IOIM_LM_UA_RESET; - return BFA_IOIM_LM_RPL_DATA_CHANGED; - } - - if (cdb->scsi_cdb[0] == REPORT_LUNS) - ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data; - - return BFA_IOIM_LM_PRESENT; - } - } - - if ((cdb->scsi_cdb[0] == INQUIRY) && - (scsilun_to_int((struct scsi_lun *)&lun) == 0)) { - ioim->proc_rsp_data = bfa_ioim_lm_proc_inq_data; - return BFA_IOIM_LM_PRESENT; - } - - if (cdb->scsi_cdb[0] == TEST_UNIT_READY) - return BFA_IOIM_LM_LUN_NOT_RDY; - - return BFA_IOIM_LM_LUN_NOT_SUP; -} - -static bfa_boolean_t -bfa_ioim_lm_proc_rsp_data_dummy(struct bfa_ioim_s *ioim) -{ - return BFA_TRUE; -} - -static void -bfa_ioim_lm_fetch_lun(struct bfa_ioim_s *ioim, u8 *rl_data, int offset, - int buf_lun_cnt) -{ - struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa); - struct scsi_lun *lun_data = (struct scsi_lun *)(rl_data + offset); - struct scsi_lun lun; - int i, j; - - bfa_trc(ioim->bfa, buf_lun_cnt); - for (j = 0; j < buf_lun_cnt; j++) { - lun = *((struct scsi_lun *)(lun_data + j)); - for (i = 0; i < MAX_LUN_MASK_CFG; i++) { - if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE) - continue; - if ((lun_list[i].rp_wwn == bfa_ioim_rp_wwn(ioim)) && - (lun_list[i].lp_wwn == bfa_ioim_lp_wwn(ioim)) && - (scsilun_to_int((struct scsi_lun *)&lun_list[i].lun) - == scsilun_to_int((struct scsi_lun *)&lun))) { - lun_list[i].state = BFA_IOIM_LUN_MASK_FETCHED; - break; - } - } /* next lun in mask DB */ - } /* next lun in buf */ -} - -static int -bfa_ioim_lm_update_lun_sg(struct bfa_ioim_s *ioim, u32 *pgdlen, - struct scsi_report_luns_data_s *rl) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio; - struct scatterlist *sg = scsi_sglist(cmnd); - struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa); - struct scsi_lun *prev_rl_data = NULL, *base_rl_data; - int i, j, sgeid, lun_fetched_cnt = 0, prev_sg_len = 0, base_count; - int lun_across_sg_bytes, bytes_from_next_buf; - u64 last_lun, temp_last_lun; - - /* fetch luns from the first sg element */ - bfa_ioim_lm_fetch_lun(ioim, (u8 *)(rl->lun), 0, - (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1); - - /* fetch luns from multiple sg elements */ - scsi_for_each_sg(cmnd, sg, scsi_sg_count(cmnd), sgeid) { - if (sgeid == 0) { - prev_sg_len = sg_dma_len(sg); - prev_rl_data = (struct scsi_lun *) - phys_to_virt(sg_dma_address(sg)); - continue; - } - - /* if the buf is having more data */ - lun_across_sg_bytes = prev_sg_len % sizeof(struct scsi_lun); - if (lun_across_sg_bytes) { - bfa_trc(ioim->bfa, lun_across_sg_bytes); - bfa_stats(ioim->itnim, lm_lun_across_sg); - bytes_from_next_buf = sizeof(struct scsi_lun) - - lun_across_sg_bytes; - - /* from next buf take higher bytes */ - temp_last_lun = *((u64 *) - phys_to_virt(sg_dma_address(sg))); - last_lun |= temp_last_lun >> - (lun_across_sg_bytes * BITS_PER_BYTE); - - /* from prev buf take higher bytes */ - temp_last_lun = *((u64 *)(prev_rl_data + - (prev_sg_len - lun_across_sg_bytes))); - temp_last_lun >>= bytes_from_next_buf * BITS_PER_BYTE; - last_lun = last_lun | (temp_last_lun << - (bytes_from_next_buf * BITS_PER_BYTE)); - - bfa_ioim_lm_fetch_lun(ioim, (u8 *)&last_lun, 0, 1); - } else - bytes_from_next_buf = 0; - - *pgdlen += sg_dma_len(sg); - prev_sg_len = sg_dma_len(sg); - prev_rl_data = (struct scsi_lun *) - phys_to_virt(sg_dma_address(sg)); - bfa_ioim_lm_fetch_lun(ioim, (u8 *)prev_rl_data, - bytes_from_next_buf, - sg_dma_len(sg) / sizeof(struct scsi_lun)); - } - - /* update the report luns data - based on fetched luns */ - sg = scsi_sglist(cmnd); - base_rl_data = (struct scsi_lun *)rl->lun; - base_count = (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1; - for (i = 0, j = 0; i < MAX_LUN_MASK_CFG; i++) { - if (lun_list[i].state == BFA_IOIM_LUN_MASK_FETCHED) { - base_rl_data[j] = lun_list[i].lun; - lun_list[i].state = BFA_IOIM_LUN_MASK_ACTIVE; - j++; - lun_fetched_cnt++; - } - - if (j > base_count) { - j = 0; - sg = sg_next(sg); - base_rl_data = (struct scsi_lun *) - phys_to_virt(sg_dma_address(sg)); - base_count = sg_dma_len(sg) / sizeof(struct scsi_lun); - } - } - - bfa_trc(ioim->bfa, lun_fetched_cnt); - return lun_fetched_cnt; -} - -static bfa_boolean_t -bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim) -{ - struct scsi_inquiry_data_s *inq; - struct scatterlist *sg = scsi_sglist((struct scsi_cmnd *)ioim->dio); - - ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; - inq = (struct scsi_inquiry_data_s *)phys_to_virt(sg_dma_address(sg)); - - bfa_trc(ioim->bfa, inq->device_type); - inq->peripheral_qual = SCSI_INQ_PQ_NOT_CON; - return 0; -} - -static bfa_boolean_t -bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio; - struct scatterlist *sg = scsi_sglist(cmnd); - struct bfi_ioim_rsp_s *m; - struct scsi_report_luns_data_s *rl = NULL; - int lun_count = 0, lun_fetched_cnt = 0; - u32 residue, pgdlen = 0; - - ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; - if (bfa_get_lun_mask_status(ioim->bfa) != BFA_LUNMASK_ENABLED) - return BFA_TRUE; - - m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg; - if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION) - return BFA_TRUE; - - pgdlen = sg_dma_len(sg); - bfa_trc(ioim->bfa, pgdlen); - rl = (struct scsi_report_luns_data_s *)phys_to_virt(sg_dma_address(sg)); - lun_count = cpu_to_be32(rl->lun_list_length) / sizeof(struct scsi_lun); - lun_fetched_cnt = bfa_ioim_lm_update_lun_sg(ioim, &pgdlen, rl); - - if (lun_count == lun_fetched_cnt) - return BFA_TRUE; - - bfa_trc(ioim->bfa, lun_count); - bfa_trc(ioim->bfa, lun_fetched_cnt); - bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length)); - - if (be32_to_cpu(rl->lun_list_length) <= pgdlen) - rl->lun_list_length = be32_to_cpu(lun_fetched_cnt) * - sizeof(struct scsi_lun); - else - bfa_stats(ioim->itnim, lm_small_buf_addresidue); - - bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length)); - bfa_trc(ioim->bfa, be32_to_cpu(m->residue)); - - residue = be32_to_cpu(m->residue); - residue += (lun_count - lun_fetched_cnt) * sizeof(struct scsi_lun); - bfa_stats(ioim->itnim, lm_wire_residue_changed); - m->residue = be32_to_cpu(residue); - bfa_trc(ioim->bfa, ioim->nsges); - return BFA_FALSE; -} - static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete) { @@ -2454,83 +2167,6 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete) m->scsi_status, sns_len, snsinfo, residue); } -static void -__bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete) -{ - struct bfa_ioim_s *ioim = cbarg; - int sns_len = 0xD; - u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio); - struct scsi_sense_s *snsinfo; - - if (!complete) { - bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); - return; - } - - snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG( - ioim->fcpim->fcp, ioim->iotag); - snsinfo->rsp_code = SCSI_SENSE_CUR_ERR; - snsinfo->add_sense_length = 0xa; - snsinfo->asc = SCSI_ASC_LUN_NOT_SUPPORTED; - snsinfo->sense_key = ILLEGAL_REQUEST; - bfa_trc(ioim->bfa, residue); - bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK, - SCSI_STATUS_CHECK_CONDITION, sns_len, - (u8 *)snsinfo, residue); -} - -static void -__bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete) -{ - struct bfa_ioim_s *ioim = cbarg; - int sns_len = 0xD; - u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio); - struct scsi_sense_s *snsinfo; - - if (!complete) { - bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); - return; - } - - snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp, - ioim->iotag); - snsinfo->rsp_code = SCSI_SENSE_CUR_ERR; - snsinfo->sense_key = SCSI_MP_IEC_UNIT_ATTN; - snsinfo->asc = SCSI_ASC_TOCC; - snsinfo->add_sense_length = 0x6; - snsinfo->ascq = SCSI_ASCQ_RL_DATA_CHANGED; - bfa_trc(ioim->bfa, residue); - bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK, - SCSI_STATUS_CHECK_CONDITION, sns_len, - (u8 *)snsinfo, residue); -} - -static void -__bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete) -{ - struct bfa_ioim_s *ioim = cbarg; - int sns_len = 0xD; - u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio); - struct scsi_sense_s *snsinfo; - - if (!complete) { - bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); - return; - } - - snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG( - ioim->fcpim->fcp, ioim->iotag); - snsinfo->rsp_code = SCSI_SENSE_CUR_ERR; - snsinfo->add_sense_length = 0xa; - snsinfo->sense_key = NOT_READY; - snsinfo->asc = SCSI_ASC_LUN_NOT_READY; - snsinfo->ascq = SCSI_ASCQ_MAN_INTR_REQ; - bfa_trc(ioim->bfa, residue); - bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK, - SCSI_STATUS_CHECK_CONDITION, sns_len, - (u8 *)snsinfo, residue); -} - void bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn, u16 rp_tag, u8 lp_tag) @@ -2759,7 +2395,6 @@ __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete) return; } - ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED, 0, 0, NULL, 0); } @@ -2775,7 +2410,6 @@ __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete) return; } - ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV, 0, 0, NULL, 0); } @@ -2790,7 +2424,6 @@ __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete) return; } - ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio); } @@ -3134,7 +2767,6 @@ bfa_ioim_attach(struct bfa_fcpim_s *fcpim) ioim->bfa = fcpim->bfa; ioim->fcpim = fcpim; ioim->iosp = iosp; - ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; INIT_LIST_HEAD(&ioim->sgpg_q); bfa_reqq_winit(&ioim->iosp->reqq_wait, bfa_ioim_qresume, ioim); @@ -3172,7 +2804,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) evt = BFA_IOIM_SM_DONE; else evt = BFA_IOIM_SM_COMP; - ioim->proc_rsp_data(ioim); break; case BFI_IOIM_STS_TIMEDOUT: @@ -3208,7 +2839,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) if (rsp->abort_tag != ioim->abort_tag) { bfa_trc(ioim->bfa, rsp->abort_tag); bfa_trc(ioim->bfa, ioim->abort_tag); - ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; return; } @@ -3227,7 +2857,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) WARN_ON(1); } - ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy; bfa_sm_send_event(ioim, evt); } @@ -3246,15 +2875,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m) bfa_ioim_cb_profile_comp(fcpim, ioim); - if (bfa_get_lun_mask_status(bfa) != BFA_LUNMASK_ENABLED) { - bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); - return; - } - - if (ioim->proc_rsp_data(ioim) == BFA_TRUE) - bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); - else - bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP); + bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); } /* @@ -3366,35 +2987,6 @@ bfa_ioim_free(struct bfa_ioim_s *ioim) void bfa_ioim_start(struct bfa_ioim_s *ioim) { - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio; - struct bfa_lps_s *lps; - enum bfa_ioim_lm_status status; - struct scsi_lun scsilun; - - if (bfa_get_lun_mask_status(ioim->bfa) == BFA_LUNMASK_ENABLED) { - lps = BFA_IOIM_TO_LPS(ioim); - int_to_scsilun(cmnd->device->lun, &scsilun); - status = bfa_ioim_lm_check(ioim, lps, - ioim->itnim->rport, scsilun); - if (status == BFA_IOIM_LM_LUN_NOT_RDY) { - bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_RDY); - bfa_stats(ioim->itnim, lm_lun_not_rdy); - return; - } - - if (status == BFA_IOIM_LM_LUN_NOT_SUP) { - bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_SUP); - bfa_stats(ioim->itnim, lm_lun_not_sup); - return; - } - - if (status == BFA_IOIM_LM_RPL_DATA_CHANGED) { - bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_RPL_DC); - bfa_stats(ioim->itnim, lm_rpl_data_changed); - return; - } - } - bfa_ioim_cb_profile_start(ioim->fcpim, ioim); /* diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index 1080bcb81cb7..36f26da80f76 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h @@ -110,7 +110,6 @@ struct bfad_ioim_s; struct bfad_tskim_s; typedef void (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim); -typedef bfa_boolean_t (*bfa_ioim_lm_proc_rsp_data_t) (struct bfa_ioim_s *ioim); struct bfa_fcpim_s { struct bfa_s *bfa; @@ -124,7 +123,6 @@ struct bfa_fcpim_s { u32 path_tov; u16 q_depth; u8 reqq; /* Request queue to be used */ - u8 lun_masking_pending; struct list_head itnim_q; /* queue of active itnim */ struct list_head ioim_resfree_q; /* IOs waiting for f/w */ struct list_head ioim_comp_q; /* IO global comp Q */ @@ -181,7 +179,6 @@ struct bfa_ioim_s { u8 reqq; /* Request queue for I/O */ u8 mode; /* IO is passthrough or not */ u64 start_time; /* IO's Profile start val */ - bfa_ioim_lm_proc_rsp_data_t proc_rsp_data; /* RSP data adjust */ }; struct bfa_ioim_sp_s { @@ -261,10 +258,6 @@ struct bfa_itnim_s { (__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET; \ } while (0) -#define BFA_IOIM_TO_LPS(__ioim) \ - BFA_LPS_FROM_TAG(BFA_LPS_MOD(__ioim->bfa), \ - __ioim->itnim->rport->rport_info.lp_tag) - static inline bfa_boolean_t bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim) { diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 95adb86d3769..b52cbb6bcd5a 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -582,11 +582,6 @@ void bfa_cb_rport_qos_scn_prio(void *rport, #define BFA_LP_TAG_INVALID 0xff void bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp); void bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp); -bfa_boolean_t bfa_rport_lunmask_active(struct bfa_rport_s *rp); -wwn_t bfa_rport_get_pwwn(struct bfa_s *bfa, struct bfa_rport_s *rp); -struct bfa_rport_s *bfa_rport_get_by_wwn(struct bfa_s *bfa, u16 vf_id, - wwn_t *lpwwn, wwn_t rpwwn); -void *bfa_cb_get_rp_by_wwn(void *arg, u16 vf_id, wwn_t *lpwwn, wwn_t rpwwn); /* * bfa fcxp API functions -- cgit From 5b7db7af522d9f281ff8bf540d2b5cbea2206b27 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Tue, 20 Dec 2011 18:58:32 -0800 Subject: [SCSI] bfa: Implement LUN Masking feature using the SCSI Slave Callouts. This patch re-implements LUN Masking feature using SCSI Slave Callouts. With the new design in the slave_alloc entry point; for each new LUN discovered we check with our internal LUN Masking config whether to expose or to mask this particular LUN. We return -ENXIO (No such device or address) from slave_alloc for the LUNs we don't want to be exposed. We also notify the SCSI mid-layer to do a sequential LUN scan rather than REPORT_LUNS based scan if LUN masking is enabled on our HBA port, since a -ENXIO from any LUN in REPORT_LUNS based scan translates to a scan abort. This patch also handles the dynamic lun masking config change from enable to disable or vice-versa by resetting sdev_bflags of LUN 0 appropriately. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad.c | 2 ++ drivers/scsi/bfa/bfad_attr.c | 2 +- drivers/scsi/bfa/bfad_bsg.c | 27 ++++++++++++++++++--- drivers/scsi/bfa/bfad_drv.h | 2 ++ drivers/scsi/bfa/bfad_im.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/bfa/bfad_im.h | 27 +++++++++++++++++++++ 6 files changed, 112 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 66fb72531b34..404fd10ddb21 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -674,6 +674,7 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id, spin_lock_irqsave(&bfad->bfad_lock, flags); bfa_fcs_vport_start(&vport->fcs_vport); + list_add_tail(&vport->list_entry, &bfad->vport_list); spin_unlock_irqrestore(&bfad->bfad_lock, flags); return BFA_STATUS_OK; @@ -1404,6 +1405,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) bfad->ref_count = 0; bfad->pport.bfad = bfad; INIT_LIST_HEAD(&bfad->pbc_vport_list); + INIT_LIST_HEAD(&bfad->vport_list); /* Setup the debugfs node for this bfad */ if (bfa_debugfs_enable) diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 9d95844ab463..1938fe0473e9 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -491,7 +491,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport) free_scsi_host: bfad_scsi_host_free(bfad, im_port); - + list_del(&vport->list_entry); kfree(vport); return 0; diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 06fc00caeb41..530de2b1200a 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -2394,6 +2394,21 @@ out: return 0; } +/* Function to reset the LUN SCAN mode */ +static void +bfad_iocmd_lunmask_reset_lunscan_mode(struct bfad_s *bfad, int lunmask_cfg) +{ + struct bfad_im_port_s *pport_im = bfad->pport.im_port; + struct bfad_vport_s *vport = NULL; + + /* Set the scsi device LUN SCAN flags for base port */ + bfad_reset_sdev_bflags(pport_im, lunmask_cfg); + + /* Set the scsi device LUN SCAN flags for the vports */ + list_for_each_entry(vport, &bfad->vport_list, list_entry) + bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg); +} + int bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) { @@ -2401,11 +2416,17 @@ bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd) unsigned long flags; spin_lock_irqsave(&bfad->bfad_lock, flags); - if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) + if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) { iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE); - else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) + /* Set the LUN Scanning mode to be Sequential scan */ + if (iocmd->status == BFA_STATUS_OK) + bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_TRUE); + } else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) { iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE); - else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR) + /* Set the LUN Scanning mode to default REPORT_LUNS scan */ + if (iocmd->status == BFA_STATUS_OK) + bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_FALSE); + } else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR) iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa); spin_unlock_irqrestore(&bfad->bfad_lock, flags); return 0; diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 5e19a5f820ec..dc5b9d99c450 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -43,6 +43,7 @@ #include #include #include +#include #include "bfa_modules.h" #include "bfa_fcs.h" @@ -227,6 +228,7 @@ struct bfad_s { struct list_head active_aen_q; struct bfa_aen_entry_s aen_list[BFA_AEN_MAX_ENTRY]; spinlock_t bfad_aen_spinlock; + struct list_head vport_list; }; /* BFAD state machine events */ diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index e5db649e8eb7..3153923f5b60 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -917,6 +917,37 @@ bfad_get_itnim(struct bfad_im_port_s *im_port, int id) return NULL; } +/* + * Function is invoked from the SCSI Host Template slave_alloc() entry point. + * Has the logic to query the LUN Mask database to check if this LUN needs to + * be made visible to the SCSI mid-layer or not. + * + * Returns BFA_STATUS_OK if this LUN needs to be added to the OS stack. + * Returns -ENXIO to notify SCSI mid-layer to not add this LUN to the OS stack. + */ +static int +bfad_im_check_if_make_lun_visible(struct scsi_device *sdev, + struct fc_rport *rport) +{ + struct bfad_itnim_data_s *itnim_data = + (struct bfad_itnim_data_s *) rport->dd_data; + struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa; + struct bfa_rport_s *bfa_rport = itnim_data->itnim->bfa_itnim->rport; + struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(bfa); + int i = 0, ret = -ENXIO; + + for (i = 0; i < MAX_LUN_MASK_CFG; i++) { + if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE && + scsilun_to_int(&lun_list[i].lun) == sdev->lun && + lun_list[i].rp_tag == bfa_rport->rport_tag && + lun_list[i].lp_tag == (u8)bfa_rport->rport_info.lp_tag) { + ret = BFA_STATUS_OK; + break; + } + } + return ret; +} + /* * Scsi_Host template entry slave_alloc */ @@ -924,10 +955,33 @@ static int bfad_im_slave_alloc(struct scsi_device *sdev) { struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); + struct bfad_itnim_data_s *itnim_data = + (struct bfad_itnim_data_s *) rport->dd_data; + struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa; if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; + if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) { + /* + * We should not mask LUN 0 - since this will translate + * to no LUN / TARGET for SCSI ml resulting no scan. + */ + if (sdev->lun == 0) { + sdev->sdev_bflags |= BLIST_NOREPORTLUN | + BLIST_SPARSELUN; + goto done; + } + + /* + * Query LUN Mask configuration - to expose this LUN + * to the SCSI mid-layer or to mask it. + */ + if (bfad_im_check_if_make_lun_visible(sdev, rport) != + BFA_STATUS_OK) + return -ENXIO; + } +done: sdev->hostdata = rport->dd_data; return 0; @@ -1037,6 +1091,8 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim) && (fc_rport->scsi_target_id < MAX_FCP_TARGET)) itnim->scsi_tgt_id = fc_rport->scsi_target_id; + itnim->channel = fc_rport->channel; + return; } diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h index 004b6cf848d9..0814367ef101 100644 --- a/drivers/scsi/bfa/bfad_im.h +++ b/drivers/scsi/bfa/bfad_im.h @@ -91,6 +91,7 @@ struct bfad_itnim_s { struct fc_rport *fc_rport; struct bfa_itnim_s *bfa_itnim; u16 scsi_tgt_id; + u16 channel; u16 queue_work; unsigned long last_ramp_up_time; unsigned long last_queue_full_time; @@ -166,4 +167,30 @@ irqreturn_t bfad_intx(int irq, void *dev_id); int bfad_im_bsg_request(struct fc_bsg_job *job); int bfad_im_bsg_timeout(struct fc_bsg_job *job); +/* + * Macro to set the SCSI device sdev_bflags - sdev_bflags are used by the + * SCSI mid-layer to choose LUN Scanning mode REPORT_LUNS vs. Sequential Scan + * + * Internally iterate's over all the ITNIM's part of the im_port & set's the + * sdev_bflags for the scsi_device associated with LUN #0. + */ +#define bfad_reset_sdev_bflags(__im_port, __lunmask_cfg) do { \ + struct scsi_device *__sdev = NULL; \ + struct bfad_itnim_s *__itnim = NULL; \ + u32 scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN; \ + list_for_each_entry(__itnim, &((__im_port)->itnim_mapped_list), \ + list_entry) { \ + __sdev = scsi_device_lookup((__im_port)->shost, \ + __itnim->channel, \ + __itnim->scsi_tgt_id, 0); \ + if (__sdev) { \ + if ((__lunmask_cfg) == BFA_TRUE) \ + __sdev->sdev_bflags |= scan_flags; \ + else \ + __sdev->sdev_bflags &= ~scan_flags; \ + scsi_device_put(__sdev); \ + } \ + } \ +} while (0) + #endif -- cgit From 410f02d813212eef1dedfcfd43460dd11a0ff707 Mon Sep 17 00:00:00 2001 From: "Moger, Babu" Date: Wed, 21 Dec 2011 18:01:37 -0500 Subject: [SCSI] scsi_dh_alua: Retry the check-condition in case Mode Parameters Changed This patch adds a check-condition in scsi_dh_alua handler for a retry. Sometimes, I have seen attach failing due to this check-condition with following error messages on NetApp E series storage. Dec 7 15:31:01 nilgiris kernel: [102979.696673] scsi 3:0:2:9: alua: port group 00 rel port 01 Dec 7 15:31:01 nilgiris kernel: [102979.697082] scsi 3:0:2:9: alua: rtpg failed with 8000002 Dec 7 15:31:01 nilgiris kernel: [102979.697086] scsi 3:0:2:9: alua: rtpg sense code 06/2a/01 Dec 7 15:31:01 nilgiris kernel: [102979.697088] scsi 3:0:2:9: alua: not attached Signed-off-by: Babu Moger Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_alua.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 4ef021291a4d..04c5cea47a22 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -466,6 +466,11 @@ static int alua_check_sense(struct scsi_device *sdev, * Power On, Reset, or Bus Device Reset, just retry. */ return ADD_TO_MLQUEUE; + if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01) + /* + * Mode Parameters Changed + */ + return ADD_TO_MLQUEUE; if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) /* * ALUA state changed -- cgit From 90ab5ee94171b3e28de6bb42ee30b527014e0be7 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 13 Jan 2012 09:32:20 +1030 Subject: module_param: make bool parameters really bool (drivers & misc) module_param(bool) used to counter-intuitively take an int. In fddd5201 (mid-2009) we allowed bool or int/unsigned int using a messy trick. It's time to remove the int/unsigned int option. For this version it'll simply give a warning, but it'll break next kernel version. Acked-by: Mauro Carvalho Chehab Signed-off-by: Rusty Russell --- drivers/scsi/aha1542.c | 2 +- drivers/scsi/dc395x.c | 2 +- drivers/scsi/nsp32.c | 4 ++-- drivers/scsi/pcmcia/nsp_cs.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 195823a51aab..ed119cedaae0 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -102,7 +102,7 @@ static int setup_dmaspeed[MAXBOARDS] __initdata = { -1, -1, -1, -1 }; */ #if defined(MODULE) -static int isapnp = 0; +static bool isapnp = 0; static int aha1542[] = {0x330, 11, 4, -1}; module_param_array(aha1542, int, NULL, 0); module_param(isapnp, bool, 0); diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index f5b718d3c31b..13aeca3d51f2 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -546,7 +546,7 @@ static struct ParameterData __devinitdata cfg_data[] = { * command line overrides will be used. If set to 1 then safe and * slow settings will be used. */ -static int use_safe_settings = 0; +static bool use_safe_settings = 0; module_param_named(safe, use_safe_settings, bool, 0); MODULE_PARM_DESC(safe, "Use safe and slow settings only. Default: false"); diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index f6a50c98c36f..002924963cd8 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -59,11 +59,11 @@ MODULE_PARM_DESC(trans_mode, "transfer mode (0: BIOS(default) 1: Async 2: Ultra2 #define ASYNC_MODE 1 #define ULTRA20M_MODE 2 -static int auto_param = 0; /* default: ON */ +static bool auto_param = 0; /* default: ON */ module_param (auto_param, bool, 0); MODULE_PARM_DESC(auto_param, "AutoParameter mode (0: ON(default) 1: OFF)"); -static int disc_priv = 1; /* default: OFF */ +static bool disc_priv = 1; /* default: OFF */ module_param (disc_priv, bool, 0); MODULE_PARM_DESC(disc_priv, "disconnection privilege mode (0: ON 1: OFF(default))"); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index ca86721a71b9..b61a753eb896 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -70,7 +70,7 @@ module_param(nsp_burst_mode, int, 0); MODULE_PARM_DESC(nsp_burst_mode, "Burst transfer mode (0=io8, 1=io32, 2=mem32(default))"); /* Release IO ports after configuration? */ -static int free_ports = 0; +static bool free_ports = 0; module_param(free_ports, bool, 0); MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 (=no))"); -- cgit From 577ebb374c78314ac4617242f509e2f5e7156649 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 12 Jan 2012 16:01:27 +0100 Subject: block: add and use scsi_blk_cmd_ioctl Introduce a wrapper around scsi_cmd_ioctl that takes a block device. The function will then be enhanced to detect partition block devices and, in that case, subject the ioctls to whitelisting. Cc: linux-scsi@vger.kernel.org Cc: Jens Axboe Cc: James Bottomley Signed-off-by: Paolo Bonzini Signed-off-by: Linus Torvalds --- drivers/scsi/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7b3f8075e2a5..b4d57bb04c72 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1097,7 +1097,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, error = scsi_ioctl(sdp, cmd, p); break; default: - error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); + error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); if (error != -ENOTTY) break; error = scsi_ioctl(sdp, cmd, p); -- cgit From 0bfc96cb77224736dfa35c3c555d37b3646ef35e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 12 Jan 2012 16:01:28 +0100 Subject: block: fail SCSI passthrough ioctls on partition devices Linux allows executing the SG_IO ioctl on a partition or LVM volume, and will pass the command to the underlying block device. This is well-known, but it is also a large security problem when (via Unix permissions, ACLs, SELinux or a combination thereof) a program or user needs to be granted access only to part of the disk. This patch lets partitions forward a small set of harmless ioctls; others are logged with printk so that we can see which ioctls are actually sent. In my tests only CDROM_GET_CAPABILITY actually occurred. Of course it was being sent to a (partition on a) hard disk, so it would have failed with ENOTTY and the patch isn't changing anything in practice. Still, I'm treating it specially to avoid spamming the logs. In principle, this restriction should include programs running with CAP_SYS_RAWIO. If for example I let a program access /dev/sda2 and /dev/sdb, it still should not be able to read/write outside the boundaries of /dev/sda2 independent of the capabilities. However, for now programs with CAP_SYS_RAWIO will still be allowed to send the ioctls. Their actions will still be logged. This patch does not affect the non-libata IDE driver. That driver however already tests for bd != bd->bd_contains before issuing some ioctl; it could be restricted further to forbid these ioctls even for programs running with CAP_SYS_ADMIN/CAP_SYS_RAWIO. Cc: linux-scsi@vger.kernel.org Cc: Jens Axboe Cc: James Bottomley Signed-off-by: Paolo Bonzini [ Make it also print the command name when warning - Linus ] Signed-off-by: Linus Torvalds --- drivers/scsi/sd.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index b4d57bb04c72..c691fb50e6cb 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1075,6 +1075,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, " "cmd=0x%x\n", disk->disk_name, cmd)); + error = scsi_verify_blk_ioctl(bdev, cmd); + if (error < 0) + return error; + /* * If we are in the middle of error recovery, don't let anyone * else try and use this device. Also, if error recovery fails, it @@ -1267,6 +1271,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; + int ret; + + ret = scsi_verify_blk_ioctl(bdev, cmd); + if (ret < 0) + return ret; /* * If we are in the middle of error recovery, don't let anyone @@ -1278,8 +1287,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, return -ENODEV; if (sdev->host->hostt->compat_ioctl) { - int ret; - ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); return ret; -- cgit From 0eecee413d3157bac4477362bfc4b907b4b2988b Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 3 Nov 2011 11:10:40 -0400 Subject: [SCSI] scsi_transport_fc: Clear Devloss Callback Done flag in fc_remote_port_rolechg This patch fixes a bug where devloss is not called on fc_host teardown. The issue is seen if the LLDD uses rport_rolechg to add the target role to an rport. When an rport goes away, the LLDD will call fc_remote_port_delete, which will start the devloss timer. If the timer expires, the transport will call the devloss callback and set the FC_RPORT_DEVLOSS_CALLBK_DONE flag. However, the rport structure is not deleted, it is retained to store the SCSI id mappings for the rport in case it comes back. In the scenario where it does come back, and the driver calls fc_remote_port_add, but does not indicate the "target" role for the rport - the create will clear the structure, but forgets to clear FC_RPORT_DEVLOSS_CALLBK_DONE flag (which is cleared if it's added with the target role). The secondary call, of fc_remote_port_rolechg to add the target role also does not clear the flag. Thus, the next time the rport goes away, the resulting devloss timer expiration will not call the driver callback as the flag is still set. This patch adds the FC_RPORT_DEVLOSS_CALLBK_DONE flags to the list of those that are cleared upon reuse of the rport structure. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 1b214910b714..f59d4a05ecd7 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3048,7 +3048,8 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) spin_lock_irqsave(shost->host_lock, flags); rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT | - FC_RPORT_DEVLOSS_PENDING); + FC_RPORT_DEVLOSS_PENDING | + FC_RPORT_DEVLOSS_CALLBK_DONE); spin_unlock_irqrestore(shost->host_lock, flags); /* ensure any stgt delete functions are done */ -- cgit From 775bf2773858c50d2acfcdf71889984be94e7037 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 5 Jan 2012 10:15:31 -0600 Subject: [SCSI] hpsa: do not sleep in atomic context in rmmod path. Don't call kthread_stop with a spin lock held and interrupts disabled because kthread_stop will sleep waiting for the thread to stop. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5140f5d0fd6b..b96962c39449 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4271,7 +4271,9 @@ static void stop_controller_lockup_detector(struct ctlr_info *h) remove_ctlr_from_lockup_detector_list(h); /* If the list of ctlr's to monitor is empty, stop the thread */ if (list_empty(&hpsa_ctlr_list)) { + spin_unlock_irqrestore(&lockup_detector_lock, flags); kthread_stop(hpsa_lockup_detector); + spin_lock_irqsave(&lockup_detector_lock, flags); hpsa_lockup_detector = NULL; } spin_unlock_irqrestore(&lockup_detector_lock, flags); -- cgit From 0d4c24cc1bf62e75fdb31e73c68daa50e0877564 Mon Sep 17 00:00:00 2001 From: adam radford Date: Fri, 6 Jan 2012 17:02:26 -0800 Subject: [SCSI] megaraid_sas: Fix reglockFlags for degraded raid5/6 The following patch for megaraid_sas fixes the reglockFlags field for degraded raid5/6 for MR9360/9380, which will result in a performance improvement. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_fp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index 5255dd688aca..294abb0defa6 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -282,7 +282,9 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow, else { *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */ if ((raid->level >= 5) && - (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER)) + ((instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER && + raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; else if (raid->level == 1) { /* Get alternate Pd. */ -- cgit From 882be7c3be72f6d72ae7a81e707154287ea5d289 Mon Sep 17 00:00:00 2001 From: adam radford Date: Fri, 6 Jan 2012 17:02:34 -0800 Subject: [SCSI] megaraid_sas: mask off flags in ioctl path Mask off flags in the ioctl path to prevent memory scribble with older MegaCLI versions. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_base.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 29a994f9c4f1..2bdc70754b14 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4773,6 +4773,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); cmd->frame->hdr.context = cmd->index; cmd->frame->hdr.pad_0 = 0; + cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 | + MFI_FRAME_SENSE64); /* * The management interface between applications and the fw uses -- cgit From 7895f9c957ff5dbce8e1b96ed11919bb2e20641f Mon Sep 17 00:00:00 2001 From: adam radford Date: Fri, 6 Jan 2012 17:02:40 -0800 Subject: [SCSI] megaraid_sas: remove poll_mode_io code This code has never worked correctly, doesn't disable interrupts when set as a module parameter, doesn't disable interrupts when set after driver load time in sysfs node, etc. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.h | 2 - drivers/scsi/megaraid/megaraid_sas_base.c | 141 ------------------------------ 2 files changed, 143 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index dd94c7d574fb..7a03a9a6bde0 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -773,7 +773,6 @@ struct megasas_ctrl_info { #define MFI_OB_INTR_STATUS_MASK 0x00000002 #define MFI_POLL_TIMEOUT_SECS 60 -#define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10) #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 #define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001 @@ -1353,7 +1352,6 @@ struct megasas_instance { u32 mfiStatus; u32 last_seq_num; - struct timer_list io_completion_timer; struct list_head internal_reset_pending_q; /* Ptr to hba specific information */ diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 2bdc70754b14..f42bd88a30e0 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -58,14 +58,6 @@ #include "megaraid_sas_fusion.h" #include "megaraid_sas.h" -/* - * poll_mode_io:1- schedule complete completion from q cmd - */ -static unsigned int poll_mode_io; -module_param_named(poll_mode_io, poll_mode_io, int, 0); -MODULE_PARM_DESC(poll_mode_io, - "Complete cmds from IO path, (default=0)"); - /* * Number of sectors per IO command * Will be set in megasas_init_mfi if user does not provide @@ -1439,11 +1431,6 @@ megasas_build_and_issue_cmd(struct megasas_instance *instance, instance->instancet->fire_cmd(instance, cmd->frame_phys_addr, cmd->frame_count-1, instance->reg_set); - /* - * Check if we have pend cmds to be completed - */ - if (poll_mode_io && atomic_read(&instance->fw_outstanding)) - tasklet_schedule(&instance->isr_tasklet); return 0; out_return_cmd: @@ -3370,47 +3357,6 @@ fail_fw_init: return -EINVAL; } -/** - * megasas_start_timer - Initializes a timer object - * @instance: Adapter soft state - * @timer: timer object to be initialized - * @fn: timer function - * @interval: time interval between timer function call - */ -static inline void -megasas_start_timer(struct megasas_instance *instance, - struct timer_list *timer, - void *fn, unsigned long interval) -{ - init_timer(timer); - timer->expires = jiffies + interval; - timer->data = (unsigned long)instance; - timer->function = fn; - add_timer(timer); -} - -/** - * megasas_io_completion_timer - Timer fn - * @instance_addr: Address of adapter soft state - * - * Schedules tasklet for cmd completion - * if poll_mode_io is set - */ -static void -megasas_io_completion_timer(unsigned long instance_addr) -{ - struct megasas_instance *instance = - (struct megasas_instance *)instance_addr; - - if (atomic_read(&instance->fw_outstanding)) - tasklet_schedule(&instance->isr_tasklet); - - /* Restart timer */ - if (poll_mode_io) - mod_timer(&instance->io_completion_timer, - jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL); -} - static u32 megasas_init_adapter_mfi(struct megasas_instance *instance) { @@ -3638,11 +3584,6 @@ static int megasas_init_fw(struct megasas_instance *instance) tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, (unsigned long)instance); - /* Initialize the cmd completion timer */ - if (poll_mode_io) - megasas_start_timer(instance, &instance->io_completion_timer, - megasas_io_completion_timer, - MEGASAS_COMPLETION_TIMER_INTERVAL); return 0; fail_init_adapter: @@ -4369,9 +4310,6 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) host = instance->host; instance->unload = 1; - if (poll_mode_io) - del_timer_sync(&instance->io_completion_timer); - megasas_flush_cache(instance); megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); @@ -4511,12 +4449,6 @@ megasas_resume(struct pci_dev *pdev) } instance->instancet->enable_intr(instance->reg_set); - - /* Initialize the cmd completion timer */ - if (poll_mode_io) - megasas_start_timer(instance, &instance->io_completion_timer, - megasas_io_completion_timer, - MEGASAS_COMPLETION_TIMER_INTERVAL); instance->unload = 0; /* @@ -4570,9 +4502,6 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) host = instance->host; fusion = instance->ctrl_context; - if (poll_mode_io) - del_timer_sync(&instance->io_completion_timer); - scsi_remove_host(instance->host); megasas_flush_cache(instance); megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); @@ -5221,60 +5150,6 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl, megasas_sysfs_set_dbg_lvl); -static ssize_t -megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf) -{ - return sprintf(buf, "%u\n", poll_mode_io); -} - -static ssize_t -megasas_sysfs_set_poll_mode_io(struct device_driver *dd, - const char *buf, size_t count) -{ - int retval = count; - int tmp = poll_mode_io; - int i; - struct megasas_instance *instance; - - if (sscanf(buf, "%u", &poll_mode_io) < 1) { - printk(KERN_ERR "megasas: could not set poll_mode_io\n"); - retval = -EINVAL; - } - - /* - * Check if poll_mode_io is already set or is same as previous value - */ - if ((tmp && poll_mode_io) || (tmp == poll_mode_io)) - goto out; - - if (poll_mode_io) { - /* - * Start timers for all adapters - */ - for (i = 0; i < megasas_mgmt_info.max_index; i++) { - instance = megasas_mgmt_info.instance[i]; - if (instance) { - megasas_start_timer(instance, - &instance->io_completion_timer, - megasas_io_completion_timer, - MEGASAS_COMPLETION_TIMER_INTERVAL); - } - } - } else { - /* - * Delete timers for all adapters - */ - for (i = 0; i < megasas_mgmt_info.max_index; i++) { - instance = megasas_mgmt_info.instance[i]; - if (instance) - del_timer_sync(&instance->io_completion_timer); - } - } - -out: - return retval; -} - static void megasas_aen_polling(struct work_struct *work) { @@ -5504,11 +5379,6 @@ megasas_aen_polling(struct work_struct *work) kfree(ev); } - -static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR, - megasas_sysfs_show_poll_mode_io, - megasas_sysfs_set_poll_mode_io); - /** * megasas_init - Driver load entry point */ @@ -5567,11 +5437,6 @@ static int __init megasas_init(void) &driver_attr_dbg_lvl); if (rval) goto err_dcf_dbg_lvl; - rval = driver_create_file(&megasas_pci_driver.driver, - &driver_attr_poll_mode_io); - if (rval) - goto err_dcf_poll_mode_io; - rval = driver_create_file(&megasas_pci_driver.driver, &driver_attr_support_device_change); if (rval) @@ -5580,10 +5445,6 @@ static int __init megasas_init(void) return rval; err_dcf_support_device_change: - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_poll_mode_io); - -err_dcf_poll_mode_io: driver_remove_file(&megasas_pci_driver.driver, &driver_attr_dbg_lvl); err_dcf_dbg_lvl: @@ -5608,8 +5469,6 @@ err_pcidrv: */ static void __exit megasas_exit(void) { - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_poll_mode_io); driver_remove_file(&megasas_pci_driver.driver, &driver_attr_dbg_lvl); driver_remove_file(&megasas_pci_driver.driver, -- cgit From 798edaadba97612224c250d50f880405d75a3af1 Mon Sep 17 00:00:00 2001 From: adam radford Date: Fri, 6 Jan 2012 17:02:45 -0800 Subject: [SCSI] megaraid_sas: Version and Changelog update Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.h | 6 +++--- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 7a03a9a6bde0..e5f416f8042d 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -33,9 +33,9 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "00.00.06.12-rc1" -#define MEGASAS_RELDATE "Oct. 5, 2011" -#define MEGASAS_EXT_VERSION "Wed. Oct. 5 17:00:00 PDT 2011" +#define MEGASAS_VERSION "00.00.06.14-rc1" +#define MEGASAS_RELDATE "Jan. 6, 2012" +#define MEGASAS_EXT_VERSION "Fri. Jan. 6 17:00:00 PDT 2012" /* * Device IDs diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index f42bd88a30e0..8b300be44284 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * FILE: megaraid_sas_base.c - * Version : v00.00.06.12-rc1 + * Version : v00.00.06.14-rc1 * * Authors: LSI Corporation * Sreenivas Bagalkote -- cgit From 7d99b3abaf8412932269a2a2e561138326d61f8b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 4 Jan 2012 01:32:28 -0800 Subject: [SCSI] isci, firmware: Remove isci fallback parameter blob and generator This parameter blob and generator program have been moved to the linux-firmware.git repository. Signed-off-by: Ben Hutchings Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/firmware/Makefile | 19 ------- drivers/scsi/isci/firmware/README | 36 ------------- drivers/scsi/isci/firmware/create_fw.c | 99 ---------------------------------- drivers/scsi/isci/firmware/create_fw.h | 77 -------------------------- 4 files changed, 231 deletions(-) delete mode 100644 drivers/scsi/isci/firmware/Makefile delete mode 100644 drivers/scsi/isci/firmware/README delete mode 100644 drivers/scsi/isci/firmware/create_fw.c delete mode 100644 drivers/scsi/isci/firmware/create_fw.h (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/firmware/Makefile b/drivers/scsi/isci/firmware/Makefile deleted file mode 100644 index 5f54461cabc5..000000000000 --- a/drivers/scsi/isci/firmware/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# Makefile for create_fw -# -CC=gcc -CFLAGS=-c -Wall -O2 -g -LDFLAGS= -SOURCES=create_fw.c -OBJECTS=$(SOURCES:.cpp=.o) -EXECUTABLE=create_fw - -all: $(SOURCES) $(EXECUTABLE) - -$(EXECUTABLE): $(OBJECTS) - $(CC) $(LDFLAGS) $(OBJECTS) -o $@ - -.c.o: - $(CC) $(CFLAGS) $< -O $@ - -clean: - rm -f *.o $(EXECUTABLE) diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README deleted file mode 100644 index 8056d2bd233b..000000000000 --- a/drivers/scsi/isci/firmware/README +++ /dev/null @@ -1,36 +0,0 @@ -This defines the temporary binary blow we are to pass to the SCU -driver to emulate the binary firmware that we will eventually be -able to access via NVRAM on the SCU controller. - -The current size of the binary blob is expected to be 149 bytes or larger - -Header Types: -0x1: Phy Masks -0x2: Phy Gens -0x3: SAS Addrs -0xff: End of Data - -ID string - u8[12]: "#SCU MAGIC#\0" -Version - u8: 1 -SubVersion - u8: 0 - -Header Type - u8: 0x1 -Size - u8: 8 -Phy Mask - u32[8] - -Header Type - u8: 0x2 -Size - u8: 8 -Phy Gen - u32[8] - -Header Type - u8: 0x3 -Size - u8: 8 -Sas Addr - u64[8] - -Header Type - u8: 0xf - - -============================================================================== - -Place isci_firmware.bin in /lib/firmware -Be sure to recreate the initramfs image to include the firmware. - diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c deleted file mode 100644 index c7a2887a7e95..000000000000 --- a/drivers/scsi/isci/firmware/create_fw.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "create_fw.h" -#include "../probe_roms.h" - -int write_blob(struct isci_orom *isci_orom) -{ - FILE *fd; - int err; - size_t count; - - fd = fopen(blob_name, "w+"); - if (!fd) { - perror("Open file for write failed"); - fclose(fd); - return -EIO; - } - - count = fwrite(isci_orom, sizeof(struct isci_orom), 1, fd); - if (count != 1) { - perror("Write data failed"); - fclose(fd); - return -EIO; - } - - fclose(fd); - - return 0; -} - -void set_binary_values(struct isci_orom *isci_orom) -{ - int ctrl_idx, phy_idx, port_idx; - - /* setting OROM signature */ - strncpy(isci_orom->hdr.signature, sig, strlen(sig)); - isci_orom->hdr.version = version; - isci_orom->hdr.total_block_length = sizeof(struct isci_orom); - isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr); - isci_orom->hdr.num_elements = num_elements; - - for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) { - isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type; - isci_orom->ctrl[ctrl_idx].controller.max_concurrent_dev_spin_up = - max_num_concurrent_dev_spin_up; - isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc = - enable_ssc; - - for (port_idx = 0; port_idx < 4; port_idx++) - isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask = - phy_mask[ctrl_idx][port_idx]; - - for (phy_idx = 0; phy_idx < 4; phy_idx++) { - isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high = - (__u32)(sas_addr[ctrl_idx][phy_idx] >> 32); - isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low = - (__u32)(sas_addr[ctrl_idx][phy_idx]); - - isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 = - afe_tx_amp_control0; - isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 = - afe_tx_amp_control1; - isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 = - afe_tx_amp_control2; - isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 = - afe_tx_amp_control3; - } - } -} - -int main(void) -{ - int err; - struct isci_orom *isci_orom; - - isci_orom = malloc(sizeof(struct isci_orom)); - memset(isci_orom, 0, sizeof(struct isci_orom)); - - set_binary_values(isci_orom); - - err = write_blob(isci_orom); - if (err < 0) { - free(isci_orom); - return err; - } - - free(isci_orom); - return 0; -} diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h deleted file mode 100644 index 5f298828d22e..000000000000 --- a/drivers/scsi/isci/firmware/create_fw.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _CREATE_FW_H_ -#define _CREATE_FW_H_ -#include "../probe_roms.h" - - -/* we are configuring for 2 SCUs */ -static const int num_elements = 2; - -/* - * For all defined arrays: - * elements 0-3 are for SCU0, ports 0-3 - * elements 4-7 are for SCU1, ports 0-3 - * - * valid configurations for one SCU are: - * P0 P1 P2 P3 - * ---------------- - * 0xF,0x0,0x0,0x0 # 1 x4 port - * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1 - * # ports - * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2 - * # port - * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port - * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration) - * - * if there is a port/phy on which you do not wish to override the default - * values, use the value assigned to UNINIT_PARAM (255). - */ - -/* discovery mode type (port auto config mode by default ) */ - -/* - * if there is a port/phy on which you do not wish to override the default - * values, use the value "0000000000000000". SAS address of zero's is - * considered invalid and will not be used. - */ -#ifdef MPC -static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE; -static const __u8 phy_mask[2][4] = { {1, 2, 4, 8}, - {1, 2, 4, 8} }; -static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000001ULL, - 0x5FCFFFFFF0000002ULL, - 0x5FCFFFFFF0000003ULL, - 0x5FCFFFFFF0000004ULL }, - { 0x5FCFFFFFF0000005ULL, - 0x5FCFFFFFF0000006ULL, - 0x5FCFFFFFF0000007ULL, - 0x5FCFFFFFF0000008ULL } }; -#else /* APC (default) */ -static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; -static const __u8 phy_mask[2][4]; -static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL, - 0x5FCFFFFF00000001ULL, - 0x5FCFFFFF00000001ULL, - 0x5FCFFFFF00000001ULL }, - { 0x5FCFFFFF00000002ULL, - 0x5FCFFFFF00000002ULL, - 0x5FCFFFFF00000002ULL, - 0x5FCFFFFF00000002ULL } }; -#endif - -/* Maximum number of concurrent device spin up */ -static const int max_num_concurrent_dev_spin_up = 1; - -/* enable of ssc operation */ -static const int enable_ssc; - -/* AFE_TX_AMP_CONTROL */ -static const unsigned int afe_tx_amp_control0 = 0x000bdd08; -static const unsigned int afe_tx_amp_control1 = 0x000ffc00; -static const unsigned int afe_tx_amp_control2 = 0x000b7c09; -static const unsigned int afe_tx_amp_control3 = 0x000afc6e; - -static const char blob_name[] = "isci_firmware.bin"; -static const char sig[] = "ISCUOEMB"; -static const unsigned char version = 0x10; - -#endif -- cgit From 2e5da889d44a3a9629f895de3488306e7f5ddf16 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 4 Jan 2012 01:32:34 -0800 Subject: [SCSI] isci: cleanup oem parameter and recipe handling Before updating the code to support the latest platform updates and silicon revision cleanup some of the long deref chains. Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/host.c | 107 +++++++++++++++++++++-------------------------- drivers/scsi/isci/phy.c | 81 +++++++++++++++++------------------ 2 files changed, 86 insertions(+), 102 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index e7fe9c4c85b8..8e7de192cf6d 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1910,160 +1910,147 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost, #define AFE_REGISTER_WRITE_DELAY 10 -/* Initialize the AFE for this phy index. We need to read the AFE setup from - * the OEM parameters - */ static void sci_controller_afe_initialization(struct isci_host *ihost) { + struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe; const struct sci_oem_params *oem = &ihost->oem_parameters; struct pci_dev *pdev = ihost->pdev; u32 afe_status; u32 phy_id; /* Clear DFX Status registers */ - writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0); + writel(0x0081000f, &afe->afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); if (is_b0(pdev)) { /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement - * Timer, PM Stagger Timer */ - writel(0x0007BFFF, &ihost->scu_registers->afe.afe_pmsn_master_control2); + * Timer, PM Stagger Timer + */ + writel(0x0007BFFF, &afe->afe_pmsn_master_control2); udelay(AFE_REGISTER_WRITE_DELAY); } /* Configure bias currents to normal */ if (is_a2(pdev)) - writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control); + writel(0x00005A00, &afe->afe_bias_control); else if (is_b0(pdev) || is_c0(pdev)) - writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control); + writel(0x00005F00, &afe->afe_bias_control); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable PLL */ if (is_b0(pdev) || is_c0(pdev)) - writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0); + writel(0x80040A08, &afe->afe_pll_control0); else - writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0); + writel(0x80040908, &afe->afe_pll_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Wait for the PLL to lock */ do { - afe_status = readl(&ihost->scu_registers->afe.afe_common_block_status); + afe_status = readl(&afe->afe_common_block_status); udelay(AFE_REGISTER_WRITE_DELAY); } while ((afe_status & 0x00001000) == 0); if (is_a2(pdev)) { - /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ - writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0); + /* Shorten SAS SNW lock time (RxLock timer value from 76 + * us to 50 us) + */ + writel(0x7bcc96ad, &afe->afe_pmsn_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); } for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { + struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_id]; const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id]; if (is_b0(pdev)) { /* Configure transmitter SSC parameters */ - writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); + writel(0x00030000, &xcvr->afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); } else if (is_c0(pdev)) { /* Configure transmitter SSC parameters */ - writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control); + writel(0x0003000, &xcvr->afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); - /* - * All defaults, except the Receive Word Alignament/Comma Detect - * Enable....(0xe800) */ - writel(0x00004500, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + /* All defaults, except the Receive Word + * Alignament/Comma Detect Enable....(0xe800) + */ + writel(0x00004500, &xcvr->afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); } else { - /* - * All defaults, except the Receive Word Alignament/Comma Detect - * Enable....(0xe800) */ - writel(0x00004512, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + /* All defaults, except the Receive Word + * Alignament/Comma Detect Enable....(0xe800) + */ + writel(0x00004512, &xcvr->afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); - writel(0x0050100F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1); + writel(0x0050100F, &xcvr->afe_xcvr_control1); udelay(AFE_REGISTER_WRITE_DELAY); } - /* - * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) - * & increase TX int & ext bias 20%....(0xe85c) */ + /* Power up TX and RX out from power down (PWRDNTX and PWRDNRX) + * & increase TX int & ext bias 20%....(0xe85c) + */ if (is_a2(pdev)) - writel(0x000003F0, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000003F0, &xcvr->afe_channel_control); else if (is_b0(pdev)) { /* Power down TX and RX (PWRDNTX and PWRDNRX) */ - writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000003D7, &xcvr->afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); - - /* - * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) - * & increase TX int & ext bias 20%....(0xe85c) */ - writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000003D4, &xcvr->afe_channel_control); } else { - writel(0x000001E7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000001E7, &xcvr->afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); - - /* - * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) - * & increase TX int & ext bias 20%....(0xe85c) */ - writel(0x000001E4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control); + writel(0x000001E4, &xcvr->afe_channel_control); } udelay(AFE_REGISTER_WRITE_DELAY); if (is_a2(pdev)) { /* Enable TX equalization (0xe824) */ - writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + writel(0x00040000, &xcvr->afe_tx_control); udelay(AFE_REGISTER_WRITE_DELAY); } - /* - * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On), - * RDD=0x0(RX Detect Enabled) ....(0xe800) */ - writel(0x00004100, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0); + writel(0x00004100, &xcvr->afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Leave DFE/FFE on */ if (is_a2(pdev)) - writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + writel(0x3F11103F, &xcvr->afe_rx_ssc_control0); else if (is_b0(pdev)) { - writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + writel(0x3F11103F, &xcvr->afe_rx_ssc_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable TX equalization (0xe824) */ - writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + writel(0x00040000, &xcvr->afe_tx_control); } else { - writel(0x0140DF0F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control1); + writel(0x0140DF0F, &xcvr->afe_rx_ssc_control1); udelay(AFE_REGISTER_WRITE_DELAY); - writel(0x3F6F103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0); + writel(0x3F6F103F, &xcvr->afe_rx_ssc_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable TX equalization (0xe824) */ - writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control); + writel(0x00040000, &xcvr->afe_tx_control); } udelay(AFE_REGISTER_WRITE_DELAY); - writel(oem_phy->afe_tx_amp_control0, - &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0); + writel(oem_phy->afe_tx_amp_control0, &xcvr->afe_tx_amp_control0); udelay(AFE_REGISTER_WRITE_DELAY); - writel(oem_phy->afe_tx_amp_control1, - &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1); + writel(oem_phy->afe_tx_amp_control1, &xcvr->afe_tx_amp_control1); udelay(AFE_REGISTER_WRITE_DELAY); - writel(oem_phy->afe_tx_amp_control2, - &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2); + writel(oem_phy->afe_tx_amp_control2, &xcvr->afe_tx_amp_control2); udelay(AFE_REGISTER_WRITE_DELAY); - writel(oem_phy->afe_tx_amp_control3, - &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3); + writel(oem_phy->afe_tx_amp_control3, &xcvr->afe_tx_amp_control3); udelay(AFE_REGISTER_WRITE_DELAY); } /* Transfer control to the PEs */ - writel(0x00010f00, &ihost->scu_registers->afe.afe_dfx_master_control0); + writel(0x00010f00, &afe->afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); } diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 35f50c2183e1..0ae0990b39dd 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -91,22 +91,23 @@ sci_phy_transport_layer_initialization(struct isci_phy *iphy, static enum sci_status sci_phy_link_layer_initialization(struct isci_phy *iphy, - struct scu_link_layer_registers __iomem *reg) + struct scu_link_layer_registers __iomem *llr) { struct isci_host *ihost = iphy->owning_port->owning_controller; + struct sci_phy_user_params *phy_user; + struct sci_phy_oem_params *phy_oem; int phy_idx = iphy->phy_index; - struct sci_phy_user_params *phy_user = &ihost->user_parameters.phys[phy_idx]; - struct sci_phy_oem_params *phy_oem = - &ihost->oem_parameters.phys[phy_idx]; - u32 phy_configuration; struct sci_phy_cap phy_cap; + u32 phy_configuration; u32 parity_check = 0; u32 parity_count = 0; u32 llctl, link_rate; u32 clksm_value = 0; u32 sp_timeouts = 0; - iphy->link_layer_registers = reg; + phy_user = &ihost->user_parameters.phys[phy_idx]; + phy_oem = &ihost->oem_parameters.phys[phy_idx]; + iphy->link_layer_registers = llr; /* Set our IDENTIFY frame data */ #define SCI_END_DEVICE 0x01 @@ -116,32 +117,26 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE), - &iphy->link_layer_registers->transmit_identification); + &llr->transmit_identification); /* Write the device SAS Address */ - writel(0xFEDCBA98, - &iphy->link_layer_registers->sas_device_name_high); - writel(phy_idx, &iphy->link_layer_registers->sas_device_name_low); + writel(0xFEDCBA98, &llr->sas_device_name_high); + writel(phy_idx, &llr->sas_device_name_low); /* Write the source SAS Address */ - writel(phy_oem->sas_address.high, - &iphy->link_layer_registers->source_sas_address_high); - writel(phy_oem->sas_address.low, - &iphy->link_layer_registers->source_sas_address_low); + writel(phy_oem->sas_address.high, &llr->source_sas_address_high); + writel(phy_oem->sas_address.low, &llr->source_sas_address_low); /* Clear and Set the PHY Identifier */ - writel(0, &iphy->link_layer_registers->identify_frame_phy_id); - writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), - &iphy->link_layer_registers->identify_frame_phy_id); + writel(0, &llr->identify_frame_phy_id); + writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), &llr->identify_frame_phy_id); /* Change the initial state of the phy configuration register */ - phy_configuration = - readl(&iphy->link_layer_registers->phy_configuration); + phy_configuration = readl(&llr->phy_configuration); /* Hold OOB state machine in reset */ phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); - writel(phy_configuration, - &iphy->link_layer_registers->phy_configuration); + writel(phy_configuration, &llr->phy_configuration); /* Configure the SNW capabilities */ phy_cap.all = 0; @@ -155,9 +150,9 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, phy_cap.gen1_ssc = 1; } - /* - * The SAS specification indicates that the phy_capabilities that - * are transmitted shall have an even parity. Calculate the parity. */ + /* The SAS specification indicates that the phy_capabilities that + * are transmitted shall have an even parity. Calculate the parity. + */ parity_check = phy_cap.all; while (parity_check != 0) { if (parity_check & 0x1) @@ -165,20 +160,20 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, parity_check >>= 1; } - /* - * If parity indicates there are an odd number of bits set, then - * set the parity bit to 1 in the phy capabilities. */ + /* If parity indicates there are an odd number of bits set, then + * set the parity bit to 1 in the phy capabilities. + */ if ((parity_count % 2) != 0) phy_cap.parity = 1; - writel(phy_cap.all, &iphy->link_layer_registers->phy_capabilities); + writel(phy_cap.all, &llr->phy_capabilities); /* Set the enable spinup period but disable the ability to send * notify enable spinup */ writel(SCU_ENSPINUP_GEN_VAL(COUNT, phy_user->notify_enable_spin_up_insertion_frequency), - &iphy->link_layer_registers->notify_enable_spinup_control); + &llr->notify_enable_spinup_control); /* Write the ALIGN Insertion Ferequency for connected phy and * inpendent of connected state @@ -189,11 +184,10 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL, phy_user->align_insertion_frequency); - writel(clksm_value, &iphy->link_layer_registers->clock_skew_management); + writel(clksm_value, &llr->clock_skew_management); /* @todo Provide a way to write this register correctly */ - writel(0x02108421, - &iphy->link_layer_registers->afe_lookup_table_control); + writel(0x02108421, &llr->afe_lookup_table_control); llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, (u8)ihost->user_parameters.no_outbound_task_timeout); @@ -210,9 +204,9 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, break; } llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate); - writel(llctl, &iphy->link_layer_registers->link_layer_control); + writel(llctl, &llr->link_layer_control); - sp_timeouts = readl(&iphy->link_layer_registers->sas_phy_timeouts); + sp_timeouts = readl(&llr->sas_phy_timeouts); /* Clear the default 0x36 (54us) RATE_CHANGE timeout value. */ sp_timeouts &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF); @@ -222,20 +216,23 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, */ sp_timeouts |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B); - writel(sp_timeouts, &iphy->link_layer_registers->sas_phy_timeouts); + writel(sp_timeouts, &llr->sas_phy_timeouts); if (is_a2(ihost->pdev)) { - /* Program the max ARB time for the PHY to 700us so we inter-operate with - * the PMC expander which shuts down PHYs if the expander PHY generates too - * many breaks. This time value will guarantee that the initiator PHY will - * generate the break. + /* Program the max ARB time for the PHY to 700us so we + * inter-operate with the PMC expander which shuts down + * PHYs if the expander PHY generates too many breaks. + * This time value will guarantee that the initiator PHY + * will generate the break. */ writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME, - &iphy->link_layer_registers->maximum_arbitration_wait_timer_timeout); + &llr->maximum_arbitration_wait_timer_timeout); } - /* Disable link layer hang detection, rely on the OS timeout for I/O timeouts. */ - writel(0, &iphy->link_layer_registers->link_layer_hang_detection_timeout); + /* Disable link layer hang detection, rely on the OS timeout for + * I/O timeouts. + */ + writel(0, &llr->link_layer_hang_detection_timeout); /* We can exit the initial state to the stopped state */ sci_change_state(&iphy->sm, SCI_PHY_STOPPED); -- cgit From afd13a1f2b05157c7621d87dfe89ea6ea9061bd8 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Wed, 4 Jan 2012 01:32:39 -0800 Subject: [SCSI] isci: update afe (analog-front-end) recipe for C1 C1 silicon requires updates to the phy tuning recipe and also support for user provided cable selects (per-phy) for short, medium, and long cables. Default to 'short' awaiting support for selecting the cable via oem parameters. Reviewed-by: Jiangbi Liu Signed-off-by: Marcin Tomczak Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/host.c | 111 +++++++++++++++++++++++++++++++++-------- drivers/scsi/isci/host.h | 9 +++- drivers/scsi/isci/phy.c | 7 ++- drivers/scsi/isci/probe_roms.c | 2 +- 4 files changed, 103 insertions(+), 26 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 8e7de192cf6d..383bb6913087 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1908,12 +1908,23 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost, ihost->power_control.requesters[iphy->phy_index] = NULL; } +static int is_long_cable(int phy, unsigned char selection_byte) +{ + return 0; +} + +static int is_medium_cable(int phy, unsigned char selection_byte) +{ + return 0; +} + #define AFE_REGISTER_WRITE_DELAY 10 static void sci_controller_afe_initialization(struct isci_host *ihost) { struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe; const struct sci_oem_params *oem = &ihost->oem_parameters; + unsigned char cable_selection_mask = 0; struct pci_dev *pdev = ihost->pdev; u32 afe_status; u32 phy_id; @@ -1922,11 +1933,11 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) writel(0x0081000f, &afe->afe_dfx_master_control0); udelay(AFE_REGISTER_WRITE_DELAY); - if (is_b0(pdev)) { + if (is_b0(pdev) || is_c0(pdev) || is_c1(pdev)) { /* PM Rx Equalization Save, PM SPhy Rx Acknowledgement * Timer, PM Stagger Timer */ - writel(0x0007BFFF, &afe->afe_pmsn_master_control2); + writel(0x0007FFFF, &afe->afe_pmsn_master_control2); udelay(AFE_REGISTER_WRITE_DELAY); } @@ -1935,14 +1946,23 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) writel(0x00005A00, &afe->afe_bias_control); else if (is_b0(pdev) || is_c0(pdev)) writel(0x00005F00, &afe->afe_bias_control); + else if (is_c1(pdev)) + writel(0x00005500, &afe->afe_bias_control); udelay(AFE_REGISTER_WRITE_DELAY); /* Enable PLL */ - if (is_b0(pdev) || is_c0(pdev)) - writel(0x80040A08, &afe->afe_pll_control0); - else + if (is_a2(pdev)) writel(0x80040908, &afe->afe_pll_control0); + else if (is_b0(pdev) || is_c0(pdev)) + writel(0x80040A08, &afe->afe_pll_control0); + else if (is_c1(pdev)) { + writel(0x80000B08, &afe->afe_pll_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + writel(0x00000B08, &afe->afe_pll_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + writel(0x80000B08, &afe->afe_pll_control0); + } udelay(AFE_REGISTER_WRITE_DELAY); @@ -1963,46 +1983,68 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_id]; const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id]; + int cable_length_long = + is_long_cable(phy_id, cable_selection_mask); + int cable_length_medium = + is_medium_cable(phy_id, cable_selection_mask); + + if (is_a2(pdev)) { + /* All defaults, except the Receive Word + * Alignament/Comma Detect Enable....(0xe800) + */ + writel(0x00004512, &xcvr->afe_xcvr_control0); + udelay(AFE_REGISTER_WRITE_DELAY); - if (is_b0(pdev)) { - /* Configure transmitter SSC parameters */ + writel(0x0050100F, &xcvr->afe_xcvr_control1); + udelay(AFE_REGISTER_WRITE_DELAY); + } else if (is_b0(pdev)) { + /* Configure transmitter SSC parameters */ writel(0x00030000, &xcvr->afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); } else if (is_c0(pdev)) { - /* Configure transmitter SSC parameters */ - writel(0x0003000, &xcvr->afe_tx_ssc_control); + /* Configure transmitter SSC parameters */ + writel(0x00010202, &xcvr->afe_tx_ssc_control); udelay(AFE_REGISTER_WRITE_DELAY); /* All defaults, except the Receive Word * Alignament/Comma Detect Enable....(0xe800) */ - writel(0x00004500, &xcvr->afe_xcvr_control0); + writel(0x00014500, &xcvr->afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); - } else { + } else if (is_c1(pdev)) { + /* Configure transmitter SSC parameters */ + writel(0x00010202, &xcvr->afe_tx_ssc_control); + udelay(AFE_REGISTER_WRITE_DELAY); + /* All defaults, except the Receive Word * Alignament/Comma Detect Enable....(0xe800) */ - writel(0x00004512, &xcvr->afe_xcvr_control0); - udelay(AFE_REGISTER_WRITE_DELAY); - - writel(0x0050100F, &xcvr->afe_xcvr_control1); + writel(0x0001C500, &xcvr->afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); } - /* Power up TX and RX out from power down (PWRDNTX and PWRDNRX) - * & increase TX int & ext bias 20%....(0xe85c) + /* Power up TX and RX out from power down (PWRDNTX and + * PWRDNRX) & increase TX int & ext bias 20%....(0xe85c) */ if (is_a2(pdev)) writel(0x000003F0, &xcvr->afe_channel_control); else if (is_b0(pdev)) { - /* Power down TX and RX (PWRDNTX and PWRDNRX) */ writel(0x000003D7, &xcvr->afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); + writel(0x000003D4, &xcvr->afe_channel_control); - } else { + } else if (is_c0(pdev)) { writel(0x000001E7, &xcvr->afe_channel_control); udelay(AFE_REGISTER_WRITE_DELAY); + writel(0x000001E4, &xcvr->afe_channel_control); + } else if (is_c1(pdev)) { + writel(cable_length_long ? 0x000002F7 : 0x000001F7, + &xcvr->afe_channel_control); + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(cable_length_long ? 0x000002F4 : 0x000001F4, + &xcvr->afe_channel_control); } udelay(AFE_REGISTER_WRITE_DELAY); @@ -2012,7 +2054,16 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) udelay(AFE_REGISTER_WRITE_DELAY); } - writel(0x00004100, &xcvr->afe_xcvr_control0); + if (is_a2(pdev) || is_b0(pdev)) + /* RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, + * TPD=0x0(TX Power On), RDD=0x0(RX Detect + * Enabled) ....(0xe800) + */ + writel(0x00004100, &xcvr->afe_xcvr_control0); + else if (is_c0(pdev)) + writel(0x00014100, &xcvr->afe_xcvr_control0); + else if (is_c1(pdev)) + writel(0x0001C100, &xcvr->afe_xcvr_control0); udelay(AFE_REGISTER_WRITE_DELAY); /* Leave DFE/FFE on */ @@ -2023,13 +2074,29 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) udelay(AFE_REGISTER_WRITE_DELAY); /* Enable TX equalization (0xe824) */ writel(0x00040000, &xcvr->afe_tx_control); - } else { - writel(0x0140DF0F, &xcvr->afe_rx_ssc_control1); + } else if (is_c0(pdev)) { + writel(0x01400C0F, &xcvr->afe_rx_ssc_control1); udelay(AFE_REGISTER_WRITE_DELAY); writel(0x3F6F103F, &xcvr->afe_rx_ssc_control0); udelay(AFE_REGISTER_WRITE_DELAY); + /* Enable TX equalization (0xe824) */ + writel(0x00040000, &xcvr->afe_tx_control); + } else if (is_c1(pdev)) { + writel(cable_length_long ? 0x01500C0C : + cable_length_medium ? 0x01400C0D : 0x02400C0D, + &xcvr->afe_xcvr_control1); + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(0x000003E0, &xcvr->afe_dfx_rx_control1); + udelay(AFE_REGISTER_WRITE_DELAY); + + writel(cable_length_long ? 0x33091C1F : + cable_length_medium ? 0x3315181F : 0x2B17161F, + &xcvr->afe_rx_ssc_control0); + udelay(AFE_REGISTER_WRITE_DELAY); + /* Enable TX equalization (0xe824) */ writel(0x00040000, &xcvr->afe_tx_control); } diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 646051afd3cb..4573075a6b97 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -435,7 +435,14 @@ static inline bool is_b0(struct pci_dev *pdev) static inline bool is_c0(struct pci_dev *pdev) { - if (pdev->revision >= 5) + if (pdev->revision == 5) + return true; + return false; +} + +static inline bool is_c1(struct pci_dev *pdev) +{ + if (pdev->revision >= 6) return true; return false; } diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 0ae0990b39dd..c650d3003c22 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -186,8 +186,11 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, writel(clksm_value, &llr->clock_skew_management); - /* @todo Provide a way to write this register correctly */ - writel(0x02108421, &llr->afe_lookup_table_control); + if (is_c0(ihost->pdev) || is_c1(ihost->pdev)) { + writel(0x04210400, &llr->afe_lookup_table_control); + writel(0x020A7C05, &llr->sas_primitive_timeout); + } else + writel(0x02108421, &llr->afe_lookup_table_control); llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT, (u8)ihost->user_parameters.no_outbound_task_timeout); diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index b5f4341de243..9b8117b9d756 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -147,7 +147,7 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw memcpy(orom, fw->data, fw->size); - if (is_c0(pdev)) + if (is_c0(pdev) || is_c1(pdev)) goto out; /* -- cgit From 594e566ae5985e0cc3185ac21509a86e90aad577 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 4 Jan 2012 01:32:44 -0800 Subject: [SCSI] isci: oem parameter format v1.1 (ssc select) v1.1 allows finer grained tuning of the SSC (spread-spectrum-clocking) settings for SAS and SATA. See notes in probe_roms.h Signed-off-by: Dave Jiang Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/host.c | 47 +++++++++++++++++++++++++++++++++++-- drivers/scsi/isci/init.c | 3 ++- drivers/scsi/isci/phy.c | 51 +++++++++++++++++++++++++++++++++++++++- drivers/scsi/isci/probe_roms.h | 53 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 148 insertions(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 383bb6913087..ed1441c89577 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1759,7 +1759,7 @@ static enum sci_status sci_controller_construct(struct isci_host *ihost, return sci_controller_reset(ihost); } -int sci_oem_parameters_validate(struct sci_oem_params *oem) +int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version) { int i; @@ -1791,18 +1791,61 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem) oem->controller.max_concurr_spin_up < 1) return -EINVAL; + if (oem->controller.do_enable_ssc) { + if (version < ISCI_ROM_VER_1_1 && oem->controller.do_enable_ssc != 1) + return -EINVAL; + + if (version >= ISCI_ROM_VER_1_1) { + u8 test = oem->controller.ssc_sata_tx_spread_level; + + switch (test) { + case 0: + case 2: + case 3: + case 6: + case 7: + break; + default: + return -EINVAL; + } + + test = oem->controller.ssc_sas_tx_spread_level; + if (oem->controller.ssc_sas_tx_type == 0) { + switch (test) { + case 0: + case 2: + case 3: + break; + default: + return -EINVAL; + } + } else if (oem->controller.ssc_sas_tx_type == 1) { + switch (test) { + case 0: + case 3: + case 6: + break; + default: + return -EINVAL; + } + } + } + } + return 0; } static enum sci_status sci_oem_parameters_set(struct isci_host *ihost) { u32 state = ihost->sm.current_state_id; + struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); if (state == SCIC_RESET || state == SCIC_INITIALIZING || state == SCIC_INITIALIZED) { - if (sci_oem_parameters_validate(&ihost->oem_parameters)) + if (sci_oem_parameters_validate(&ihost->oem_parameters, + pci_info->orom->hdr.version)) return SCI_FAILURE_INVALID_PARAMETER_VALUE; return SCI_SUCCESS; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index a97edabcb85a..8a34fd92e42e 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -466,7 +466,8 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic orom = isci_request_oprom(pdev); for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) { - if (sci_oem_parameters_validate(&orom->ctrl[i])) { + if (sci_oem_parameters_validate(&orom->ctrl[i], + orom->hdr.version)) { dev_warn(&pdev->dev, "[%d]: invalid oem parameters detected, falling back to firmware\n", i); devm_kfree(&pdev->dev, orom); diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index c650d3003c22..61000cde84c7 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -144,10 +144,59 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy, phy_cap.gen3_no_ssc = 1; phy_cap.gen2_no_ssc = 1; phy_cap.gen1_no_ssc = 1; - if (ihost->oem_parameters.controller.do_enable_ssc == true) { + if (ihost->oem_parameters.controller.do_enable_ssc) { + struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe; + struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_idx]; + struct isci_pci_info *pci_info = to_pci_info(ihost->pdev); + bool en_sas = false; + bool en_sata = false; + u32 sas_type = 0; + u32 sata_spread = 0x2; + u32 sas_spread = 0x2; + phy_cap.gen3_ssc = 1; phy_cap.gen2_ssc = 1; phy_cap.gen1_ssc = 1; + + if (pci_info->orom->hdr.version < ISCI_ROM_VER_1_1) + en_sas = en_sata = true; + else { + sata_spread = ihost->oem_parameters.controller.ssc_sata_tx_spread_level; + sas_spread = ihost->oem_parameters.controller.ssc_sas_tx_spread_level; + + if (sata_spread) + en_sata = true; + + if (sas_spread) { + en_sas = true; + sas_type = ihost->oem_parameters.controller.ssc_sas_tx_type; + } + + } + + if (en_sas) { + u32 reg; + + reg = readl(&xcvr->afe_xcvr_control0); + reg |= (0x00100000 | (sas_type << 19)); + writel(reg, &xcvr->afe_xcvr_control0); + + reg = readl(&xcvr->afe_tx_ssc_control); + reg |= sas_spread << 8; + writel(reg, &xcvr->afe_tx_ssc_control); + } + + if (en_sata) { + u32 reg; + + reg = readl(&xcvr->afe_tx_ssc_control); + reg |= sata_spread; + writel(reg, &xcvr->afe_tx_ssc_control); + + reg = readl(&llr->stp_control); + reg |= 1 << 12; + writel(reg, &llr->stp_control); + } } /* The SAS specification indicates that the phy_capabilities that diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 2c75248ca326..42dd05414f3b 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -152,7 +152,7 @@ struct sci_user_parameters { #define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4 struct sci_oem_params; -int sci_oem_parameters_validate(struct sci_oem_params *oem); +int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version); struct isci_orom; struct isci_orom *isci_request_oprom(struct pci_dev *pdev); @@ -191,6 +191,10 @@ struct isci_oem_hdr { 0x1a, 0x04, 0xc6) #define ISCI_EFI_VAR_NAME "RstScuO" +#define ISCI_ROM_VER_1_0 0x10 +#define ISCI_ROM_VER_1_1 0x11 +#define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_1 + /* Allowed PORT configuration modes APC Automatic PORT configuration mode is * defined by the OEM configuration parameters providing no PHY_MASK parameters * for any PORT. i.e. There are no phys assigned to any of the ports at start. @@ -220,7 +224,52 @@ struct sci_oem_params { struct { uint8_t mode_type; uint8_t max_concurr_spin_up; - uint8_t do_enable_ssc; + /* + * This bitfield indicates the OEM's desired default Tx + * Spread Spectrum Clocking (SSC) settings for SATA and SAS. + * NOTE: Default SSC Modulation Frequency is 31.5KHz. + */ + union { + struct { + /* + * NOTE: Max spread for SATA is +0 / -5000 PPM. + * Down-spreading SSC (only method allowed for SATA): + * SATA SSC Tx Disabled = 0x0 + * SATA SSC Tx at +0 / -1419 PPM Spread = 0x2 + * SATA SSC Tx at +0 / -2129 PPM Spread = 0x3 + * SATA SSC Tx at +0 / -4257 PPM Spread = 0x6 + * SATA SSC Tx at +0 / -4967 PPM Spread = 0x7 + */ + uint8_t ssc_sata_tx_spread_level:4; + /* + * SAS SSC Tx Disabled = 0x0 + * + * NOTE: Max spread for SAS down-spreading +0 / + * -2300 PPM + * Down-spreading SSC: + * SAS SSC Tx at +0 / -1419 PPM Spread = 0x2 + * SAS SSC Tx at +0 / -2129 PPM Spread = 0x3 + * + * NOTE: Max spread for SAS center-spreading +2300 / + * -2300 PPM + * Center-spreading SSC: + * SAS SSC Tx at +1064 / -1064 PPM Spread = 0x3 + * SAS SSC Tx at +2129 / -2129 PPM Spread = 0x6 + */ + uint8_t ssc_sas_tx_spread_level:3; + /* + * NOTE: Refer to the SSC section of the SAS 2.x + * Specification for proper setting of this field. + * For standard SAS Initiator SAS PHY operation it + * should be 0 for Down-spreading. + * SAS SSC Tx spread type: + * Down-spreading SSC = 0 + * Center-spreading SSC = 1 + */ + uint8_t ssc_sas_tx_type:1; + }; + uint8_t do_enable_ssc; + }; uint8_t reserved; } controller; -- cgit From 9fee607f0b29adabd72265a847b8e421dff10d66 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Wed, 4 Jan 2012 01:32:49 -0800 Subject: [SCSI] isci: oem parameter format v1.3 (cable select) v1.3 allows the attenuation of the attached cables to be specified to the driver in terms of 'short', 'medium', and 'long' (see probe_roms.h). These settings (per phy) are retrieved from the platform oem-parameters (BIOS rom) or via a module parameter override. Reviewed-by: Jiangbi Liu Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/host.c | 43 +++++++++++++++++++++++++++++++++++++++--- drivers/scsi/isci/host.h | 18 ++++++++++++++++++ drivers/scsi/isci/init.c | 16 ++++++++++++++++ drivers/scsi/isci/isci.h | 1 + drivers/scsi/isci/probe_roms.h | 38 +++++++++++++++++++++++++++++++++++-- 5 files changed, 111 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index ed1441c89577..9a52b984620f 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1666,6 +1666,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost /* Default to no SSC operation. */ ihost->oem_parameters.controller.do_enable_ssc = false; + /* Default to short cables on all phys. */ + ihost->oem_parameters.controller.cable_selection_mask = 0; + /* Initialize all of the port parameter information to narrow ports. */ for (index = 0; index < SCI_MAX_PORTS; index++) { ihost->oem_parameters.ports[index].phy_mask = 0; @@ -1953,12 +1956,46 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost, static int is_long_cable(int phy, unsigned char selection_byte) { - return 0; + return !!(selection_byte & (1 << phy)); } static int is_medium_cable(int phy, unsigned char selection_byte) { - return 0; + return !!(selection_byte & (1 << (phy + 4))); +} + +static enum cable_selections decode_selection_byte( + int phy, + unsigned char selection_byte) +{ + return ((selection_byte & (1 << phy)) ? 1 : 0) + + (selection_byte & (1 << (phy + 4)) ? 2 : 0); +} + +static unsigned char *to_cable_select(struct isci_host *ihost) +{ + if (is_cable_select_overridden()) + return ((unsigned char *)&cable_selection_override) + + ihost->id; + else + return &ihost->oem_parameters.controller.cable_selection_mask; +} + +enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy) +{ + return decode_selection_byte(phy, *to_cable_select(ihost)); +} + +char *lookup_cable_names(enum cable_selections selection) +{ + static char *cable_names[] = { + [short_cable] = "short", + [long_cable] = "long", + [medium_cable] = "medium", + [undefined_cable] = "" /* bit 0==1 */ + }; + return (selection <= undefined_cable) ? cable_names[selection] + : cable_names[undefined_cable]; } #define AFE_REGISTER_WRITE_DELAY 10 @@ -1967,10 +2004,10 @@ static void sci_controller_afe_initialization(struct isci_host *ihost) { struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe; const struct sci_oem_params *oem = &ihost->oem_parameters; - unsigned char cable_selection_mask = 0; struct pci_dev *pdev = ihost->pdev; u32 afe_status; u32 phy_id; + unsigned char cable_selection_mask = *to_cable_select(ihost); /* Clear DFX Status registers */ writel(0x0081000f, &afe->afe_dfx_master_control0); diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h index 4573075a6b97..5477f0fa8233 100644 --- a/drivers/scsi/isci/host.h +++ b/drivers/scsi/isci/host.h @@ -447,6 +447,24 @@ static inline bool is_c1(struct pci_dev *pdev) return false; } +enum cable_selections { + short_cable = 0, + long_cable = 1, + medium_cable = 2, + undefined_cable = 3 +}; + +#define CABLE_OVERRIDE_DISABLED (0x10000) + +static inline int is_cable_select_overridden(void) +{ + return cable_selection_override < CABLE_OVERRIDE_DISABLED; +} + +enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy); +void validate_cable_selections(struct isci_host *ihost); +char *lookup_cable_names(enum cable_selections); + /* set hw control for 'activity', even though active enclosures seem to drive * the activity led on their own. Skip setting FSENG control on 'status' due * to unexpected operation and 'error' due to not being a supported automatic diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 8a34fd92e42e..1047108ba4de 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -122,6 +122,14 @@ unsigned char max_concurr_spinup; module_param(max_concurr_spinup, byte, 0); MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup"); +uint cable_selection_override = CABLE_OVERRIDE_DISABLED; +module_param(cable_selection_override, uint, 0); + +MODULE_PARM_DESC(cable_selection_override, + "This field indicates length of the SAS/SATA cable between " + "host and device. If any bits > 15 are set (default) " + "indicates \"use platform defaults\""); + static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf) { struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev); @@ -412,6 +420,14 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) return NULL; isci_host->shost = shost; + dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: " + "{%s, %s, %s, %s}\n", + (is_cable_select_overridden() ? "* " : ""), isci_host->id, + lookup_cable_names(decode_cable_selection(isci_host, 3)), + lookup_cable_names(decode_cable_selection(isci_host, 2)), + lookup_cable_names(decode_cable_selection(isci_host, 1)), + lookup_cable_names(decode_cable_selection(isci_host, 0))); + err = isci_host_init(isci_host); if (err) goto err_shost; diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h index 8efeb6b08321..234ab46fce33 100644 --- a/drivers/scsi/isci/isci.h +++ b/drivers/scsi/isci/isci.h @@ -480,6 +480,7 @@ extern u16 ssp_inactive_to; extern u16 stp_inactive_to; extern unsigned char phy_gen; extern unsigned char max_concurr_spinup; +extern uint cable_selection_override; irqreturn_t isci_msix_isr(int vec, void *data); irqreturn_t isci_intx_isr(int vec, void *data); diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h index 42dd05414f3b..bb0e9d4d97c9 100644 --- a/drivers/scsi/isci/probe_roms.h +++ b/drivers/scsi/isci/probe_roms.h @@ -193,7 +193,8 @@ struct isci_oem_hdr { #define ISCI_ROM_VER_1_0 0x10 #define ISCI_ROM_VER_1_1 0x11 -#define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_1 +#define ISCI_ROM_VER_1_3 0x13 +#define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_3 /* Allowed PORT configuration modes APC Automatic PORT configuration mode is * defined by the OEM configuration parameters providing no PHY_MASK parameters @@ -270,7 +271,40 @@ struct sci_oem_params { }; uint8_t do_enable_ssc; }; - uint8_t reserved; + /* + * This field indicates length of the SAS/SATA cable between + * host and device. + * This field is used make relationship between analog + * parameters of the phy in the silicon and length of the cable. + * Supported cable attenuation levels: + * "short"- up to 3m, "medium"-3m to 6m, and "long"- more than + * 6m. + * + * This is bit mask field: + * + * BIT: (MSB) 7 6 5 4 + * ASSIGNMENT: - Medium cable + * length assignment + * BIT: 3 2 1 0 (LSB) + * ASSIGNMENT: - Long cable length + * assignment + * + * BITS 7-4 are set when the cable length is assigned to medium + * BITS 3-0 are set when the cable length is assigned to long + * + * The BIT positions are clear when the cable length is + * assigned to short. + * + * Setting the bits for both long and medium cable length is + * undefined. + * + * A value of 0x84 would assign + * phy3 - medium + * phy2 - long + * phy1 - short + * phy0 - short + */ + uint8_t cable_selection_mask; } controller; struct { -- cgit From 6024d38b86ecc7943e398ef01b0dc2765870d444 Mon Sep 17 00:00:00 2001 From: Marcin Tomczak Date: Wed, 4 Jan 2012 01:32:54 -0800 Subject: [SCSI] isci: performance-fix, shorten default "no outbound task" timeout "No task timeout timer reduced from 20 to 2 This timer controls how long the SCU hardware will hold open the TX side of the connection before sending a DONE. The timer allows the hardware to attempt to optimize the DONE/CLOSE behavior to allow for new COMMAND IU to be posted. In practice closing the connection quicker is better." Signed-off-by: Marcin Tomczak Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/host.c | 2 +- drivers/scsi/isci/init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 9a52b984620f..670ecb456d48 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1697,7 +1697,7 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost ihost->user_parameters.ssp_inactivity_timeout = 5; ihost->user_parameters.stp_max_occupancy_timeout = 5; ihost->user_parameters.ssp_max_occupancy_timeout = 20; - ihost->user_parameters.no_outbound_task_timeout = 20; + ihost->user_parameters.no_outbound_task_timeout = 2; } static void controller_timeout(unsigned long data) diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 1047108ba4de..3c4ddad97053 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -94,7 +94,7 @@ MODULE_DEVICE_TABLE(pci, isci_id_table); /* linux isci specific settings */ -unsigned char no_outbound_task_to = 20; +unsigned char no_outbound_task_to = 2; module_param(no_outbound_task_to, byte, 0); MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)"); -- cgit From be168a3b89b43b8bb4ef71066e91439d400e20a6 Mon Sep 17 00:00:00 2001 From: Jeff Skirvin Date: Wed, 4 Jan 2012 01:33:00 -0800 Subject: [SCSI] isci: link speeds default to gen 2 Gen-3 operation is marginal, default to gen-2 for now. Signed-off-by: Jeff Skirvin Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/host.c | 5 +++-- drivers/scsi/isci/init.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 670ecb456d48..7e4d709dc201 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -1676,8 +1676,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost /* Initialize all of the phy parameter information. */ for (index = 0; index < SCI_MAX_PHYS; index++) { - /* Default to 6G (i.e. Gen 3) for now. */ - ihost->user_parameters.phys[index].max_speed_generation = 3; + /* Default to 3G (i.e. Gen 2). */ + ihost->user_parameters.phys[index].max_speed_generation = + SCIC_SDS_PARM_GEN2_SPEED; /* the frequencies cannot be 0 */ ihost->user_parameters.phys[index].align_insertion_frequency = 0x7f; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 3c4ddad97053..2bcfb40ae9ad 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -114,7 +114,7 @@ u16 stp_inactive_to = 5; module_param(stp_inactive_to, ushort, 0); MODULE_PARM_DESC(stp_inactive_to, "STP inactivity timeout (100us incr)"); -unsigned char phy_gen = 3; +unsigned char phy_gen = SCIC_SDS_PARM_GEN2_SPEED; module_param(phy_gen, byte, 0); MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)"); -- cgit From 27234ab44f97d85bab062a9d18aaff99addd267d Mon Sep 17 00:00:00 2001 From: Maciej Trela Date: Wed, 4 Jan 2012 01:33:05 -0800 Subject: [SCSI] isci: remove unused 'isci_tmf->device' field As the field was never set, isci_print_tmf() using 'isci_tmf->device' sometimes causes a kernel crash if the dev_dbg() statement is enabled. Remove the unused field both from isci_tmf struct definition and from isci_print_tmf() Signed-off-by: Maciej Trela Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/task.c | 2 +- drivers/scsi/isci/task.h | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 66ad3dc89498..f5a3f7d2bdab 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -496,7 +496,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost, } } - isci_print_tmf(tmf); + isci_print_tmf(ihost, tmf); if (tmf->status == SCI_SUCCESS) ret = TMF_RESP_FUNC_COMPLETE; diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h index bc78c0a41d5c..1b27b3797c6c 100644 --- a/drivers/scsi/isci/task.h +++ b/drivers/scsi/isci/task.h @@ -106,7 +106,6 @@ struct isci_tmf { } resp; unsigned char lun[8]; u16 io_tag; - struct isci_remote_device *device; enum isci_tmf_function_codes tmf_code; int status; @@ -120,10 +119,10 @@ struct isci_tmf { }; -static inline void isci_print_tmf(struct isci_tmf *tmf) +static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf) { if (SAS_PROTOCOL_SATA == tmf->proto) - dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: status = %x\n" "tmf->resp.d2h_fis.status = %x\n" "tmf->resp.d2h_fis.error = %x\n", @@ -132,7 +131,7 @@ static inline void isci_print_tmf(struct isci_tmf *tmf) tmf->resp.d2h_fis.status, tmf->resp.d2h_fis.error); else - dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev, + dev_dbg(&ihost->pdev->dev, "%s: status = %x\n" "tmf->resp.resp_iu.data_present = %x\n" "tmf->resp.resp_iu.status = %x\n" -- cgit From d3fd2e2bc29b1f0979352994f9035359003461c3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 4 Jan 2012 01:33:10 -0800 Subject: [SCSI] isci: update version to 1.1 Bump the version now that the driver has atapi support and the initial round of hotplug fixes. The EXPERIMENTAL tag should have been removed a while back. While we're here also kill the "select SCSI_SAS_HOST_SMP" as the build error was separately fixed by commit d962480e "[SCSI] libsas: fix try_test_sas_gpio_gp_bit() build error". Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 5 ----- drivers/scsi/isci/init.c | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 06ea3bcfdd2a..16570aa84aac 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -830,16 +830,11 @@ config SCSI_ISCI tristate "Intel(R) C600 Series Chipset SAS Controller" depends on PCI && SCSI depends on X86 - # (temporary): known alpha quality driver - depends on EXPERIMENTAL select SCSI_SAS_LIBSAS - select SCSI_SAS_HOST_SMP ---help--- This driver supports the 6Gb/s SAS capabilities of the storage control unit found in the Intel(R) C600 series chipset. - The experimental tag will be removed after the driver exits alpha - config SCSI_GENERIC_NCR5380 tristate "Generic NCR5380/53c400 SCSI PIO support" depends on ISA && SCSI diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 2bcfb40ae9ad..17c4c2c89c2e 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -65,7 +65,7 @@ #include "probe_roms.h" #define MAJ 1 -#define MIN 0 +#define MIN 1 #define BUILD 0 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ __stringify(BUILD) -- cgit From d4ec1cf61fb081a9dde0c0e0b2d0201f4005f937 Mon Sep 17 00:00:00 2001 From: Marcin Tomczak Date: Wed, 4 Jan 2012 01:33:15 -0800 Subject: [SCSI] isci: Fix IO fails when pull cable from phy in x4 wideport in MPC mode. Failure seen pulling a cable from a x4 port configured in manual port configuration (MPC) mode (MPC mode is set by the the OEM paramaters provided by the platform or isci_firmware.bin). While IO running to devices behind and expander, plugging out the cable from phy is causing IO failures and IO drops on disks and never recover. It happens because during link up/down the phy were being taken out of the port. Fix: during link down the phy is kept in the same logical port. Signed-off-by: Marcin Tomczak Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/port.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index ac7f27749f97..4cb071d825bb 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -674,9 +674,13 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy, iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN; - /* Re-assign the phy back to the LP as if it were a narrow port */ - writel(iphy->phy_index, - &iport->port_pe_configuration_register[iphy->phy_index]); + /* Re-assign the phy back to the LP as if it were a narrow port for APC + * mode. For MPC mode, the phy will remain in the port. + */ + if (iport->owning_controller->oem_parameters.controller.mode_type == + SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) + writel(iphy->phy_index, + &iport->port_pe_configuration_register[iphy->phy_index]); if (do_notify_user == true) isci_port_link_down(ihost, iphy, iport); -- cgit From 7e629841b8f8f7bc84d74de994d748b0a3282225 Mon Sep 17 00:00:00 2001 From: Bartek Nowakowski Date: Wed, 4 Jan 2012 01:33:20 -0800 Subject: [SCSI] isci: enable wide port targets Arrange for task_contexts prepared for the wide targets to account for all the attached phys in the port. Signed-off-by: Bartek Nowakowski Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/port.c | 2 +- drivers/scsi/isci/port.h | 4 ++++ drivers/scsi/isci/remote_device.c | 10 +++++++--- 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 4cb071d825bb..49e8a72d1c5b 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -114,7 +114,7 @@ static u32 sci_port_get_phys(struct isci_port *iport) * value is returned if the specified port is not valid. When this value is * returned, no data is copied to the properties output parameter. */ -static enum sci_status sci_port_get_properties(struct isci_port *iport, +enum sci_status sci_port_get_properties(struct isci_port *iport, struct sci_port_properties *prop) { if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT) diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index cb5ffbc38603..b3a7f12803f5 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -250,6 +250,10 @@ bool sci_port_link_detected( struct isci_port *iport, struct isci_phy *iphy); +enum sci_status sci_port_get_properties( + struct isci_port *iport, + struct sci_port_properties *prop); + enum sci_status sci_port_link_up(struct isci_port *iport, struct isci_phy *iphy); enum sci_status sci_port_link_down(struct isci_port *iport, diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index b207cd3b15a0..dd74b6ceeb82 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -53,6 +53,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include #include "isci.h" #include "port.h" #include "remote_device.h" @@ -1101,6 +1102,7 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport, struct isci_remote_device *idev) { enum sci_status status; + struct sci_port_properties properties; struct domain_device *dev = idev->domain_dev; sci_remote_device_construct(iport, idev); @@ -1110,6 +1112,11 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport, * entries will be needed to store the remote node. */ idev->is_direct_attached = true; + + sci_port_get_properties(iport, &properties); + /* Get accurate port width from port's phy mask for a DA device. */ + idev->device_port_width = hweight32(properties.phy_mask); + status = sci_controller_allocate_remote_node_context(iport->owning_controller, idev, &idev->rnc.remote_node_index); @@ -1125,9 +1132,6 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport, idev->connection_rate = sci_port_get_max_allowed_speed(iport); - /* / @todo Should I assign the port width by reading all of the phys on the port? */ - idev->device_port_width = 1; - return SCI_SUCCESS; } -- cgit From 472d4d2cfbc169f3868a5f63ce727a482a2fd487 Mon Sep 17 00:00:00 2001 From: Marcin Tomczak Date: Wed, 4 Jan 2012 01:33:26 -0800 Subject: [SCSI] isci: allow more time for wide port targets When hot insert the wide port device through the mini-sas port, the first IOs (Report Luns or Inquiry) may fail due to the device trying to open to a SCU phy that is still in suspended state. This IO failure causes the wide port device stuck in UPDATING_PORT_WIDTH state. Signed-off-by: Marcin Tomczak Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/port_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index 38a99d281141..37d15d3165da 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -57,7 +57,7 @@ #define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) #define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) -#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100) +#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (250) enum SCIC_SDS_APC_ACTIVITY { SCIC_SDS_APC_SKIP_PHY, -- cgit From be778341812dc75b1c515fab6ebd39c0daf1e2bc Mon Sep 17 00:00:00 2001 From: Marcin Tomczak Date: Wed, 4 Jan 2012 01:33:31 -0800 Subject: [SCSI] isci: fix io failures while wide port links are coming up When the first phy of a wide port comes up, don't report the port ready yet, always wait for 250 miliseconds then config the port with all phys added to the port. So that we can avoid reporting wide port device too early to kernel, which caused the first IOs (report luns, inquirys) failed due to not all the phys are configured into its port. Changes also made that the phys in a wide port don't need to go through half second wait time for consuming power. Signed-off-by: Marcin Tomczak Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/host.c | 59 ++++++++++++++++++++++++++++++++++++++--- drivers/scsi/isci/port_config.c | 33 ++++++++++++++--------- 2 files changed, 76 insertions(+), 16 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c index 7e4d709dc201..1a65d6514237 100644 --- a/drivers/scsi/isci/host.c +++ b/drivers/scsi/isci/host.c @@ -899,7 +899,8 @@ static enum sci_status sci_controller_start_next_phy(struct isci_host *ihost) */ if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) || (iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) || - (iphy->is_in_link_training == true && is_phy_starting(iphy))) { + (iphy->is_in_link_training == true && is_phy_starting(iphy)) || + (ihost->port_agent.phy_ready_mask != ihost->port_agent.phy_configured_mask)) { is_controller_start_complete = false; break; } @@ -1904,6 +1905,31 @@ static void power_control_timeout(unsigned long data) ihost->power_control.phys_waiting--; ihost->power_control.phys_granted_power++; sci_phy_consume_power_handler(iphy); + + if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { + u8 j; + + for (j = 0; j < SCI_MAX_PHYS; j++) { + struct isci_phy *requester = ihost->power_control.requesters[j]; + + /* + * Search the power_control queue to see if there are other phys + * attached to the same remote device. If found, take all of + * them out of await_sas_power state. + */ + if (requester != NULL && requester != iphy) { + u8 other = memcmp(requester->frame_rcvd.iaf.sas_addr, + iphy->frame_rcvd.iaf.sas_addr, + sizeof(requester->frame_rcvd.iaf.sas_addr)); + + if (other == 0) { + ihost->power_control.requesters[j] = NULL; + ihost->power_control.phys_waiting--; + sci_phy_consume_power_handler(requester); + } + } + } + } } /* @@ -1938,9 +1964,34 @@ void sci_controller_power_control_queue_insert(struct isci_host *ihost, ihost->power_control.timer_started = true; } else { - /* Add the phy in the waiting list */ - ihost->power_control.requesters[iphy->phy_index] = iphy; - ihost->power_control.phys_waiting++; + /* + * There are phys, attached to the same sas address as this phy, are + * already in READY state, this phy don't need wait. + */ + u8 i; + struct isci_phy *current_phy; + + for (i = 0; i < SCI_MAX_PHYS; i++) { + u8 other; + current_phy = &ihost->phys[i]; + + other = memcmp(current_phy->frame_rcvd.iaf.sas_addr, + iphy->frame_rcvd.iaf.sas_addr, + sizeof(current_phy->frame_rcvd.iaf.sas_addr)); + + if (current_phy->sm.current_state_id == SCI_PHY_READY && + current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS && + other == 0) { + sci_phy_consume_power_handler(iphy); + break; + } + } + + if (i == SCI_MAX_PHYS) { + /* Add the phy in the waiting list */ + ihost->power_control.requesters[iphy->phy_index] = iphy; + ihost->power_control.phys_waiting++; + } } } diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c index 37d15d3165da..6d1e9544cbe5 100644 --- a/drivers/scsi/isci/port_config.c +++ b/drivers/scsi/isci/port_config.c @@ -466,6 +466,23 @@ sci_apc_agent_validate_phy_configuration(struct isci_host *ihost, return sci_port_configuration_agent_validate_ports(ihost, port_agent); } +/* + * This routine will restart the automatic port configuration timeout + * timer for the next time period. This could be caused by either a link + * down event or a link up event where we can not yet tell to which a phy + * belongs. + */ +static void sci_apc_agent_start_timer( + struct sci_port_configuration_agent *port_agent, + u32 timeout) +{ + if (port_agent->timer_pending) + sci_del_timer(&port_agent->timer); + + port_agent->timer_pending = true; + sci_mod_timer(&port_agent->timer, timeout); +} + static void sci_apc_agent_configure_ports(struct isci_host *ihost, struct sci_port_configuration_agent *port_agent, struct isci_phy *iphy, @@ -565,17 +582,8 @@ static void sci_apc_agent_configure_ports(struct isci_host *ihost, break; case SCIC_SDS_APC_START_TIMER: - /* - * This can occur for either a link down event, or a link - * up event where we cannot yet tell the port to which a - * phy belongs. - */ - if (port_agent->timer_pending) - sci_del_timer(&port_agent->timer); - - port_agent->timer_pending = true; - sci_mod_timer(&port_agent->timer, - SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION); + sci_apc_agent_start_timer(port_agent, + SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION); break; case SCIC_SDS_APC_SKIP_PHY: @@ -607,7 +615,8 @@ static void sci_apc_agent_link_up(struct isci_host *ihost, if (!iport) { /* the phy is not the part of this port */ port_agent->phy_ready_mask |= 1 << phy_index; - sci_apc_agent_configure_ports(ihost, port_agent, iphy, true); + sci_apc_agent_start_timer(port_agent, + SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION); } else { /* the phy is already the part of the port */ u32 port_state = iport->sm.current_state_id; -- cgit From 0953dbea1d9a84c8443b5f5bb45229a6c9d7f9f3 Mon Sep 17 00:00:00 2001 From: Marcin Tomczak Date: Wed, 4 Jan 2012 01:33:36 -0800 Subject: [SCSI] isci: fix start OOB Split scu_link_layer_start_oob function to reset and enable and add flush after all steps. Signed-off-by: Marcin Tomczak Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/phy.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 61000cde84c7..fe18acfd6eb3 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -1098,24 +1098,25 @@ static void scu_link_layer_stop_protocol_engine( writel(enable_spinup_value, &iphy->link_layer_registers->notify_enable_spinup_control); } -/** - * - * - * This method will start the OOB/SN state machine for this struct isci_phy object. - */ -static void scu_link_layer_start_oob( - struct isci_phy *iphy) +static void scu_link_layer_start_oob(struct isci_phy *iphy) { - u32 scu_sas_pcfg_value; - - scu_sas_pcfg_value = - readl(&iphy->link_layer_registers->phy_configuration); - scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); - scu_sas_pcfg_value &= - ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | - SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); - writel(scu_sas_pcfg_value, - &iphy->link_layer_registers->phy_configuration); + struct scu_link_layer_registers __iomem *ll = iphy->link_layer_registers; + u32 val; + + /** Reset OOB sequence - start */ + val = readl(&ll->phy_configuration); + val &= ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | + SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); + writel(val, &ll->phy_configuration); + readl(&ll->phy_configuration); /* flush */ + /** Reset OOB sequence - end */ + + /** Start OOB sequence - start */ + val = readl(&ll->phy_configuration); + val |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); + writel(val, &ll->phy_configuration); + readl(&ll->phy_configuration); /* flush */ + /** Start OOB sequence - end */ } /** -- cgit From 05b080fc933bb068b32fa119db00e8efcc10e3bd Mon Sep 17 00:00:00 2001 From: Marcin Tomczak Date: Wed, 4 Jan 2012 01:33:41 -0800 Subject: [SCSI] isci: fix, prevent port from getting stuck in the 'configuring' state When expander connected in x2 or x4 mode and with IO runnning, if a cable from wideport is plugged out from the phy, IO's start failing on all the targets. Observed that when cable is pulled with IO running, cominit is happening on all the links and IO's start dropping to 0 and eventually the whole IO fails. Second observation, target is trying to open and SCU is responding with "Open reject no destination". A cause of the problem is when the port went from the "ready configuring substate" back to "ready configuring substate" as a result of phy being pulled off, scic suspended the port task scheduler register. As a result no IO was allowed and in the "substate configuring enter" routine the IO never goes back to 0. As a result the port never comes out of "ready substate configuring". The patch adds a mechanism of activate and deactivate phy when a port link up, which fixes the problem. Signed-off-by: Bartek Nowakowski Signed-off-by: Maciej Trela Signed-off-by: Marcin Tomczak Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/isci/port.c | 92 ++++++++++++++++++++++++++---------------------- drivers/scsi/isci/port.h | 6 ++++ 2 files changed, 56 insertions(+), 42 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c index 49e8a72d1c5b..7c6ac58a5c4c 100644 --- a/drivers/scsi/isci/port.c +++ b/drivers/scsi/isci/port.c @@ -647,19 +647,26 @@ void sci_port_setup_transports(struct isci_port *iport, u32 device_id) } } -static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy, - bool do_notify_user) +static void sci_port_resume_phy(struct isci_port *iport, struct isci_phy *iphy) +{ + sci_phy_resume(iphy); + iport->enabled_phy_mask |= 1 << iphy->phy_index; +} + +static void sci_port_activate_phy(struct isci_port *iport, + struct isci_phy *iphy, + u8 flags) { struct isci_host *ihost = iport->owning_controller; - if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) + if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA && (flags & PF_RESUME)) sci_phy_resume(iphy); iport->active_phy_mask |= 1 << iphy->phy_index; sci_controller_clear_invalid_phy(ihost, iphy); - if (do_notify_user == true) + if (flags & PF_NOTIFY) isci_port_link_up(ihost, iport, iphy); } @@ -669,6 +676,7 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy, struct isci_host *ihost = iport->owning_controller; iport->active_phy_mask &= ~(1 << iphy->phy_index); + iport->enabled_phy_mask &= ~(1 << iphy->phy_index); if (!iport->active_phy_mask) iport->last_active_phy = iphy->phy_index; @@ -705,18 +713,16 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i * sci_port_general_link_up_handler - phy can be assigned to port? * @sci_port: sci_port object for which has a phy that has gone link up. * @sci_phy: This is the struct isci_phy object that has gone link up. - * @do_notify_user: This parameter specifies whether to inform the user (via - * sci_port_link_up()) as to the fact that a new phy as become ready. + * @flags: PF_RESUME, PF_NOTIFY to sci_port_activate_phy * - * Determine if this phy can be assigned to this - * port . If the phy is not a valid PHY for - * this port then the function will notify the user. A PHY can only be - * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in - * the same port. none + * Determine if this phy can be assigned to this port . If the phy is + * not a valid PHY for this port then the function will notify the user. + * A PHY can only be part of a port if it's attached SAS ADDRESS is the + * same as all other PHYs in the same port. */ static void sci_port_general_link_up_handler(struct isci_port *iport, - struct isci_phy *iphy, - bool do_notify_user) + struct isci_phy *iphy, + u8 flags) { struct sci_sas_address port_sas_address; struct sci_sas_address phy_sas_address; @@ -734,7 +740,7 @@ static void sci_port_general_link_up_handler(struct isci_port *iport, iport->active_phy_mask == 0) { struct sci_base_state_machine *sm = &iport->sm; - sci_port_activate_phy(iport, iphy, do_notify_user); + sci_port_activate_phy(iport, iphy, flags); if (sm->current_state_id == SCI_PORT_RESETTING) port_state_machine_change(iport, SCI_PORT_READY); } else @@ -785,11 +791,16 @@ bool sci_port_link_detected( struct isci_phy *iphy) { if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) && - (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) && - sci_port_is_wide(iport)) { - sci_port_invalid_link_up(iport, iphy); - - return false; + (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)) { + if (sci_port_is_wide(iport)) { + sci_port_invalid_link_up(iport, iphy); + return false; + } else { + struct isci_host *ihost = iport->owning_controller; + struct isci_port *dst_port = &(ihost->ports[iphy->phy_index]); + writel(iphy->phy_index, + &dst_port->port_pe_configuration_register[iphy->phy_index]); + } } return true; @@ -979,6 +990,13 @@ static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine } } +static void scic_sds_port_ready_substate_waiting_exit( + struct sci_base_state_machine *sm) +{ + struct isci_port *iport = container_of(sm, typeof(*iport), sm); + sci_port_resume_port_task_scheduler(iport); +} + static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm) { u32 index; @@ -992,13 +1010,13 @@ static void sci_port_ready_substate_operational_enter(struct sci_base_state_mach writel(iport->physical_port_index, &iport->port_pe_configuration_register[ iport->phy_table[index]->phy_index]); + if (((iport->active_phy_mask^iport->enabled_phy_mask) & (1 << index)) != 0) + sci_port_resume_phy(iport, iport->phy_table[index]); } } sci_port_update_viit_entry(iport); - sci_port_resume_port_task_scheduler(iport); - /* * Post the dummy task for the port so the hardware can schedule * io correctly @@ -1065,20 +1083,9 @@ static void sci_port_ready_substate_configuring_enter(struct sci_base_state_mach if (iport->active_phy_mask == 0) { isci_port_not_ready(ihost, iport); - port_state_machine_change(iport, - SCI_PORT_SUB_WAITING); - } else if (iport->started_request_count == 0) - port_state_machine_change(iport, - SCI_PORT_SUB_OPERATIONAL); -} - -static void sci_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm) -{ - struct isci_port *iport = container_of(sm, typeof(*iport), sm); - - sci_port_suspend_port_task_scheduler(iport); - if (iport->ready_exit) - sci_port_invalidate_dummy_remote_node(iport); + port_state_machine_change(iport, SCI_PORT_SUB_WAITING); + } else + port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); } enum sci_status sci_port_start(struct isci_port *iport) @@ -1256,7 +1263,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport, if (status != SCI_SUCCESS) return status; - sci_port_general_link_up_handler(iport, iphy, true); + sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME); iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING); @@ -1266,7 +1273,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport, if (status != SCI_SUCCESS) return status; - sci_port_general_link_up_handler(iport, iphy, true); + sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY); /* Re-enter the configuring state since this may be the last phy in * the port. @@ -1342,13 +1349,13 @@ enum sci_status sci_port_link_up(struct isci_port *iport, /* Since this is the first phy going link up for the port we * can just enable it and continue */ - sci_port_activate_phy(iport, iphy, true); + sci_port_activate_phy(iport, iphy, PF_NOTIFY|PF_RESUME); port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL); return SCI_SUCCESS; case SCI_PORT_SUB_OPERATIONAL: - sci_port_general_link_up_handler(iport, iphy, true); + sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME); return SCI_SUCCESS; case SCI_PORT_RESETTING: /* TODO We should make sure that the phy that has gone @@ -1365,7 +1372,7 @@ enum sci_status sci_port_link_up(struct isci_port *iport, /* In the resetting state we don't notify the user regarding * link up and link down notifications. */ - sci_port_general_link_up_handler(iport, iphy, false); + sci_port_general_link_up_handler(iport, iphy, PF_RESUME); return SCI_SUCCESS; default: dev_warn(sciport_to_dev(iport), @@ -1588,14 +1595,14 @@ static const struct sci_base_state sci_port_state_table[] = { }, [SCI_PORT_SUB_WAITING] = { .enter_state = sci_port_ready_substate_waiting_enter, + .exit_state = scic_sds_port_ready_substate_waiting_exit, }, [SCI_PORT_SUB_OPERATIONAL] = { .enter_state = sci_port_ready_substate_operational_enter, .exit_state = sci_port_ready_substate_operational_exit }, [SCI_PORT_SUB_CONFIGURING] = { - .enter_state = sci_port_ready_substate_configuring_enter, - .exit_state = sci_port_ready_substate_configuring_exit + .enter_state = sci_port_ready_substate_configuring_enter }, [SCI_PORT_RESETTING] = { .exit_state = sci_port_resetting_state_exit @@ -1613,6 +1620,7 @@ void sci_port_construct(struct isci_port *iport, u8 index, iport->logical_port_index = SCIC_SDS_DUMMY_PORT; iport->physical_port_index = index; iport->active_phy_mask = 0; + iport->enabled_phy_mask = 0; iport->last_active_phy = 0; iport->ready_exit = false; diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h index b3a7f12803f5..08116090eb70 100644 --- a/drivers/scsi/isci/port.h +++ b/drivers/scsi/isci/port.h @@ -63,6 +63,9 @@ #define SCIC_SDS_DUMMY_PORT 0xFF +#define PF_NOTIFY (1 << 0) +#define PF_RESUME (1 << 1) + struct isci_phy; struct isci_host; @@ -83,6 +86,8 @@ enum isci_status { * @logical_port_index: software port index * @physical_port_index: hardware port index * @active_phy_mask: identifies phy members + * @enabled_phy_mask: phy mask for the port + * that are already part of the port * @reserved_tag: * @reserved_rni: reserver for port task scheduler workaround * @started_request_count: reference count for outstanding commands @@ -104,6 +109,7 @@ struct isci_port { u8 logical_port_index; u8 physical_port_index; u8 active_phy_mask; + u8 enabled_phy_mask; u8 last_active_phy; u16 reserved_rni; u16 reserved_tag; -- cgit From 466c08c71a7dc19528e9b336c5bfa5ec41730c7c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 10 Jan 2012 11:27:01 +0800 Subject: [SCSI] don't change sdev starvation list order without request dispatched The sdev is deleted from starved list and then try to dispatch from this device. It's quite possible the sdev can't eventually dispatch a request, then the sdev will be in starved list tail. This isn't fair. There are two cases here: 1. unplug path. scsi_request_fn() calls to scsi_target_queue_ready(), then the dev is removed from starved list, but quite possible host queue isn't ready, the dev is moved to starved list without dispatching any request. 2. scsi_run_queue path. It deletes the dev from starved list first (both global and local starved lists), then handles the dev. Then we could have the same process like case 1. This patch fixes the first case. Case 2 isn't fixed, because there is a rare case scsi_run_queue finds host isn't busy but scsi_request_fn finds host is busy (other CPU is faster to get host queue depth). Not deleting the dev from starved list in scsi_run_queue will keep scsi_run_queue looping (though this is very rare case, because host will become busy). Fortunately fixing case 1 already gives big improvement for starvation in my test. In a 12 disk JBOD setup, running file creation under EXT4, this gives 12% more throughput. Signed-off-by: Shaohua Li Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f85cfa6c47b5..b2c95dbe9d65 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1316,15 +1316,10 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost, } if (scsi_target_is_busy(starget)) { - if (list_empty(&sdev->starved_entry)) - list_add_tail(&sdev->starved_entry, - &shost->starved_list); + list_move_tail(&sdev->starved_entry, &shost->starved_list); return 0; } - /* We're OK to process the command, so we can't be starved */ - if (!list_empty(&sdev->starved_entry)) - list_del_init(&sdev->starved_entry); return 1; } -- cgit From 7e95fffe080d4dbe826dfe864eb084916cdc6468 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 10 Jan 2012 15:42:34 -0800 Subject: [SCSI] sg: convert to kstrtoul_from_user() Instead of open coding this function use kstrtoul_from_user() directly. Signed-off-by: Stephen Boyd Acked-by: Douglas Gilbert Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 02d99982a74d..eacd46bb36b9 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2368,16 +2368,15 @@ static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer, size_t count, loff_t *off) { - int num; - char buff[11]; + int err; + unsigned long num; if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - num = (count < 10) ? count : 10; - if (copy_from_user(buff, buffer, num)) - return -EFAULT; - buff[num] = '\0'; - sg_allow_dio = simple_strtoul(buff, NULL, 10) ? 1 : 0; + err = kstrtoul_from_user(buffer, count, 0, &num); + if (err) + return err; + sg_allow_dio = num ? 1 : 0; return count; } @@ -2390,17 +2389,15 @@ static ssize_t sg_proc_write_dressz(struct file *filp, const char __user *buffer, size_t count, loff_t *off) { - int num; + int err; unsigned long k = ULONG_MAX; - char buff[11]; if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - num = (count < 10) ? count : 10; - if (copy_from_user(buff, buffer, num)) - return -EFAULT; - buff[num] = '\0'; - k = simple_strtoul(buff, NULL, 10); + + err = kstrtoul_from_user(buffer, count, 0, &k); + if (err) + return err; if (k <= 1048576) { /* limit "big buff" to 1 MB */ sg_big_buff = k; return count; -- cgit From 124dd90f6525ee785b47b59aebadd4a35f797dc1 Mon Sep 17 00:00:00 2001 From: adam radford Date: Tue, 10 Jan 2012 18:07:56 -0800 Subject: [SCSI] megaraid: fix sparse warnings There's a zero day mistake in the megaraid driver in that the code that obtains the version number does a >> 8 on a char quantity. This >>8 causes a sparse warning because it always produces zero. Al Viro suggested these shifts should be >> 4 thus treating the firmware version as a BCD quantity. However, in the interests of safety we've elected to replace the >> 8 quantities with an explicit zero, thus quieting the sparse warning while preserving the same (albeit incorrect) version number as had previously been seen. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 5c1776406c96..15eefa1d61fd 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -306,19 +306,22 @@ mega_query_adapter(adapter_t *adapter) adapter->host->sg_tablesize = adapter->sglen; - /* use HP firmware and bios version encoding */ + /* use HP firmware and bios version encoding + Note: fw_version[0|1] and bios_version[0|1] were originally shifted + right 8 bits making them zero. This 0 value was hardcoded to fix + sparse warnings. */ if (adapter->product_info.subsysvid == HP_SUBSYS_VID) { sprintf (adapter->fw_version, "%c%d%d.%d%d", adapter->product_info.fw_version[2], - adapter->product_info.fw_version[1] >> 8, + 0, adapter->product_info.fw_version[1] & 0x0f, - adapter->product_info.fw_version[0] >> 8, + 0, adapter->product_info.fw_version[0] & 0x0f); sprintf (adapter->bios_version, "%c%d%d.%d%d", adapter->product_info.bios_version[2], - adapter->product_info.bios_version[1] >> 8, + 0, adapter->product_info.bios_version[1] & 0x0f, - adapter->product_info.bios_version[0] >> 8, + 0, adapter->product_info.bios_version[0] & 0x0f); } else { memcpy(adapter->fw_version, -- cgit From 4f77083ed0325ceb9cd5701c0f335583df3dded2 Mon Sep 17 00:00:00 2001 From: Mike Hernandez Date: Wed, 11 Jan 2012 02:44:15 -0800 Subject: [SCSI] qla4xxx: Temperature monitoring for ISP82XX core. During watchdog, need to monitor temperature of ISP82XX core and set device state to FAILED when temperature reaches "Panic" level. Signed-off-by: Mike Hernandez Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 1 + drivers/scsi/qla4xxx/ql4_nx.h | 19 ++++++++++++++++--- drivers/scsi/qla4xxx/ql4_os.c | 42 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 22a3ff02e48a..ec48dc30b9a2 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -671,6 +671,7 @@ struct scsi_qla_host { uint16_t pri_ddb_idx; uint16_t sec_ddb_idx; int is_reset; + uint16_t temperature; }; struct ql4_task_data { diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index 35376a1c3f1b..cfb2f2edac3a 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h @@ -19,12 +19,25 @@ #define PHAN_PEG_RCV_INITIALIZED 0xff01 /*CRB_RELATED*/ -#define QLA82XX_CRB_BASE QLA82XX_CAM_RAM(0x200) -#define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X)) - +#define QLA82XX_CRB_BASE (QLA82XX_CAM_RAM(0x200)) +#define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X)) #define CRB_CMDPEG_STATE QLA82XX_REG(0x50) #define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) #define CRB_DMA_SHIFT QLA82XX_REG(0xcc) +#define CRB_TEMP_STATE QLA82XX_REG(0x1b4) + +#define qla82xx_get_temp_val(x) ((x) >> 16) +#define qla82xx_get_temp_state(x) ((x) & 0xffff) +#define qla82xx_encode_temp(val, state) (((val) << 16) | (state)) + +/* + * Temperature control. + */ +enum { + QLA82XX_TEMP_NORMAL = 0x1, /* Normal operating range */ + QLA82XX_TEMP_WARN, /* Sound alert, temperature getting high */ + QLA82XX_TEMP_PANIC /* Fatal error, hardware has shut down. */ +}; #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 #define QLA82XX_HW_H1_CH_HUB_ADR 0x0E diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 0048a3facd7a..9d3eab513935 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1971,6 +1971,42 @@ mem_alloc_error_exit: return QLA_ERROR; } +/** + * qla4_8xxx_check_temp - Check the ISP82XX temperature. + * @ha: adapter block pointer. + * + * Note: The caller should not hold the idc lock. + **/ +static int qla4_8xxx_check_temp(struct scsi_qla_host *ha) +{ + uint32_t temp, temp_state, temp_val; + int status = QLA_SUCCESS; + + temp = qla4_8xxx_rd_32(ha, CRB_TEMP_STATE); + + temp_state = qla82xx_get_temp_state(temp); + temp_val = qla82xx_get_temp_val(temp); + + if (temp_state == QLA82XX_TEMP_PANIC) { + ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C" + " exceeds maximum allowed. Hardware has been shut" + " down.\n", temp_val); + status = QLA_ERROR; + } else if (temp_state == QLA82XX_TEMP_WARN) { + if (ha->temperature == QLA82XX_TEMP_NORMAL) + ql4_printk(KERN_WARNING, ha, "Device temperature %d" + " degrees C exceeds operating range." + " Immediate action needed.\n", temp_val); + } else { + if (ha->temperature == QLA82XX_TEMP_WARN) + ql4_printk(KERN_INFO, ha, "Device temperature is" + " now %d degrees C in normal range.\n", + temp_val); + } + ha->temperature = temp_state; + return status; +} + /** * qla4_8xxx_check_fw_alive - Check firmware health * @ha: Pointer to host adapter structure. @@ -2042,7 +2078,11 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) test_bit(DPC_RESET_HA, &ha->dpc_flags) || test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); - if (dev_state == QLA82XX_DEV_NEED_RESET && + + if (qla4_8xxx_check_temp(ha)) { + set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); + qla4xxx_wake_dpc(ha); + } else if (dev_state == QLA82XX_DEV_NEED_RESET && !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { if (!ql4xdontresethba) { ql4_printk(KERN_INFO, ha, "%s: HW State: " -- cgit From e6bd0ebd4a8ba9118e970c0214e912e35895c92b Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Wed, 11 Jan 2012 02:44:16 -0800 Subject: [SCSI] qla4xxx: Disable generating pause frames in case of FW hung In case of FW hung ISP82xx generates continuous pause frames which causes switch to disable port. Added fix to disable generating pause frames in case of FW hung Signed-off-by: Giridhar Malavali Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_mbx.c | 7 +++++++ drivers/scsi/qla4xxx/ql4_nx.h | 3 +++ drivers/scsi/qla4xxx/ql4_os.c | 10 ++++++++++ 3 files changed, 20 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index c2593782fbbe..e1e66a45e4d0 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -219,6 +219,13 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, ha->mailbox_timeout_count++; mbx_sts[0] = (-1); set_bit(DPC_RESET_HA, &ha->dpc_flags); + if (is_qla8022(ha)) { + ql4_printk(KERN_INFO, ha, + "disabling pause transmit on port 0 & 1.\n"); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, + CRB_NIU_XG_PAUSE_CTL_P0 | + CRB_NIU_XG_PAUSE_CTL_P1); + } goto mbox_exit; } diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index cfb2f2edac3a..dc45ac923691 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h @@ -39,6 +39,9 @@ enum { QLA82XX_TEMP_PANIC /* Fatal error, hardware has shut down. */ }; +#define CRB_NIU_XG_PAUSE_CTL_P0 0x1 +#define CRB_NIU_XG_PAUSE_CTL_P1 0x8 + #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 #define QLA82XX_HW_H1_CH_HUB_ADR 0x0E #define QLA82XX_HW_H2_CH_HUB_ADR 0x03 diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 9d3eab513935..e2ef7762dc24 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2080,6 +2080,11 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); if (qla4_8xxx_check_temp(ha)) { + ql4_printk(KERN_INFO, ha, "disabling pause" + " transmit on port 0 & 1.\n"); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, + CRB_NIU_XG_PAUSE_CTL_P0 | + CRB_NIU_XG_PAUSE_CTL_P1); set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); qla4xxx_wake_dpc(ha); } else if (dev_state == QLA82XX_DEV_NEED_RESET && @@ -2099,6 +2104,11 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) } else { /* Check firmware health */ if (qla4_8xxx_check_fw_alive(ha)) { + ql4_printk(KERN_INFO, ha, "disabling pause" + " transmit on port 0 & 1.\n"); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, + CRB_NIU_XG_PAUSE_CTL_P0 | + CRB_NIU_XG_PAUSE_CTL_P1); halt_status = qla4_8xxx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); -- cgit From 527c8b2e962d21baa38a96b22e1bf50a47fdf4fb Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Wed, 11 Jan 2012 02:44:17 -0800 Subject: [SCSI] qla4xxx: Added error logging for firmware abort Added debug print with error code in case of firmware error. Signed-off-by: Nilesh Javali Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 2 ++ drivers/scsi/qla4xxx/ql4_os.c | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index ec48dc30b9a2..bfe68545203f 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -150,6 +150,8 @@ #define QL4_SESS_RECOVERY_TMO 120 /* iSCSI session */ /* recovery timeout */ +#define MSB(x) ((uint8_t)((uint16_t)(x) >> 8)) +#define LSW(x) ((uint16_t)(x)) #define LSDW(x) ((u32)((u64)(x))) #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index e2ef7762dc24..b75590af8ed3 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2112,6 +2112,13 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) halt_status = qla4_8xxx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); + if (LSW(MSB(halt_status)) == 0x67) + ql4_printk(KERN_ERR, ha, "%s:" + " Firmware aborted with" + " error code 0x00006700." + " Device is being reset\n", + __func__); + /* Since we cannot change dev_state in interrupt * context, set appropriate DPC flag then wakeup * DPC */ -- cgit From 787649993230eb1d6fc326f13be285a840092538 Mon Sep 17 00:00:00 2001 From: Sarang Radke Date: Wed, 11 Jan 2012 02:44:18 -0800 Subject: [SCSI] qla4xxx: Clear the RISC interrupt bit during FW init This patch fix kernel panic during kdump. Signed-off-by: Sarang Radke Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 3 +++ drivers/scsi/qla4xxx/ql4_nx.c | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 1bdfa8120ac8..90614f38b55d 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -697,6 +697,9 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha) writel(set_rmask(CSR_SCSI_PROCESSOR_INTR), &ha->reg->ctrl_status); readl(&ha->reg->ctrl_status); + writel(set_rmask(CSR_SCSI_COMPLETION_INTR), + &ha->reg->ctrl_status); + readl(&ha->reg->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s: Get firmware " diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 8d6bc1b2ff17..78f1111158d7 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1875,6 +1875,11 @@ exit: int qla4_8xxx_load_risc(struct scsi_qla_host *ha) { int retval; + + /* clear the interrupt */ + writel(0, &ha->qla4_8xxx_reg->host_int); + readl(&ha->qla4_8xxx_reg->host_int); + retval = qla4_8xxx_device_state_handler(ha); if (retval == QLA_SUCCESS && !test_bit(AF_INIT_DONE, &ha->flags)) -- cgit From a4e8a715a39e5d29f7d35a7289b914ef205a866b Mon Sep 17 00:00:00 2001 From: Karen Higgins Date: Wed, 11 Jan 2012 02:44:20 -0800 Subject: [SCSI] qla4xxx: Cleanup modinfo display Beautify modinfo display. Display correct info for ql4xextended_error_logging [jejb: fixup checkpatch warning] Signed-off-by: Karen Higgins Signed-off-by: Vikas Chaudhary Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index b75590af8ed3..ce6d3b7f0c61 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -35,43 +35,44 @@ static struct kmem_cache *srb_cachep; int ql4xdisablesysfsboot = 1; module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql4xdisablesysfsboot, - "Set to disable exporting boot targets to sysfs\n" - " 0 - Export boot targets\n" - " 1 - Do not export boot targets (Default)"); + " Set to disable exporting boot targets to sysfs.\n" + "\t\t 0 - Export boot targets\n" + "\t\t 1 - Do not export boot targets (Default)"); int ql4xdontresethba = 0; module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql4xdontresethba, - "Don't reset the HBA for driver recovery \n" - " 0 - It will reset HBA (Default)\n" - " 1 - It will NOT reset HBA"); + " Don't reset the HBA for driver recovery.\n" + "\t\t 0 - It will reset HBA (Default)\n" + "\t\t 1 - It will NOT reset HBA"); -int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */ +int ql4xextended_error_logging; module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql4xextended_error_logging, - "Option to enable extended error logging, " - "Default is 0 - no logging, 1 - debug logging"); + " Option to enable extended error logging.\n" + "\t\t 0 - no logging (Default)\n" + "\t\t 2 - debug logging"); int ql4xenablemsix = 1; module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ql4xenablemsix, - "Set to enable MSI or MSI-X interrupt mechanism.\n" - " 0 = enable INTx interrupt mechanism.\n" - " 1 = enable MSI-X interrupt mechanism (Default).\n" - " 2 = enable MSI interrupt mechanism."); + " Set to enable MSI or MSI-X interrupt mechanism.\n" + "\t\t 0 = enable INTx interrupt mechanism.\n" + "\t\t 1 = enable MSI-X interrupt mechanism (Default).\n" + "\t\t 2 = enable MSI interrupt mechanism."); #define QL4_DEF_QDEPTH 32 static int ql4xmaxqdepth = QL4_DEF_QDEPTH; module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql4xmaxqdepth, - "Maximum queue depth to report for target devices.\n" - " Default: 32."); + " Maximum queue depth to report for target devices.\n" + "\t\t Default: 32."); static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; module_param(ql4xsess_recovery_tmo, int, S_IRUGO); MODULE_PARM_DESC(ql4xsess_recovery_tmo, "Target Session Recovery Timeout.\n" - " Default: 120 sec."); + "\t\t Default: 120 sec."); static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); /* -- cgit From 19b628dfc60eda4459b65e4b6b7a748932d28929 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Wed, 11 Jan 2012 02:44:21 -0800 Subject: [SCSI] qla4xxx: Update driver version to 5.02.00-k12 Signed-off-by: Vikas Chaudhary Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 7d04eb05c45e..133989b3a9f4 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k11" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k12" -- cgit From a762dce41cb5742a143f6aa2d80ee1aac7e1f5eb Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 13 Jan 2012 17:26:15 -0800 Subject: [SCSI] fcoe: fix regression on offload em matching function for initiator/target This is a regression introduced by commit 1ff9918b625457ce20d450d00f9ed0a12ba191b7 The else statement here is breaking the initiator logic of allocating xid from the offloaded em xid pool for READ I/O only to use DDP, as shown by the snippet of trace below, where the WRITE is using xid 0x5 from the offloaded em xid pool: Protocol VID Len S_ID D_ID OX_ID RX_ID Summary .. *FCP 228 96 0b.08.01 -> 01.0f.00 0x0005 0xffff SCSI: Write(10) LUN: 0x00 FCP 228 76 01.0f.00 -> 0b.08.01 0x0005 0x828d XFER_RDY ... The bug is in the else statement, for both initiator and target, the new command will have FC frame header bit 23 (FC_FC_EX_CTX) cleared as it was originated from the initiator. Also, this is assuming the frame header is already filled up, which is only true for target since for initiator, this is a new frame and oem_match gets called when em tries get xid for this i/o before it is filled up and sent out. The fix is to check if there is a fc_fcp_pkt associated w/ this frame from fr_fsp(fp), since fr_fsp(fp) is NULL for tcm_fc target and non-I/O frame in initiator. This should also return true for target only if it is an FC_RCTL_DD_UNSOL_CMD and rx_id is not allocated. Signed-off-by: Yi Zou Tested-by: Ross Brattain Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index e535f95e4772..507504b77880 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -756,11 +756,12 @@ bool fcoe_oem_match(struct fc_frame *fp) if (fc_fcp_is_read(fr_fsp(fp)) && (fr_fsp(fp)->data_len > fcoe_ddp_min)) return true; - else if (!(ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)) { + else if ((fr_fsp(fp) == NULL) && + (fh->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD) && + (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)) { fcp = fc_frame_payload_get(fp, sizeof(*fcp)); - if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN && - fcp && (ntohl(fcp->fc_dl) > fcoe_ddp_min) && - (fcp->fc_flags & FCP_CFL_WRDATA)) + if ((fcp->fc_flags & FCP_CFL_WRDATA) && + (ntohl(fcp->fc_dl) > fcoe_ddp_min)) return true; } return false; -- cgit From c6b21c93c1794113c68f3d43f321968191d87b1b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 13 Jan 2012 17:26:20 -0800 Subject: [SCSI] libfc: Declare local functions static Avoid that sparse complains about missing declarations for local functions by declaring these static or by adding an #include directive. Add the __percpu annotation where it is missing. Signed-off-by: Bart Van Assche Reviewed-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 6 +++--- drivers/scsi/libfc/fc_elsct.c | 1 + drivers/scsi/libfc/fc_exch.c | 2 +- drivers/scsi/libfc/fc_lport.c | 5 +++-- drivers/scsi/libfc/fc_rport.c | 10 +++++----- 5 files changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 7269e928824a..1d1b0c9da29b 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -61,7 +61,7 @@ static void fc_disc_restart(struct fc_disc *); * Locking Note: This function expects that the lport mutex is locked before * calling it. */ -void fc_disc_stop_rports(struct fc_disc *disc) +static void fc_disc_stop_rports(struct fc_disc *disc) { struct fc_lport *lport; struct fc_rport_priv *rdata; @@ -682,7 +682,7 @@ static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp) * fc_disc_stop() - Stop discovery for a given lport * @lport: The local port that discovery should stop on */ -void fc_disc_stop(struct fc_lport *lport) +static void fc_disc_stop(struct fc_lport *lport) { struct fc_disc *disc = &lport->disc; @@ -698,7 +698,7 @@ void fc_disc_stop(struct fc_lport *lport) * This function will block until discovery has been * completely stopped and all rports have been deleted. */ -void fc_disc_stop_final(struct fc_lport *lport) +static void fc_disc_stop_final(struct fc_lport *lport) { fc_disc_stop(lport); lport->tt.rport_flush_queue(); diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index fb9161dc4ca6..e17a28d324d0 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -28,6 +28,7 @@ #include #include #include +#include "fc_libfc.h" /** * fc_elsct_send() - Send an ELS or CT frame diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 9de9db27e874..4d70d96fa5dc 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -91,7 +91,7 @@ struct fc_exch_pool { * It manages the allocation of exchange IDs. */ struct fc_exch_mgr { - struct fc_exch_pool *pool; + struct fc_exch_pool __percpu *pool; mempool_t *ep_pool; enum fc_class class; struct kref kref; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index e77094a587ed..83750ebb527f 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -677,7 +677,8 @@ EXPORT_SYMBOL(fc_set_mfs); * @lport: The local port receiving the event * @event: The discovery event */ -void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) +static void fc_lport_disc_callback(struct fc_lport *lport, + enum fc_disc_event event) { switch (event) { case DISC_EV_SUCCESS: @@ -1568,7 +1569,7 @@ EXPORT_SYMBOL(fc_lport_flogi_resp); * Locking Note: The lport lock is expected to be held before calling * this routine. */ -void fc_lport_enter_flogi(struct fc_lport *lport) +static void fc_lport_enter_flogi(struct fc_lport *lport) { struct fc_frame *fp; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index b9e434844a69..83aa1efec875 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -391,7 +391,7 @@ static void fc_rport_work(struct work_struct *work) * If it appears we are already logged in, ADISC is used to verify * the setup. */ -int fc_rport_login(struct fc_rport_priv *rdata) +static int fc_rport_login(struct fc_rport_priv *rdata) { mutex_lock(&rdata->rp_mutex); @@ -451,7 +451,7 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, * function will hold the rport lock, call an _enter_* * function and then unlock the rport. */ -int fc_rport_logoff(struct fc_rport_priv *rdata) +static int fc_rport_logoff(struct fc_rport_priv *rdata) { mutex_lock(&rdata->rp_mutex); @@ -653,8 +653,8 @@ static int fc_rport_login_complete(struct fc_rport_priv *rdata, * @fp: The FLOGI response frame * @rp_arg: The remote port that received the FLOGI response */ -void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, - void *rp_arg) +static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, + void *rp_arg) { struct fc_rport_priv *rdata = rp_arg; struct fc_lport *lport = rdata->local_port; @@ -1520,7 +1520,7 @@ reject: * * Locking Note: Called with the lport lock held. */ -void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) +static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) { struct fc_seq_els_data els_data; -- cgit From 7c9c684160bc2c6668abbd2701b440e18bb9ef35 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 13 Jan 2012 17:26:25 -0800 Subject: [SCSI] fcoe: Move fcoe_debug_logging from fcoe.h to fcoe.c Move the definition of the global variable fcoe_debug_logging from fcoe.h to fcoe.c. Avoid that sparse complains about missing declarations for local functions or variables by declaring these static. Signed-off-by: Bart Van Assche Reviewed-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 34 +++++++++++++++++++--------------- drivers/scsi/fcoe/fcoe.h | 4 +--- 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 507504b77880..e9599600aa23 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -58,7 +58,11 @@ module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \ "Direct Data Placement (DDP)."); -DEFINE_MUTEX(fcoe_config_mutex); +unsigned int fcoe_debug_logging; +module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); + +static DEFINE_MUTEX(fcoe_config_mutex); static struct workqueue_struct *fcoe_wq; @@ -67,8 +71,8 @@ static DECLARE_COMPLETION(fcoe_flush_completion); /* fcoe host list */ /* must only by accessed under the RTNL mutex */ -LIST_HEAD(fcoe_hostlist); -DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); +static LIST_HEAD(fcoe_hostlist); +static DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); /* Function Prototypes */ static int fcoe_reset(struct Scsi_Host *); @@ -157,7 +161,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = { .lport_set_port_id = fcoe_set_port_id, }; -struct fc_function_template fcoe_nport_fc_functions = { +static struct fc_function_template fcoe_nport_fc_functions = { .show_host_node_name = 1, .show_host_port_name = 1, .show_host_supported_classes = 1, @@ -197,7 +201,7 @@ struct fc_function_template fcoe_nport_fc_functions = { .bsg_request = fc_lport_bsg_request, }; -struct fc_function_template fcoe_vport_fc_functions = { +static struct fc_function_template fcoe_vport_fc_functions = { .show_host_node_name = 1, .show_host_port_name = 1, .show_host_supported_classes = 1, @@ -433,7 +437,7 @@ static inline void fcoe_interface_put(struct fcoe_interface *fcoe) * * Caller must be holding the RTNL mutex */ -void fcoe_interface_cleanup(struct fcoe_interface *fcoe) +static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) { struct net_device *netdev = fcoe->netdev; struct fcoe_ctlr *fip = &fcoe->ctlr; @@ -748,7 +752,7 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev) * * Returns: True for read types I/O, otherwise returns false. */ -bool fcoe_oem_match(struct fc_frame *fp) +static bool fcoe_oem_match(struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); struct fcp_cmnd *fcp; @@ -1107,7 +1111,7 @@ static int __init fcoe_if_init(void) * * Returns: 0 on success */ -int __exit fcoe_if_exit(void) +static int __exit fcoe_if_exit(void) { fc_release_transport(fcoe_nport_scsi_transport); fc_release_transport(fcoe_vport_scsi_transport); @@ -1296,7 +1300,7 @@ static inline unsigned int fcoe_select_cpu(void) * * Returns: 0 for success */ -int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, +static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, struct packet_type *ptype, struct net_device *olddev) { struct fc_lport *lport; @@ -1452,7 +1456,7 @@ static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen) * * Return: 0 for success */ -int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) +static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) { int wlen; u32 crc; @@ -1728,7 +1732,7 @@ drop: * * Return: 0 for success */ -int fcoe_percpu_receive_thread(void *arg) +static int fcoe_percpu_receive_thread(void *arg) { struct fcoe_percpu_s *p = arg; struct sk_buff *skb; @@ -2146,7 +2150,7 @@ out_nortnl: * Returns: 0 if the ethtool query was successful * -1 if the ethtool query failed */ -int fcoe_link_speed_update(struct fc_lport *lport) +static int fcoe_link_speed_update(struct fc_lport *lport) { struct net_device *netdev = fcoe_netdev(lport); struct ethtool_cmd ecmd; @@ -2180,7 +2184,7 @@ int fcoe_link_speed_update(struct fc_lport *lport) * Returns: 0 if link is UP and OK, -1 if not * */ -int fcoe_link_ok(struct fc_lport *lport) +static int fcoe_link_ok(struct fc_lport *lport) { struct net_device *netdev = fcoe_netdev(lport); @@ -2200,7 +2204,7 @@ int fcoe_link_ok(struct fc_lport *lport) * there no packets that will be handled by the lport, but also that any * threads already handling packet have returned. */ -void fcoe_percpu_clean(struct fc_lport *lport) +static void fcoe_percpu_clean(struct fc_lport *lport) { struct fcoe_percpu_s *pp; struct fcoe_rcv_info *fr; @@ -2251,7 +2255,7 @@ void fcoe_percpu_clean(struct fc_lport *lport) * * Returns: Always 0 (return value required by FC transport template) */ -int fcoe_reset(struct Scsi_Host *shost) +static int fcoe_reset(struct Scsi_Host *shost) { struct fc_lport *lport = shost_priv(shost); struct fcoe_port *port = lport_priv(lport); diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index 6c6884bcf840..bcc89e639495 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h @@ -40,9 +40,7 @@ #define FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */ #define FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */ -unsigned int fcoe_debug_logging; -module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); +extern unsigned int fcoe_debug_logging; #define FCOE_LOGGING 0x01 /* General logging, not categorized */ #define FCOE_NETDEV_LOGGING 0x02 /* Netdevice logging */ -- cgit From 76ffe8a3f766358a0ade543153625b3e4e66159d Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 13 Jan 2012 17:26:30 -0800 Subject: [SCSI] libfc: remove redundant timer init for fcp The fcp timer is already initialized when it gets allocated. Signed-off-by: Yi Zou Tested-by: Ross Brattain Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 221875ec3d7c..f607314810ac 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -155,6 +155,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp) fsp->xfer_ddp = FC_XID_UNKNOWN; atomic_set(&fsp->ref_cnt, 1); init_timer(&fsp->timer); + fsp->timer.data = (unsigned long)fsp; INIT_LIST_HEAD(&fsp->list); spin_lock_init(&fsp->scsi_pkt_lock); } @@ -1850,9 +1851,6 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd) } put_cpu(); - init_timer(&fsp->timer); - fsp->timer.data = (unsigned long)fsp; - /* * send it to the lower layer * if we get -1 return then put the request in the pending -- cgit From 37be2c86f0fbd89b66792008767e688c819b7c32 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 24 Oct 2011 01:11:23 +1100 Subject: mac_scsi: dont enable mac_scsi irq before requesting it Don't enable the SCSI irq when initialising the chip -- the irq has no handler yet. Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/scsi/mac_scsi.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index af3a6af97cc7..737d526c0813 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -340,9 +340,6 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance) printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." ); - /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ - disable_irq(IRQ_MAC_SCSI); - /* get in phase */ NCR5380_write( TARGET_COMMAND_REG, PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); @@ -358,9 +355,6 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance) for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); ) barrier(); - /* switch on SCSI IRQ again */ - enable_irq(IRQ_MAC_SCSI); - printk(KERN_INFO " done\n" ); } #endif -- cgit From c808d3d839ab70c87a6c9356c50569c87661378e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 24 Oct 2011 01:11:24 +1100 Subject: mac_esp: rename irq Rename the "Mac ESP" irq as "ESP" to be consistent with all the other Mac drivers and ESP drivers. Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/scsi/mac_esp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index 4ceeace80453..70eb1f79b1ba 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -565,8 +565,7 @@ static int __devinit esp_mac_probe(struct platform_device *dev) esp_chips[dev->id] = esp; mb(); if (esp_chips[!dev->id] == NULL) { - err = request_irq(host->irq, mac_scsi_esp_intr, 0, - "Mac ESP", NULL); + err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL); if (err < 0) { esp_chips[dev->id] = NULL; goto fail_free_priv; -- cgit