[PATCH 42/43] qla2xxx: Serialize session free in qlt_free_session_done
From: Quinn TranAdd free_pending flag to serialize queueing of free_work element onto the work queue Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h| 1 + drivers/scsi/qla2xxx/qla_target.c | 13 + 2 files changed, 14 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 0c31c8ad0c1e..3feb843ef333 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2384,6 +2384,7 @@ typedef struct fc_port { unsigned int conf_compl_supported:1; unsigned int deleted:2; + unsigned int free_pending:1; unsigned int local:1; unsigned int logout_on_delete:1; unsigned int logo_ack_needed:1; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 814dfb1036de..225b88c47505 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1105,6 +1105,7 @@ static void qlt_free_session_done(struct work_struct *work) sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] = NULL; } } + spin_unlock_irqrestore(>tgt.sess_lock, flags); ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001, @@ -1118,6 +1119,9 @@ static void qlt_free_session_done(struct work_struct *work) wake_up_all(>fcport_waitQ); base_vha = pci_get_drvdata(ha->pdev); + + sess->free_pending = 0; + if (test_bit(PFLG_DRIVER_REMOVING, _vha->pci_flags)) return; @@ -1140,11 +1144,20 @@ static void qlt_free_session_done(struct work_struct *work) void qlt_unreg_sess(struct fc_port *sess) { struct scsi_qla_host *vha = sess->vha; + unsigned long flags; ql_dbg(ql_dbg_disc, sess->vha, 0x210a, "%s sess %p for deletion %8phC\n", __func__, sess, sess->port_name); + spin_lock_irqsave(>vha->work_lock, flags); + if (sess->free_pending) { + spin_unlock_irqrestore(>vha->work_lock, flags); + return; + } + sess->free_pending = 1; + spin_unlock_irqrestore(>vha->work_lock, flags); + if (sess->se_sess) vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); -- 2.12.0
[PATCH 41/43] qla2xxx: Serialize session deletion by using work_lock
From: Quinn Tranfor session deletion, replace sess_lock with work_lock. Under certain case sess_lock is not feasiable to acquire. The lock is needed temporarily to make sure a single call to schedule of the work element. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_gbl.h| 1 - drivers/scsi/qla2xxx/qla_gs.c | 14 ++ drivers/scsi/qla2xxx/qla_init.c | 9 +++-- drivers/scsi/qla2xxx/qla_isr.c| 4 ++-- drivers/scsi/qla2xxx/qla_mbx.c| 2 +- drivers/scsi/qla2xxx/qla_os.c | 5 ++--- drivers/scsi/qla2xxx/qla_target.c | 29 ++--- 7 files changed, 28 insertions(+), 36 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index ab8ffd7933c9..733906cb6c69 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -889,7 +889,6 @@ void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *, struct fc_port *, enum qlt_plogi_link_t); void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *); extern void qlt_schedule_sess_for_deletion(struct fc_port *); -extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *); extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *, uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **); void qla24xx_delete_sess_fn(struct work_struct *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index dd02cbfd0fb1..f26d680fe6c1 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3096,7 +3096,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea) ql_dbg(ql_dbg_disc, vha, 0x2021, "%s %d %8phC post del sess\n", __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion_lock(fcport); + qlt_schedule_sess_for_deletion(fcport); } } } else { /* ea->sp->gen1 != fcport->rscn_gen */ @@ -3113,7 +3113,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea) ql_dbg(ql_dbg_disc, vha, 0x2042, "%s %d %8phC post del sess\n", __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion_lock(fcport); + qlt_schedule_sess_for_deletion(fcport); } else { ql_dbg(ql_dbg_disc, vha, 0x2045, "%s %d %8phC login\n", __func__, __LINE__, @@ -3485,8 +3485,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) "%s %d %8phC post del sess\n", __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion_lock - (fcport); + qlt_schedule_sess_for_deletion(fcport); break; } } @@ -3519,7 +3518,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) "%s %d %8phC post del sess\n", __func__, __LINE__, conflict->port_name); - qlt_schedule_sess_for_deletion_lock + qlt_schedule_sess_for_deletion (conflict); break; } @@ -3577,7 +3576,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) "%s %d %8phC post del sess\n", __func__, __LINE__, conflict->port_name); - qlt_schedule_sess_for_deletion_lock + qlt_schedule_sess_for_deletion (conflict); break; } @@ -4008,8 +4007,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
[PATCH 35/43] qla2xxx: Add retry limit for fabric scan logic
From: Quinn TranSwitch scan is assumed to succeed most of the time. If the scan failed, then scan is limit 5 retries. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 2 ++ drivers/scsi/qla2xxx/qla_gs.c | 33 - drivers/scsi/qla2xxx/qla_isr.c | 1 + 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index f061483475ce..3811ccd1c60b 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3036,6 +3036,8 @@ struct fab_scan_rp { struct fab_scan { struct fab_scan_rp *l; u32 size; + u16 scan_retry; +#define MAX_SCAN_RETRIES 5 enum scan_flags_t scan_flags; struct delayed_work scan_work; }; diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 903f924f6273..8256b65e9e7a 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3924,13 +3924,17 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) rc = sp->rc; if (rc) { - ql_dbg(ql_dbg_disc, vha, 0x, - "GPNFT failed. FC4type %x. Rescanning.\n", - fc4type); - set_bit(LOCAL_LOOP_UPDATE, >dpc_flags); - set_bit(LOOP_RESYNC_NEEDED, >dpc_flags); + vha->scan.scan_retry++; + if (vha->scan.scan_retry < MAX_SCAN_RETRIES) { + set_bit(LOCAL_LOOP_UPDATE, >dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, >dpc_flags); + } else { + ql_dbg(ql_dbg_disc, vha, 0x, + "Fabric scan failed on all retries.\n"); + } goto out; } + vha->scan.scan_retry = 0; list_for_each_entry(fcport, >vp_fcports, list) fcport->scan_state = QLA_FCPORT_SCAN; @@ -4013,7 +4017,6 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) out: qla24xx_sp_unmap(vha, sp); - spin_lock_irqsave(>work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; spin_unlock_irqrestore(>work_lock, flags); @@ -4041,16 +4044,20 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) if (res) { unsigned long flags; - ql_dbg(ql_dbg_disc, sp->vha, 0x, - "Async done-%s timed out.\n", - sp->name); sp->free(sp); spin_lock_irqsave(>work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; - spin_unlock_irqrestore(>work_lock, flags); - set_bit(LOCAL_LOOP_UPDATE, >dpc_flags); - set_bit(LOOP_RESYNC_NEEDED, >dpc_flags); - qla2xxx_wake_dpc(vha); + vha->scan.scan_retry++; + + if (vha->scan.scan_retry < MAX_SCAN_RETRIES) { + set_bit(LOCAL_LOOP_UPDATE, >dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, >dpc_flags); + qla2xxx_wake_dpc(vha); + } else { + ql_dbg(ql_dbg_disc, sp->vha, 0x, + "Async done-%s rescan failed on all retries\n", + sp->name); + } return; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index f02c98b3e8a7..6974657dd8c6 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1059,6 +1059,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) * Mark all devices as missing so we will login again. */ atomic_set(>loop_state, LOOP_UP); + vha->scan.scan_retry = 0; set_bit(LOOP_RESYNC_NEEDED, >dpc_flags); set_bit(LOCAL_LOOP_UPDATE, >dpc_flags); -- 2.12.0
[PATCH 36/43] qla2xxx: Add counters for Exchange Buffer to debugfs
From: Anil GurumurthySigned-off-by: Anil Gurumurthy Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_dfs.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index 4f0415e158cb..c05ebc6ebe78 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -143,6 +143,15 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) seq_printf(s, "Current IOCB count[%d]\n", mb[10]); seq_printf(s, "MAX VP count[%d]\n", mb[11]); seq_printf(s, "MAX FCF count[%d]\n", mb[12]); + seq_printf(s, "Current free pageable XCB buffer cnt[%d]\n", + mb[20]); + seq_printf(s, "Original Initiator fast XCB buffer cnt[%d]\n", + mb[21]); + seq_printf(s, "Current free Initiator fast XCB buffer cnt[%d]\n", + mb[22]); + seq_printf(s, "Original Target fast XCB buffer cnt[%d]\n", + mb[23]); + } return 0; -- 2.12.0
[PATCH 38/43] qla2xxx: Prevent relogin trigger from sending too many commands
From: Quinn TranThis patch adds check for pending work event before queueing relogin work to prevent redundant work to be active at the same time. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_gs.c | 6 -- drivers/scsi/qla2xxx/qla_init.c | 14 +- drivers/scsi/qla2xxx/qla_os.c | 4 +++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3811ccd1c60b..0c31c8ad0c1e 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2504,6 +2504,7 @@ static const char * const port_state_str[] = { #define FCF_FCP2_DEVICEBIT_2 #define FCF_ASYNC_SENT BIT_3 #define FCF_CONF_COMP_SUPPORTED BIT_4 +#define FCF_ASYNC_ACTIVE BIT_5 /* No loop ID flag. */ #define FC_NO_LOOP_ID 0x1000 diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 29b63c2a380b..dd02cbfd0fb1 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3137,7 +3137,7 @@ static void qla2x00_async_gidpn_sp_done(void *s, int res) u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id; struct event_arg ea; - fcport->flags &= ~FCF_ASYNC_SENT; + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); memset(, 0, sizeof(ea)); ea.fcport = fcport; @@ -3246,6 +3246,7 @@ int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport) return QLA_FUNCTION_FAILED; e->u.fcport.fcport = fcport; + fcport->flags |= FCF_ASYNC_ACTIVE; return qla2x00_post_work(vha, e); } @@ -3258,6 +3259,7 @@ int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport) return QLA_FUNCTION_FAILED; e->u.fcport.fcport = fcport; + fcport->flags |= FCF_ASYNC_ACTIVE; return qla2x00_post_work(vha, e); } @@ -3305,7 +3307,7 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res) "Async done-%s res %x, WWPN %8phC \n", sp->name, res, fcport->port_name); - fcport->flags &= ~FCF_ASYNC_SENT; + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); if (res == (DID_ERROR << 16)) { /* entry status error */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f42f2f16343f..85bdb6928ea2 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -109,7 +109,7 @@ qla2x00_async_iocb_timeout(void *data) "Async-%s timeout - hdl=%x portid=%06x %8phC.\n", sp->name, sp->handle, fcport->d_id.b24, fcport->port_name); - fcport->flags &= ~FCF_ASYNC_SENT; + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); } else { pr_info("Async-%s timeout - hdl=%x.\n", sp->name, sp->handle); @@ -154,7 +154,8 @@ qla2x00_async_login_sp_done(void *ptr, int res) ql_dbg(ql_dbg_disc, vha, 0x20dd, "%s %8phC res %d \n", __func__, sp->fcport->port_name, res); - sp->fcport->flags &= ~FCF_ASYNC_SENT; + sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); + if (!test_bit(UNLOADING, >dpc_flags)) { memset(, 0, sizeof(ea)); ea.event = FCME_PLOGI_DONE; @@ -231,7 +232,7 @@ qla2x00_async_logout_sp_done(void *ptr, int res) srb_t *sp = ptr; struct srb_iocb *lio = >u.iocb_cmd; - sp->fcport->flags &= ~FCF_ASYNC_SENT; + sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); if (!test_bit(UNLOADING, >vha->dpc_flags)) qla2x00_post_async_logout_done_work(sp->vha, sp->fcport, lio->u.logio.data); @@ -667,7 +668,7 @@ qla24xx_async_gnl_sp_done(void *s, int res) list_for_each_entry_safe(fcport, tf, , gnl_entry) { list_del_init(>gnl_entry); - fcport->flags &= ~FCF_ASYNC_SENT; + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); ea.fcport = fcport; qla2x00_fcport_event_handler(vha, ); @@ -790,6 +791,7 @@ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport) return QLA_FUNCTION_FAILED; e->u.fcport.fcport = fcport; + fcport->flags |= FCF_ASYNC_ACTIVE; return qla2x00_post_work(vha, e); } @@ -807,7 +809,7 @@ void qla24xx_async_gpdb_sp_done(void *s, int res) "Async done-%s res %x, WWPN %8phC mb[1]=%x mb[2]=%x \n", sp->name, res, fcport->port_name, mb[1], mb[2]); - fcport->flags &= ~FCF_ASYNC_SENT; + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); memset(, 0, sizeof(ea)); ea.event = FCME_GPDB_DONE; @@ -930,6 +932,7 @@ int
[PATCH 43/43] qla2xxx: Update driver version to 10.00.00.04-k
Signed-off-by: Himanshu Madhani--- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 911b82226d13..0843def08356 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.00.00.03-k" +#define QLA2XXX_VERSION "10.00.00.04-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 0 -- 2.12.0
[PATCH 37/43] qla2xxx: Prevent multiple active discovery commands per session
From: Quinn TranAdd check to allow single discovery command per session to be sent Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_gs.c | 16 drivers/scsi/qla2xxx/qla_init.c | 11 ++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 8256b65e9e7a..29b63c2a380b 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3176,16 +3176,16 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport) struct ct_sns_req *ct_req; srb_t *sp; - if (!vha->flags.online) + if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) goto done; - fcport->flags |= FCF_ASYNC_SENT; fcport->disc_state = DSC_GID_PN; fcport->scan_state = QLA_FCPORT_SCAN; sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC); if (!sp) goto done; + fcport->flags |= FCF_ASYNC_SENT; sp->type = SRB_CT_PTHRU_CMD; sp->name = sp_to_str(SPCN_GIDPN); sp->gen1 = fcport->rscn_gen; @@ -3226,8 +3226,8 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport) done_free_sp: sp->free(sp); -done: fcport->flags &= ~FCF_ASYNC_SENT; +done: return rval; } @@ -3368,14 +3368,14 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport) struct ct_sns_req *ct_req; srb_t *sp; - if (!vha->flags.online) + if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) goto done; - fcport->flags |= FCF_ASYNC_SENT; sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) goto done; + fcport->flags |= FCF_ASYNC_SENT; sp->type = SRB_CT_PTHRU_CMD; sp->name = sp_to_str(SPCN_GPSC); sp->gen1 = fcport->rscn_gen; @@ -3415,8 +3415,8 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport) done_free_sp: sp->free(sp); -done: fcport->flags &= ~FCF_ASYNC_SENT; +done: return rval; } @@ -3829,7 +3829,7 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport) struct ct_sns_req *ct_req; srb_t *sp; - if (!vha->flags.online) + if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) return rval; sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); @@ -4525,12 +4525,12 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport) if (!vha->flags.online) goto done; - fcport->flags |= FCF_ASYNC_SENT; fcport->disc_state = DSC_GFPN_ID; sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC); if (!sp) goto done; + fcport->flags |= FCF_ASYNC_SENT; sp->type = SRB_CT_PTHRU_CMD; sp->name = sp_to_str(SPCN_GFPNID); sp->gen1 = fcport->rscn_gen; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 185c106cec0c..f42f2f16343f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -206,7 +206,6 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, lio->u.logio.flags |= SRB_LOGIN_RETRIED; rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { - fcport->flags &= ~FCF_ASYNC_SENT; fcport->flags |= FCF_LOGIN_NEEDED; set_bit(RELOGIN_NEEDED, >dpc_flags); goto done_free_sp; @@ -221,8 +220,8 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, done_free_sp: sp->free(sp); -done: fcport->flags &= ~FCF_ASYNC_SENT; +done: return rval; } @@ -244,9 +243,11 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) { srb_t *sp; struct srb_iocb *lio; - int rval; + int rval = QLA_FUNCTION_FAILED; + + if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) + return rval; - rval = QLA_FUNCTION_FAILED; fcport->flags |= FCF_ASYNC_SENT; sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) @@ -717,7 +718,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport) unsigned long flags; u16 *mb; - if (!vha->flags.online) + if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) goto done; ql_dbg(ql_dbg_disc, vha, 0x20d9, -- 2.12.0
[PATCH 24/43] qla2xxx: Reduce the use of terminate exchange
From: Quinn Tranreduce usage of terminate exchange when command encounter resource bottle neck. Remote initiator view it as command drop. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_target.c | 140 -- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index c7c81d5cf69c..e7e0689d9ca5 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -75,7 +75,8 @@ MODULE_PARM_DESC(ql2xuctrlirq, int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE; -static int temp_sam_status = SAM_STAT_BUSY; +static int qla_sam_status = SAM_STAT_BUSY; +static int tc_sam_status = SAM_STAT_TASK_SET_FULL; /* target core */ /* * From scsi/fc/fc_fcp.h @@ -4294,14 +4295,14 @@ static void qlt_create_sess_from_atio(struct work_struct *work) if (op->atio.u.raw.entry_count > 1) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, "Dropping multy entry atio %p\n", >atio); - goto out_term; + goto out_busy; } sess = qlt_make_local_sess(vha, s_id); /* sess has an extra creation ref. */ if (!sess) - goto out_term; + goto out_busy; /* * Now obtain a pre-allocated session tag using the original op->atio * packet header, and dispatch into __qlt_do_work() using the existing @@ -4312,7 +4313,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work) struct qla_qpair *qpair = ha->base_qpair; spin_lock_irqsave(qpair->qp_lock_ptr, flags); - qlt_send_busy(qpair, >atio, SAM_STAT_BUSY); + qlt_send_busy(qpair, >atio, tc_sam_status); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); spin_lock_irqsave(>tgt.sess_lock, flags); @@ -4332,6 +4333,17 @@ static void qlt_create_sess_from_atio(struct work_struct *work) out_term: qlt_send_term_exchange(vha->hw->base_qpair, NULL, >atio, 0, 0); kfree(op); + return; +out_busy: + { + struct qla_qpair *qpair = ha->base_qpair; + + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + qlt_send_busy(qpair, >atio, qla_sam_status); + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + kfree(op); + } + return; } /* ha->hardware_lock supposed to be held on entry */ @@ -4348,7 +4360,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, if (unlikely(tgt->tgt_stop)) { ql_dbg(ql_dbg_io, vha, 0x3061, "New command while device %p is shutting down\n", tgt); - return -EFAULT; + return -ENODEV; } id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2]; @@ -4403,7 +4415,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, spin_lock_irqsave(>tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(>tgt.sess_lock, flags); - return -ENOMEM; + return -EBUSY; } cmd->cmd_in_wq = 1; @@ -5504,7 +5516,6 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, struct qla_qpair *qpair, struct atio_from_isp *atio, uint8_t ha_locked) { struct qla_hw_data *ha = vha->hw; - uint16_t status; unsigned long flags; if (ha->tgt.num_pend_cmds < Q_FULL_THRESH_HOLD(ha)) @@ -5512,8 +5523,7 @@ qlt_chk_qfull_thresh_hold(struct scsi_qla_host *vha, struct qla_qpair *qpair, if (!ha_locked) spin_lock_irqsave(>hardware_lock, flags); - status = temp_sam_status; - qlt_send_busy(qpair, atio, status); + qlt_send_busy(qpair, atio, qla_sam_status); if (!ha_locked) spin_unlock_irqrestore(>hardware_lock, flags); @@ -5528,7 +5538,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, struct qla_hw_data *ha = vha->hw; struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; int rc; - unsigned long flags; + unsigned long flags = 0; if (unlikely(tgt == NULL)) { ql_dbg(ql_dbg_tgt, vha, 0x3064, @@ -5552,8 +5562,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, "sending QUEUE_FULL\n", vha->vp_idx); if (!ha_locked) spin_lock_irqsave(>hardware_lock, flags); - qlt_send_busy(ha->base_qpair, atio, - SAM_STAT_TASK_SET_FULL); + qlt_send_busy(ha->base_qpair, atio, qla_sam_status); if (!ha_locked) spin_unlock_irqrestore(>hardware_lock,
[PATCH 34/43] qla2xxx: Delay loop id allocation at login
From: Quinn TranDelay loop id allocation to login time Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 64 ++--- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 80e9d80cce2b..185c106cec0c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -582,36 +582,29 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, if (!found) { /* fw has no record of this port */ - if (fcport->loop_id == FC_NO_LOOP_ID) { - qla2x00_find_new_loop_id(vha, fcport); - fcport->fw_login_state = DSC_LS_PORT_UNAVAIL; - } else { - for (i = 0; i < n; i++) { - e = >gnl.l[i]; - id.b.domain = e->port_id[0]; - id.b.area = e->port_id[1]; - id.b.al_pa = e->port_id[2]; - id.b.rsvd_1 = 0; - loop_id = le16_to_cpu(e->nport_handle); - - if (fcport->d_id.b24 == id.b24) { - conflict_fcport = - qla2x00_find_fcport_by_wwpn(vha, - e->port_name, 0); - - ql_dbg(ql_dbg_disc, vha, 0x20e6, - "%s %d %8phC post del sess\n", - __func__, __LINE__, - conflict_fcport->port_name); - qlt_schedule_sess_for_deletion - (conflict_fcport, 1); - } - - if (fcport->loop_id == loop_id) { - /* FW already picked this loop id for another fcport */ - qla2x00_find_new_loop_id(vha, fcport); - } + for (i = 0; i < n; i++) { + e = >gnl.l[i]; + id.b.domain = e->port_id[0]; + id.b.area = e->port_id[1]; + id.b.al_pa = e->port_id[2]; + id.b.rsvd_1 = 0; + loop_id = le16_to_cpu(e->nport_handle); + + if (fcport->d_id.b24 == id.b24) { + conflict_fcport = + qla2x00_find_fcport_by_wwpn(vha, + e->port_name, 0); + ql_dbg(ql_dbg_disc, vha, 0x20e6, + "%s %d %8phC post del sess\n", + __func__, __LINE__, + conflict_fcport->port_name); + qlt_schedule_sess_for_deletion + (conflict_fcport, 1); } + + /* FW already picked this loop id for another fcport */ + if (fcport->loop_id == loop_id) + fcport->loop_id = FC_NO_LOOP_ID; } qla24xx_fcport_handle_login(vha, fcport); } @@ -1106,6 +1099,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport) { u8 login = 0; + int rc; if (qla_tgt_mode_enabled(vha)) return; @@ -1131,6 +1125,18 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport) } if (login) { + if (fcport->loop_id == FC_NO_LOOP_ID) { + fcport->fw_login_state = DSC_LS_PORT_UNAVAIL; + rc = qla2x00_find_new_loop_id(vha, fcport); + if (rc) { + ql_dbg(ql_dbg_disc, vha, 0x20e6, + "%s %d %8phC post del sess - out of loopid\n", + __func__, __LINE__, fcport->port_name); + fcport->scan_state = 0; + qlt_schedule_sess_for_deletion(fcport, true); + return; + } + } ql_dbg(ql_dbg_disc, vha, 0x20bf, "%s %d %8phC post login\n", __func__, __LINE__, fcport->port_name); -- 2.12.0
[PATCH 30/43] qla2xxx: Properly extract ADISC error codes
From: Quinn TranThis patch fixes issue with extraction of ADISC error codes for decoding the error returned Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 24 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e58faa1e984c..bd28a0e6a95c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -338,16 +338,21 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport) static void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) { - if (ea->rc) { + struct fc_port *fcport = ea->fcport; + + ql_dbg(ql_dbg_disc, vha, 0x20d2, + "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n", + __func__, fcport->port_name, fcport->disc_state, + fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2, + fcport->rscn_gen, ea->sp->gen1, fcport->loop_id); + + if (ea->data[0] != MBS_COMMAND_COMPLETE) { ql_dbg(ql_dbg_disc, vha, 0x2066, "%s %8phC: adisc fail: post delete\n", __func__, ea->fcport->port_name); qlt_schedule_sess_for_deletion(ea->fcport, 1); return; } - ql_dbg(ql_dbg_disc, vha, 0x20d2, - "%s %8phC DS %d LS %d\n", __func__, ea->fcport->port_name, - ea->fcport->disc_state, ea->fcport->fw_login_state); if (ea->fcport->disc_state == DSC_DELETE_PEND) return; @@ -355,10 +360,8 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) if (ea->sp->gen2 != ea->fcport->login_gen) { /* target side must have changed it. */ ql_dbg(ql_dbg_disc, vha, 0x20d3, - "%s %8phC generation changed rscn %d|%d login %d|%d\n", - __func__, ea->fcport->port_name, ea->fcport->last_rscn_gen, - ea->fcport->rscn_gen, ea->fcport->last_login_gen, - ea->fcport->login_gen); + "%s %8phC generation changed\n", + __func__, ea->fcport->port_name); return; } else if (ea->sp->gen1 != ea->fcport->rscn_gen) { ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n", @@ -376,6 +379,7 @@ qla2x00_async_adisc_sp_done(void *ptr, int res) srb_t *sp = ptr; struct scsi_qla_host *vha = sp->vha; struct event_arg ea; + struct srb_iocb *lio = >u.iocb_cmd; ql_dbg(ql_dbg_disc, vha, 0x2066, "Async done-%s res %x %8phC\n", @@ -384,6 +388,10 @@ qla2x00_async_adisc_sp_done(void *ptr, int res) memset(, 0, sizeof(ea)); ea.event = FCME_ADISC_DONE; ea.rc = res; + ea.data[0] = lio->u.logio.data[0]; + ea.data[1] = lio->u.logio.data[1]; + ea.iop[0] = lio->u.logio.iop[0]; + ea.iop[1] = lio->u.logio.iop[1]; ea.fcport = sp->fcport; ea.sp = sp; -- 2.12.0
[PATCH 28/43] qla2xxx: Remove session creation redundant code
From: Quinn TranCurrent code creates a session when a new port is discovered, and a PLOGI/PRLI is received. There is no need to create session when command has arrived. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_target.c | 122 ++ 1 file changed, 5 insertions(+), 117 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 93910e56643d..598ec3481a8c 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2016,15 +2016,10 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012, "qla_target(%d): task abort for non-existant session\n", vha->vp_idx); - rc = qlt_sched_sess_work(vha->vha_tgt.qla_tgt, - QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts)); - spin_unlock_irqrestore(>tgt.sess_lock, flags); - if (rc != 0) { - qlt_24xx_send_abts_resp(ha->base_qpair, abts, - FCP_TMF_REJECTED, false); - } + qlt_24xx_send_abts_resp(ha->base_qpair, abts, FCP_TMF_REJECTED, + false); return; } spin_unlock_irqrestore(>tgt.sess_lock, flags); @@ -4265,87 +4260,6 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, return cmd; } -static void qlt_create_sess_from_atio(struct work_struct *work) -{ - struct qla_tgt_sess_op *op = container_of(work, - struct qla_tgt_sess_op, work); - scsi_qla_host_t *vha = op->vha; - struct qla_hw_data *ha = vha->hw; - struct fc_port *sess; - struct qla_tgt_cmd *cmd; - unsigned long flags; - uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id; - - spin_lock_irqsave(>cmd_list_lock, flags); - list_del(>cmd_list); - spin_unlock_irqrestore(>cmd_list_lock, flags); - - if (op->aborted) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083, - "sess_op with tag %u is aborted\n", - op->atio.u.isp24.exchange_addr); - goto out_term; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, - "qla_target(%d): Unable to find wwn login" - " (s_id %x:%x:%x), trying to create it manually\n", - vha->vp_idx, s_id[0], s_id[1], s_id[2]); - - if (op->atio.u.raw.entry_count > 1) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, - "Dropping multy entry atio %p\n", >atio); - goto out_busy; - } - - sess = qlt_make_local_sess(vha, s_id); - /* sess has an extra creation ref. */ - - if (!sess) - goto out_busy; - /* -* Now obtain a pre-allocated session tag using the original op->atio -* packet header, and dispatch into __qlt_do_work() using the existing -* process context. -*/ - cmd = qlt_get_tag(vha, sess, >atio); - if (!cmd) { - struct qla_qpair *qpair = ha->base_qpair; - - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - qlt_send_busy(qpair, >atio, tc_sam_status); - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - - spin_lock_irqsave(>tgt.sess_lock, flags); - ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(>tgt.sess_lock, flags); - kfree(op); - return; - } - - /* -* __qlt_do_work() will call qlt_put_sess() to release -* the extra reference taken above by qlt_make_local_sess() -*/ - __qlt_do_work(cmd); - kfree(op); - return; -out_term: - qlt_send_term_exchange(vha->hw->base_qpair, NULL, >atio, 0, 0); - kfree(op); - return; -out_busy: - { - struct qla_qpair *qpair = ha->base_qpair; - - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - qlt_send_busy(qpair, >atio, qla_sam_status); - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - kfree(op); - } - return; -} - /* ha->hardware_lock supposed to be held on entry */ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, struct atio_from_isp *atio) @@ -4370,23 +4284,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, return -EBUSY; sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id); - if (unlikely(!sess)) { - struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op), -GFP_ATOMIC); - if (!op) - return -ENOMEM; - - memcpy(>atio,
[PATCH 23/43] qla2xxx: Add lock protection around host lookup
From: Quinn TranHost lookup via btree is currently protected by the hardware_lock. Add hardware_lock when modifying btree to store host pointer. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 3 +++ drivers/scsi/qla2xxx/qla_mid.c| 9 + drivers/scsi/qla2xxx/qla_target.c | 6 -- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index cdcd84278fd0..300cd795dad4 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3977,6 +3977,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); port_id_t id; + unsigned long flags; /* Get host addresses. */ rval = qla2x00_get_adapter_id(vha, @@ -4058,7 +4059,9 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) id.b.area = area; id.b.al_pa = al_pa; id.b.rsvd_1 = 0; + spin_lock_irqsave(>hardware_lock, flags); qlt_update_host_map(vha, id); + spin_unlock_irqrestore(>hardware_lock, flags); if (!vha->flags.init_done) ql_log(ql_log_info, vha, 0x2010, diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index a823fa6b7060..12a29eca02e1 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -50,10 +50,11 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) spin_lock_irqsave(>vport_slock, flags); list_add_tail(>list, >vp_list); + spin_unlock_irqrestore(>vport_slock, flags); + spin_lock_irqsave(>hardware_lock, flags); qlt_update_vp_map(vha, SET_VP_IDX); - - spin_unlock_irqrestore(>vport_slock, flags); + spin_unlock_irqrestore(>hardware_lock, flags); mutex_unlock(>vport_lock); return vp_id; @@ -158,9 +159,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) atomic_set(>loop_down_timer, LOOP_DOWN_TIME); /* Remove port id from vp target map */ - spin_lock_irqsave(>hw->vport_slock, flags); + spin_lock_irqsave(>hw->hardware_lock, flags); qlt_update_vp_map(vha, RESET_AL_PA); - spin_unlock_irqrestore(>hw->vport_slock, flags); + spin_unlock_irqrestore(>hw->hardware_lock, flags); qla2x00_mark_vp_devices_dead(vha); atomic_set(>vp_state, VP_FAILED); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 48e0a12dca61..c7c81d5cf69c 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -7206,20 +7206,14 @@ qlt_update_vp_map(struct scsi_qla_host *vha, int cmd) void qlt_update_host_map(struct scsi_qla_host *vha, port_id_t id) { - unsigned long flags; - struct qla_hw_data *ha = vha->hw; if (!vha->d_id.b24) { - spin_lock_irqsave(>vport_slock, flags); vha->d_id = id; qlt_update_vp_map(vha, SET_AL_PA); - spin_unlock_irqrestore(>vport_slock, flags); } else if (vha->d_id.b24 != id.b24) { - spin_lock_irqsave(>vport_slock, flags); qlt_update_vp_map(vha, RESET_AL_PA); vha->d_id = id; qlt_update_vp_map(vha, SET_AL_PA); - spin_unlock_irqrestore(>vport_slock, flags); } } -- 2.12.0
[PATCH 27/43] qla2xxx: Migrate switch registration commands away from mailbox interface
From: Quinn TranMigrate switch registration commands: RFTID, RFFID, RNNID and RSNN_NN out of mailbox interface to reduce fabric scan bottle neck. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h| 8 +- drivers/scsi/qla2xxx/qla_gbl.h| 2 +- drivers/scsi/qla2xxx/qla_gs.c | 454 +++--- drivers/scsi/qla2xxx/qla_os.c | 20 +- drivers/scsi/qla2xxx/qla_target.c | 13 +- drivers/scsi/qla2xxx/qla_target.h | 2 +- 6 files changed, 355 insertions(+), 144 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3042697b92ae..db1f68c3e074 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -516,6 +516,10 @@ enum { SPCN_NVME_CMD, SPCN_CTRL_VP, SPCN_PRLO, + SPCN_RFTID, + SPCN_RFFID, + SPCN_RNNID, + SPCN_RS, }; struct sp_name { @@ -581,6 +585,7 @@ typedef struct srb { u32 gen1; /* scratch */ u32 gen2; /* scratch */ int rc; + int retry_count; struct completion comp; union { struct srb_iocb iocb_cmd; @@ -3234,7 +3239,7 @@ enum qla_work_type { QLA_EVT_AENFX, QLA_EVT_GIDPN, QLA_EVT_GPNID, - QLA_EVT_GPNID_DONE, + QLA_EVT_UNMAP, QLA_EVT_NEW_SESS, QLA_EVT_GPDB, QLA_EVT_PRLI, @@ -3250,6 +3255,7 @@ enum qla_work_type { QLA_EVT_GNNFT_DONE, QLA_EVT_GNNID, QLA_EVT_GFPNID, + QLA_EVT_SP_RETRY, }; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 43799e8dc68a..650ec54e3255 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -650,7 +650,6 @@ extern void qla2x00_free_fcport(fc_port_t *); extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *); extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *); -void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*); void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *); int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *); @@ -669,6 +668,7 @@ int qla24xx_post_gnnid_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *); void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea); +void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *); /* * Global Function Prototypes in qla_attr.c source file. diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 643ce1578cbe..0e84381e227e 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -14,6 +14,10 @@ static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *); static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *); static int qla2x00_sns_rft_id(scsi_qla_host_t *); static int qla2x00_sns_rnn_id(scsi_qla_host_t *); +static int qla_async_rftid(scsi_qla_host_t *, port_id_t *); +static int qla_async_rffid(scsi_qla_host_t *, port_id_t *, u8, u8); +static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*); +static int qla_async_rsnn_nn(scsi_qla_host_t *); struct sp_name sp_str[] = { { SPCN_UNKNOWN, "unknown" }, @@ -43,6 +47,10 @@ struct sp_name sp_str[] = { { SPCN_NVME_CMD, "nvme_cmd" }, { SPCN_CTRL_VP, "ctrl_vp" }, { SPCN_PRLO, "prlo" }, + { SPCN_RFTID, "rftid" }, + { SPCN_RFFID, "rffid" }, + { SPCN_RNNID, "rnnid" }, + { SPCN_RS, "rsnn_nn" }, }; const char *sp_to_str(uint16_t cmd) @@ -556,6 +564,72 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list) return (rval); } +static void qla2x00_async_sns_sp_done(void *s, int rc) +{ + struct srb *sp = s; + struct scsi_qla_host *vha = sp->vha; + struct ct_sns_pkt *ct_sns; + struct qla_work_evt *e; + + sp->rc = rc; + if (rc == QLA_SUCCESS) { + ql_dbg(ql_dbg_disc, vha, 0x204f, + "Async done-%s exiting normally.\n", + sp->name); + } else if (rc == QLA_FUNCTION_TIMEOUT) { + ql_dbg(ql_dbg_disc, vha, 0x204f, + "Async done-%s timeout\n", sp->name); + } else { + ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp; + memset(ct_sns, 0, sizeof(*ct_sns)); + sp->retry_count++; + if (sp->retry_count > 3) + goto err; + + ql_dbg(ql_dbg_disc, vha, 0x204f, + "Async done-%s fail rc %x. Retry count %d\n", + sp->name, rc, sp->retry_count); + + e = qla2x00_alloc_work(vha, QLA_EVT_SP_RETRY); + if (!e) + goto err2; + +
[PATCH 26/43] qla2xxx: Fix login state machine freeze
From: Quinn TranRelogin stop moving forward due to improper check of scan_state flag. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 300cd795dad4..152c808b272b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1270,11 +1270,6 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, { fc_port_t *fcport = ea->fcport; - if (fcport->scan_state != QLA_FCPORT_FOUND) { - fcport->login_retry++; - return; - } - ql_dbg(ql_dbg_disc, vha, 0x2102, "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n", __func__, fcport->port_name, fcport->disc_state, @@ -1324,7 +1319,6 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) int rc; switch (ea->event) { - case FCME_RELOGIN: case FCME_RSCN: case FCME_GIDPN_DONE: case FCME_GPSC_DONE: -- 2.12.0
[PATCH 40/43] qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion()
From: Quinn TranImmeadiate flag is not used for scheduling session deletion. Remove it to simplfy session deletion code path. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_gbl.h| 2 +- drivers/scsi/qla2xxx/qla_init.c | 10 +- drivers/scsi/qla2xxx/qla_target.c | 16 +++- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 91db1924ca79..ab8ffd7933c9 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -888,7 +888,7 @@ void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *); void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *, struct fc_port *, enum qlt_plogi_link_t); void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *); -extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool); +extern void qlt_schedule_sess_for_deletion(struct fc_port *); extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *); extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *, uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 49a8f2666f55..3e03c264f7bd 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -352,7 +352,7 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) ql_dbg(ql_dbg_disc, vha, 0x2066, "%s %8phC: adisc fail: post delete\n", __func__, ea->fcport->port_name); - qlt_schedule_sess_for_deletion(ea->fcport, 1); + qlt_schedule_sess_for_deletion(ea->fcport); return; } @@ -529,7 +529,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, ql_dbg(ql_dbg_disc, vha, 0x20e3, "%s %d %8phC post del sess\n", __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion(fcport, 1); + qlt_schedule_sess_for_deletion(fcport); return; } @@ -601,7 +601,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, __func__, __LINE__, conflict_fcport->port_name); qlt_schedule_sess_for_deletion - (conflict_fcport, 1); + (conflict_fcport); } /* FW already picked this loop id for another fcport */ @@ -1136,7 +1136,7 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport) "%s %d %8phC post del sess - out of loopid\n", __func__, __LINE__, fcport->port_name); fcport->scan_state = 0; - qlt_schedule_sess_for_deletion(fcport, true); + qlt_schedule_sess_for_deletion(fcport); return; } } @@ -1782,7 +1782,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) set_bit(lid, vha->hw->loop_id_map); ea->fcport->loop_id = lid; ea->fcport->keep_nport_handle = 0; - qlt_schedule_sess_for_deletion(ea->fcport, false); + qlt_schedule_sess_for_deletion(ea->fcport); } break; } diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 43e210757840..6b16f0dbd588 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1211,8 +1211,7 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess) } /* ha->tgt.sess_lock supposed to be held on entry */ -void qlt_schedule_sess_for_deletion(struct fc_port *sess, - bool immediate) +void qlt_schedule_sess_for_deletion(struct fc_port *sess) { struct qla_tgt *tgt = sess->tgt; @@ -1250,7 +1249,7 @@ void qlt_schedule_sess_for_deletion_lock(struct fc_port *sess) unsigned long flags; struct qla_hw_data *ha = sess->vha->hw; spin_lock_irqsave(>tgt.sess_lock, flags); - qlt_schedule_sess_for_deletion(sess, 1); + qlt_schedule_sess_for_deletion(sess); spin_unlock_irqrestore(>tgt.sess_lock, flags); } @@ -1262,7 +1261,7 @@ static void qlt_clear_tgt_db(struct qla_tgt *tgt) list_for_each_entry(sess, >vp_fcports, list) { if (sess->se_sess) -
[PATCH 33/43] qla2xxx: Increase verbosity of debug messages logged
From: Quinn TranAdd verbose bit for debug messages to reduce excessive log messages Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_target.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 598ec3481a8c..43e210757840 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -209,7 +209,7 @@ struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha, host = btree_lookup32(>hw->tgt.host_map, key); if (!host) - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005, + ql_dbg(ql_dbg_tgt_mgt + ql_dbg_verbose, vha, 0xf005, "Unable to find host %06x\n", key); return host; @@ -310,17 +310,17 @@ static void qlt_try_to_dequeue_unknown_atios(struct scsi_qla_host *vha, host = qlt_find_host_by_d_id(vha, u->atio.u.isp24.fcp_hdr.d_id); if (host != NULL) { - ql_dbg(ql_dbg_async, vha, 0x502f, + ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x502f, "Requeuing unknown ATIO_TYPE7 %p\n", u); qlt_24xx_atio_pkt(host, >atio, ha_locked); } else if (tgt->tgt_stop) { - ql_dbg(ql_dbg_async, vha, 0x503a, + ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x503a, "Freeing unknown %s %p, because tgt is being stopped\n", "ATIO_TYPE7", u); qlt_send_term_exchange(vha->hw->base_qpair, NULL, >atio, ha_locked, 0); } else { - ql_dbg(ql_dbg_async, vha, 0x503d, + ql_dbg(ql_dbg_async + ql_dbg_verbose, vha, 0x503d, "Reschedule u %p, vha %p, host %p\n", u, vha, host); if (!queued) { queued = 1; -- 2.12.0
[PATCH 32/43] qla2xxx: Allow relogin and session creation after reset
When any kind of reset is issued, current code was setting state of LOGIN pending too early. This resulted into driver not retrying relogin until pervious reloin completes. Signed-off-by: Himanshu MadhaniSigned-off-by: Quinn Tran --- drivers/scsi/qla2xxx/qla_init.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ac3f82340315..80e9d80cce2b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1134,7 +1134,6 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport) ql_dbg(ql_dbg_disc, vha, 0x20bf, "%s %d %8phC post login\n", __func__, __LINE__, fcport->port_name); - fcport->disc_state = DSC_LOGIN_PEND; qla2x00_post_async_login_work(vha, fcport, NULL); } } -- 2.12.0
[PATCH 22/43] qla2xxx: Add switch command to simplify fabric discovery
From: Quinn Tran- add "async" gpn_ft, gnn_ft, gfpn_id, gnn_id switch commands. - For 8G and newer adapters, use async commands when it comes to fabric scan to reduce bottle neck. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_attr.c | 2 + drivers/scsi/qla2xxx/qla_def.h| 73 +++- drivers/scsi/qla2xxx/qla_gbl.h| 17 +- drivers/scsi/qla2xxx/qla_gs.c | 711 +- drivers/scsi/qla2xxx/qla_init.c | 309 +++-- drivers/scsi/qla2xxx/qla_mbx.c| 5 +- drivers/scsi/qla2xxx/qla_os.c | 47 ++- drivers/scsi/qla2xxx/qla_target.c | 62 +++- drivers/scsi/qla2xxx/qla_target.h | 2 +- 9 files changed, 1105 insertions(+), 123 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 9ce28c4f9812..b360df9936ff 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -2170,6 +2170,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) dma_free_coherent(>pdev->dev, vha->gnl.size, vha->gnl.l, vha->gnl.ldma); + vfree(vha->scan.l); + if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) { if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS) ql_log(ql_log_warn, vha, 0x7087, diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 749f3e457346..3042697b92ae 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -490,6 +490,7 @@ enum { SPCN_GPSC, SPCN_GPNID, SPCN_GPNFT, + SPCN_GNNFT, SPCN_GNNID, SPCN_GFPNID, SPCN_LOGIN, @@ -2315,11 +2316,13 @@ struct ct_sns_desc { enum discovery_state { DSC_DELETED, + DSC_GNN_ID, DSC_GID_PN, DSC_GNL, DSC_LOGIN_PEND, DSC_LOGIN_FAILED, DSC_GPDB, + DSC_GFPN_ID, DSC_GPSC, DSC_UPD_FCPORT, DSC_LOGIN_COMPLETE, @@ -2349,8 +2352,9 @@ enum fcport_mgt_event { FCME_GPDB_DONE, FCME_GPNID_DONE, FCME_GFFID_DONE, - FCME_DELETE_DONE, FCME_ADISC_DONE, + FCME_GNNID_DONE, + FCME_GFPNID_DONE, }; enum rscn_addr_format { @@ -2383,6 +2387,7 @@ typedef struct fc_port { unsigned int login_pause:1; unsigned int login_succ:1; unsigned int query:1; + unsigned int id_changed:1; struct work_struct nvme_del_work; struct completion nvme_del_done; @@ -2530,6 +2535,11 @@ static const char * const port_state_str[] = { #defineGA_NXT_REQ_SIZE (16 + 4) #defineGA_NXT_RSP_SIZE (16 + 620) +#defineGPN_FT_CMD 0x172 +#defineGPN_FT_REQ_SIZE (16 + 4) +#defineGNN_FT_CMD 0x173 +#defineGNN_FT_REQ_SIZE (16 + 4) + #defineGID_PT_CMD 0x1A1 #defineGID_PT_REQ_SIZE (16 + 4) @@ -2785,6 +2795,13 @@ struct ct_sns_req { } port_id; struct { + uint8_t reserved; + uint8_t domain; + uint8_t area; + uint8_t port_type; + } gpn_ft; + + struct { uint8_t port_type; uint8_t domain; uint8_t area; @@ -2897,6 +2914,27 @@ struct ct_sns_gid_pt_data { uint8_t port_id[3]; }; +/* It's the same for both GPN_FT and GNN_FT */ +struct ct_sns_gpnft_rsp { + struct { + struct ct_cmd_hdr header; + uint16_t response; + uint16_t residual; + uint8_t fragment_id; + uint8_t reason_code; + uint8_t explanation_code; + uint8_t vendor_unique; + }; + /* Assume the largest number of targets for the union */ + struct ct_sns_gpn_ft_data { + u8 control_byte; + u8 port_id[3]; + u32 reserved; + u8 port_name[8]; + } entries[1]; +}; + +/* CT command response */ struct ct_sns_rsp { struct ct_rsp_hdr header; @@ -2972,6 +3010,24 @@ struct ct_sns_pkt { } p; }; +struct ct_sns_gpnft_pkt { + union { + struct ct_sns_req req; + struct ct_sns_gpnft_rsp rsp; + } p; +}; + +struct fab_scan_rp { + port_id_t id; + u8 port_name[8]; + u8 node_name[8]; +}; + +struct fab_scan { + struct fab_scan_rp *l; + u32 size; +}; + /* * SNS command structures -- for 2200 compatibility. */ @@ -3189,6 +3245,11 @@ enum qla_work_type { QLA_EVT_RELOGIN, QLA_EVT_ASYNC_PRLO, QLA_EVT_ASYNC_PRLO_DONE, + QLA_EVT_GPNFT, + QLA_EVT_GPNFT_DONE, + QLA_EVT_GNNFT_DONE, + QLA_EVT_GNNID, + QLA_EVT_GFPNID, }; @@ -3230,7 +3291,9 @@ struct qla_work_evt {
[PATCH 25/43] qla2xxx: Reduce trace noise for Async Events
From: Quinn TranAdd NPIV id check to reduce multiple debug messages of the same RSCN event. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_mid.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 12a29eca02e1..11a424df5f52 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -265,13 +265,20 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) case MBA_LIP_RESET: case MBA_POINT_TO_POINT: case MBA_CHG_IN_CONNECTION: - case MBA_PORT_UPDATE: - case MBA_RSCN_UPDATE: ql_dbg(ql_dbg_async, vha, 0x5024, "Async_event for VP[%d], mb=0x%x vha=%p.\n", i, *mb, vha); qla2x00_async_event(vha, rsp, mb); break; + case MBA_PORT_UPDATE: + case MBA_RSCN_UPDATE: + if ((mb[3] & 0xff) == vha->vp_idx) { + ql_dbg(ql_dbg_async, vha, 0x5024, + "Async_event for VP[%d], mb=0x%x vha=%p\n", + i, *mb, vha); + qla2x00_async_event(vha, rsp, mb); + } + break; } spin_lock_irqsave(>vport_slock, flags); -- 2.12.0
[PATCH 39/43] qla2xxx: Check FCF_ASYNC_SENT flag
Signed-off-by: Himanshu Madhani--- drivers/scsi/qla2xxx/qla_init.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 85bdb6928ea2..49a8f2666f55 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -720,7 +720,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport) u16 *mb; if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) - goto done; + return rval; ql_dbg(ql_dbg_disc, vha, 0x20d9, "Async-gnlist WWPN %8phC \n", fcport->port_name); @@ -734,8 +734,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport) list_add_tail(>gnl_entry, >gnl.fcports); if (vha->gnl.sent) { spin_unlock_irqrestore(>hw->tgt.sess_lock, flags); - rval = QLA_SUCCESS; - goto done; + return QLA_SUCCESS; } vha->gnl.sent = 1; spin_unlock_irqrestore(>hw->tgt.sess_lock, flags); -- 2.12.0
[PATCH 11/43] qla2xxx: Move work element processing out of DPC thread
From: Quinn TranDPC thread can stall during switch scan due to slow switch response. This will stall other work element that needs attention. Moving work element processing and relogin logic out of DPC thread and into its own work queue. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 6 ++-- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_init.c | 1 + drivers/scsi/qla2xxx/qla_mid.c | 6 +--- drivers/scsi/qla2xxx/qla_os.c | 76 +++-- 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 18b393453002..a2c0f3d78b35 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3183,6 +3183,7 @@ enum qla_work_type { QLA_EVT_UPD_FCPORT, QLA_EVT_GNL, QLA_EVT_NACK, + QLA_EVT_RELOGIN, }; @@ -3513,10 +3514,6 @@ struct qlt_hw_data { #define LEAK_EXCHG_THRESH_HOLD_PERCENT 75 /* 75 percent */ -#define QLA_EARLY_LINKUP(_ha) \ - ((_ha->flags.n2n_ae || _ha->flags.lip_ae) && \ -_ha->flags.fw_started && !_ha->flags.fw_init_done) - /* * Qlogic host adapter specific data structure. */ @@ -4222,6 +4219,7 @@ typedef struct scsi_qla_host { #define SET_ZIO_THRESHOLD_NEEDED 28 #define DETECT_SFP_CHANGE 29 #define N2N_LOGIN_NEEDED 30 +#define IOCB_WORK_ACTIVE 31 unsigned long pci_flags; #define PFLG_DISCONNECTED 0 /* PCI device removed */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 66dcbdb91244..fb1c9ffdc05a 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -204,7 +204,7 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, uint16_t *); int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_async_abort_cmd(srb_t *); - +int qla24xx_post_relogin_work(struct scsi_qla_host *vha); /* * Global Functions in qla_mid.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 0a1c287c2d66..61b74fd220a3 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -901,6 +901,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) __func__, fcport->port_name, fcport->last_rscn_gen, fcport->rscn_gen, fcport->last_login_gen, fcport->login_gen); + set_bit(RELOGIN_NEEDED, >dpc_flags); return; } else if (ea->sp->gen1 != fcport->rscn_gen) { ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n", diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index fc61fef5e305..b2fda398a098 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -319,8 +319,6 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x4012, "Entering %s vp_flags: 0x%lx.\n", __func__, vha->vp_flags); - qla2x00_do_work(vha); - /* Check if Fw is ready to configure VP first */ if (test_bit(VP_CONFIG_OK, _vha->vp_flags)) { if (test_and_clear_bit(VP_IDX_ACQUIRED, >vp_flags)) { @@ -354,9 +352,7 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) ql_dbg(ql_dbg_dpc, vha, 0x4018, "Relogin needed scheduled.\n"); - qla2x00_relogin(vha); - ql_dbg(ql_dbg_dpc, vha, 0x4019, - "Relogin needed end.\n"); + qla24xx_post_relogin_work(vha); } } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 4a542a5a976d..66e6fe73a035 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2683,14 +2683,22 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) { struct scsi_qla_host *vha = container_of(work, struct scsi_qla_host, iocb_work); - int cnt = 0; + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + int i = 20; + unsigned long flags; + + if (test_bit(UNLOADING, _vha->dpc_flags)) + return; - while (!list_empty(>work_list)) { + while (!list_empty(>work_list) && i > 0) { qla2x00_do_work(vha); - cnt++; - if (cnt > 10) - break; + i--; } + + spin_lock_irqsave(>work_lock, flags); + clear_bit(IOCB_WORK_ACTIVE, >dpc_flags); + spin_unlock_irqrestore(>work_lock, flags); } /* @@ -3192,7 +3200,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
[PATCH 09/43] qla2xxx: Fix Firmware dump size for Extended login and Exchange Offload
From: Quinn TranThis patch adjusts and reallocates fw_dump memory for target mode to save for extended login and exchange offload buffers into dump captured. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 209 +--- drivers/scsi/qla2xxx/qla_tmpl.c | 40 +++- 2 files changed, 147 insertions(+), 102 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 429305caef47..5cd04bfa5cae 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2593,70 +2593,27 @@ qla24xx_chip_diag(scsi_qla_host_t *vha) return rval; } -void -qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) +static void +qla2x00_alloc_offload_mem(scsi_qla_host_t *vha) { int rval; - uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, - eft_size, fce_size, mq_size; dma_addr_t tc_dma; void *tc; struct qla_hw_data *ha = vha->hw; - struct req_que *req = ha->req_q_map[0]; - struct rsp_que *rsp = ha->rsp_q_map[0]; - if (ha->fw_dump) { + if (ha->eft) { ql_dbg(ql_dbg_init, vha, 0x00bd, - "Firmware dump already allocated.\n"); + "%s: Offload Mem is already allocated.\n", + __func__); return; } - ha->fw_dumped = 0; - ha->fw_dump_cap_flags = 0; - dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0; - req_q_size = rsp_q_size = 0; - - if (IS_QLA27XX(ha)) - goto try_fce; - - if (IS_QLA2100(ha) || IS_QLA2200(ha)) { - fixed_size = sizeof(struct qla2100_fw_dump); - } else if (IS_QLA23XX(ha)) { - fixed_size = offsetof(struct qla2300_fw_dump, data_ram); - mem_size = (ha->fw_memory_size - 0x11000 + 1) * - sizeof(uint16_t); - } else if (IS_FWI2_CAPABLE(ha)) { - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) - fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem); - else if (IS_QLA81XX(ha)) - fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); - else if (IS_QLA25XX(ha)) - fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem); - else - fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); - - mem_size = (ha->fw_memory_size - 0x10 + 1) * - sizeof(uint32_t); - if (ha->mqenable) { - if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) - mq_size = sizeof(struct qla2xxx_mq_chain); - /* -* Allocate maximum buffer size for all queues. -* Resizing must be done at end-of-dump processing. -*/ - mq_size += ha->max_req_queues * - (req->length * sizeof(request_t)); - mq_size += ha->max_rsp_queues * - (rsp->length * sizeof(response_t)); - } - if (ha->tgt.atio_ring) - mq_size += ha->tgt.atio_q_length * sizeof(request_t); + if (IS_FWI2_CAPABLE(ha)) { /* Allocate memory for Fibre Channel Event Buffer. */ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA27XX(ha)) goto try_eft; -try_fce: if (ha->fce) dma_free_coherent(>pdev->dev, FCE_SIZE, ha->fce, ha->fce_dma); @@ -2684,7 +2641,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) 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; ha->flags.fce_enabled = 1; ha->fce_dma = tc_dma; ha->fce = tc; @@ -2701,7 +2657,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) ql_log(ql_log_warn, vha, 0x00c1, "Unable to allocate (%d KB) for EFT.\n", EFT_SIZE / 1024); - goto cont_alloc; + goto eft_err; } rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); @@ -2710,17 +2666,76 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) "Unable to initialize EFT (%d).\n", rval); dma_free_coherent(>pdev->dev, EFT_SIZE, tc, tc_dma); - goto cont_alloc; + goto eft_err; }
[PATCH 31/43] qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling
From: Quinn Tranadd ability to use gpnft/gnnft to handle RSCN. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 7 +++ drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_gs.c | 99 - drivers/scsi/qla2xxx/qla_init.c | 65 ++- drivers/scsi/qla2xxx/qla_os.c | 1 + 5 files changed, 113 insertions(+), 60 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index db1f68c3e074..f061483475ce 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3022,6 +3022,11 @@ struct ct_sns_gpnft_pkt { } p; }; +enum scan_flags_t { + SF_SCANNING = BIT_0, + SF_QUEUED = BIT_1, +}; + struct fab_scan_rp { port_id_t id; u8 port_name[8]; @@ -3031,6 +3036,8 @@ struct fab_scan_rp { struct fab_scan { struct fab_scan_rp *l; u32 size; + enum scan_flags_t scan_flags; + struct delayed_work scan_work; }; /* diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 650ec54e3255..91db1924ca79 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -669,6 +669,7 @@ int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *); void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea); void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *); +void qla_scan_work_fn(struct work_struct *); /* * Global Function Prototypes in qla_attr.c source file. diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 0fcbdcaba127..903f924f6273 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3025,8 +3025,10 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea) fc_port_t *fcport = ea->fcport; ql_dbg(ql_dbg_disc, vha, 0x201d, - "%s %8phC login state %d\n", - __func__, fcport->port_name, fcport->fw_login_state); + "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n", + __func__, fcport->port_name, fcport->disc_state, + fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2, + fcport->rscn_gen, ea->sp->gen1, fcport->loop_id); if (fcport->disc_state == DSC_DELETE_PEND) return; @@ -3034,9 +3036,9 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea) if (ea->sp->gen2 != fcport->login_gen) { /* PLOGI/PRLI/LOGO came in while cmd was out.*/ ql_dbg(ql_dbg_disc, vha, 0x201e, - "%s %8phC generation changed rscn %d|%d login %d|%d \n", + "%s %8phC generation changed rscn %d|%d n", __func__, fcport->port_name, fcport->last_rscn_gen, - fcport->rscn_gen, fcport->last_login_gen, fcport->login_gen); + fcport->rscn_gen); return; } @@ -3264,11 +3266,10 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea) struct fc_port *fcport = ea->fcport; ql_dbg(ql_dbg_disc, vha, 0x20d8, - "%s %8phC DS %d LS %d rscn %d|%d login %d|%d lid %d\n", + "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n", __func__, fcport->port_name, fcport->disc_state, - fcport->fw_login_state, fcport->last_rscn_gen, fcport->rscn_gen, - fcport->last_login_gen, fcport->login_gen, - fcport->loop_id); + fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen, + ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1, fcport->loop_id); if (fcport->disc_state == DSC_DELETE_PEND) return; @@ -3276,10 +3277,8 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea) if (ea->sp->gen2 != fcport->login_gen) { /* target side must have changed it. */ ql_dbg(ql_dbg_disc, vha, 0x20d3, - "%s %8phC generation changed rscn %d|%d login %d|%d\n", - __func__, fcport->port_name, fcport->last_rscn_gen, - fcport->rscn_gen, fcport->last_login_gen, - fcport->login_gen); + "%s %8phC generation changed\n", + __func__, fcport->port_name); return; } else if (ea->sp->gen1 != fcport->rscn_gen) { ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n", @@ -3911,6 +3910,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) bool found; u8 fc4type = sp->gen2; struct fab_scan_rp *rp; + unsigned long flags; ql_dbg(ql_dbg_disc, vha, 0x, "%s enter\n", __func__);
[PATCH 20/43] qla2xxx: Use known NPort ID for Management Server login
Signed-off-by: Himanshu Madhani--- drivers/scsi/qla2xxx/qla_def.h | 4 ++-- drivers/scsi/qla2xxx/qla_mid.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 9fcc0a5ff8df..749f3e457346 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -246,8 +246,8 @@ * There is no correspondence between an N-PORT id and an AL_PA. Therefore the * valid range of an N-PORT id is 0 through 0x7ef. */ -#define NPH_LAST_HANDLE0x7ef -#define NPH_MGMT_SERVER0x7fa /* FA */ +#define NPH_LAST_HANDLE0x7ee +#define NPH_MGMT_SERVER0x7ef /* EF */ #define NPH_SNS0x7fc /* FC */ #define NPH_FABRIC_CONTROLLER 0x7fd /* FD */ #define NPH_F_PORT 0x7fe /* FE */ diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index b2fda398a098..a823fa6b7060 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -477,7 +477,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) "Couldn't allocate vp_id.\n"); goto create_vhost_failed; } - vha->mgmt_svr_loop_id = 10 + vha->vp_idx; + vha->mgmt_svr_loop_id = NPH_MGMT_SERVER; vha->dpc_flags = 0L; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 4ba249b9921d..4e7763848d81 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3036,7 +3036,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host = base_vha->host; base_vha->req = req; if (IS_QLA2XXX_MIDTYPE(ha)) - base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx; + base_vha->mgmt_svr_loop_id = NPH_MGMT_SERVER; else base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER + base_vha->vp_idx; -- 2.12.0
[PATCH 19/43] qla2xxx: Fix session cleanup for N2N
From: Quinn TranWhen connection type is N_Port to N_Port (point-to-point), there is a possibilty where initiator will not send PLOGI request and will directly send PRLI. In N2N connection the port has higher port name sends the PLOGI but not allow to send PRLI if is a target mode. Only initiator is allowed to send PRLI. Current driver code deletes old session when it receives PLOGI request. If we will not receive PLOGI request then we will not delete old session and create new session. Add check for N2N with PRLI receive only and trigger cleanup. For this case, the cleanup requires individual cmd abort instead of using implicit logout as a broad stroke flush. Signed-off-by: Krishna Kant Signed-off-by: Alexei Potashnik Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h| 11 ++ drivers/scsi/qla2xxx/qla_fw.h | 2 +- drivers/scsi/qla2xxx/qla_init.c | 151 +--- drivers/scsi/qla2xxx/qla_isr.c| 4 +- drivers/scsi/qla2xxx/qla_mbx.c| 38 - drivers/scsi/qla2xxx/qla_os.c | 41 +- drivers/scsi/qla2xxx/qla_target.c | 286 +- 7 files changed, 378 insertions(+), 155 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ba659aa9ae83..9fcc0a5ff8df 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3575,6 +3575,7 @@ struct qla_hw_data { uint32_tfw_init_done:1; uint32_tdetected_lr_sfp:1; uint32_tusing_lr_setting:1; + uint32_trida_fmt2:1; } flags; uint16_t max_exchg; @@ -4615,6 +4616,16 @@ struct sff_8247_a0 { #define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \ (IS_QLA27XX(_ha) || IS_QLA83XX(_ha))) +#define SAVE_TOPO(_ha) { \ + if (_ha->current_topology) \ + _ha->prev_topology = _ha->current_topology; \ +} + +#define N2N_TOPO(ha) \ + ((ha->prev_topology == ISP_CFG_N && !ha->current_topology) || \ +ha->current_topology == ISP_CFG_N || \ +!ha->current_topology) + #include "qla_target.h" #include "qla_gbl.h" #include "qla_dbg.h" diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index d5cef0727e72..5d8688e5bc7c 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -1392,7 +1392,7 @@ struct vp_rpt_id_entry_24xx { uint8_t port_name[8]; uint8_t node_name[8]; - uint32_t remote_nport_id; + uint8_t remote_nport_id[4]; uint32_t reserved_5; } f2; } u; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7a8c6ead6d0e..b4a96c80853f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -181,11 +181,6 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, if (!vha->flags.online) goto done; - if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) || - (fcport->fw_login_state == DSC_LS_PLOGI_COMP) || - (fcport->fw_login_state == DSC_LS_PRLI_PEND)) - goto done; - sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) goto done; @@ -1016,6 +1011,43 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) spin_unlock_irqrestore(>hw->tgt.sess_lock, flags); } /* gpdb event */ + +static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport) +{ + u8 login = 0; + + if (qla_tgt_mode_enabled(vha)) + return; + + if (qla_dual_mode_enabled(vha)) { + if (N2N_TOPO(vha->hw)) { + u64 mywwn, wwn; + + mywwn = wwn_to_u64(vha->port_name); + wwn = wwn_to_u64(fcport->port_name); + if (mywwn > wwn) + login = 1; + else if ((fcport->fw_login_state == DSC_LS_PLOGI_COMP) + && time_after_eq(jiffies, + fcport->plogi_nack_done_deadline)) + login = 1; + } else { + login = 1; + } + } else { + /* initiator mode */ + login = 1; + } + + if (login) { + ql_dbg(ql_dbg_disc, vha, 0x20bf, + "%s %d %8phC post login\n", + __func__, __LINE__, fcport->port_name); + fcport->disc_state = DSC_LOGIN_PEND; + qla2x00_post_async_login_work(vha, fcport, NULL); + } +} + int
[PATCH 13/43] qla2xxx: Use shadow register for ISP27XX
From: Quinn TranFor ISP27XX, use shadow register to read FW provided REQQ's consumer index. The shadow register is dma'ed by firmware. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_iocb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 417c40f21244..519a0d2920b8 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2192,7 +2192,9 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp) skip_cmd_array: /* Check for room on request queue. */ if (req->cnt < req_cnt + 2) { - if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) + if (qpair->use_shadow_reg) + cnt = *req->out_ptr; + else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) cnt = RD_REG_DWORD(>isp25mq.req_q_out); else if (IS_P3P_TYPE(ha)) cnt = RD_REG_DWORD(>isp82.req_q_out); -- 2.12.0
[PATCH 17/43] qla2xxx: Allow target mode to accept PRLI in dual mode
From: Quinn TranFor Dual Mode, Initiator side of the driver finish login, target side receive PRLI, but driver terminates PRLI. This patch allows target side to go ahead and accept PRLI. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 5 + drivers/scsi/qla2xxx/qla_target.c | 16 +--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 28248adb611d..7a8c6ead6d0e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1540,6 +1540,7 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) port_id_t cid; /* conflict Nport id */ u16 lid; struct fc_port *conflict_fcport; + unsigned long flags; switch (ea->data[0]) { case MBS_COMMAND_COMPLETE: @@ -1560,10 +1561,14 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) ea->fcport->loop_id, ea->fcport->d_id.b24); set_bit(ea->fcport->loop_id, vha->hw->loop_id_map); + spin_lock_irqsave(>hw->tgt.sess_lock, flags); ea->fcport->loop_id = FC_NO_LOOP_ID; ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset; ea->fcport->logout_on_delete = 1; ea->fcport->send_els_logo = 0; + ea->fcport->fw_login_state = DSC_LS_PRLI_COMP; + spin_unlock_irqrestore(>hw->tgt.sess_lock, flags); + qla24xx_post_gpdb_work(vha, ea->fcport, 0); } break; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 835721f077f6..eaa43d3d5a91 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -4703,7 +4703,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, uint16_t wd3_lo; int res = 0; struct qlt_plogi_ack_t *pla; - unsigned long flags; + unsigned long flags = 0; wwn = wwn_to_u64(iocb->u.isp24.port_name); @@ -4839,8 +4839,14 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, } if (sess != NULL) { - if (sess->fw_login_state != DSC_LS_PLOGI_PEND && - sess->fw_login_state != DSC_LS_PLOGI_COMP) { + spin_lock_irqsave(>ha->tgt.sess_lock, flags); + switch (sess->fw_login_state) { + case DSC_LS_PLOGI_COMP: + case DSC_LS_PRLI_COMP: + break; + default: + spin_unlock_irqrestore(>ha->tgt.sess_lock, + flags); /* * Impatient initiator sent PRLI before last * PLOGI could finish. Will force him to re-try, @@ -4851,6 +4857,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, sess); qlt_send_term_imm_notif(vha, iocb, 1); res = 0; + spin_lock_irqsave(>ha->tgt.sess_lock, + flags); break; } @@ -4874,6 +4882,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, sess->port_type = FCT_INITIATOR; else sess->port_type = FCT_TARGET; + + spin_unlock_irqrestore(>ha->tgt.sess_lock, flags); } res = 1; /* send notify ack */ -- 2.12.0
[PATCH 08/43] qla2xxx: Chip reset uses wrong lock during IO flush.
From: Quinn TranAs part of chip reset, all commands from all QPairs are flushed. This patch fixes code to use Q Pair lock for flush instead of using old hardware_lock. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_os.c | 139 +++--- 1 file changed, 64 insertions(+), 75 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7f361e93c593..4a542a5a976d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1709,94 +1709,83 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) return QLA_SUCCESS; } -void -qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) +static void +__qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) { - int que, cnt, status; + int cnt; unsigned long flags; srb_t *sp; + scsi_qla_host_t *vha = qp->vha; struct qla_hw_data *ha = vha->hw; struct req_que *req; struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; struct qla_tgt_cmd *cmd; uint8_t trace = 0; - spin_lock_irqsave(>hardware_lock, flags); - for (que = 0; que < ha->max_req_queues; que++) { - req = ha->req_q_map[que]; - if (!req) - continue; - if (!req->outstanding_cmds) - continue; - for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { - sp = req->outstanding_cmds[cnt]; - if (sp) { - req->outstanding_cmds[cnt] = NULL; - if (sp->cmd_type == TYPE_SRB) { - if (sp->type == SRB_NVME_CMD || - sp->type == SRB_NVME_LS) { - sp_get(sp); - spin_unlock_irqrestore( - >hardware_lock, flags); - qla_nvme_abort(ha, sp); - spin_lock_irqsave( - >hardware_lock, flags); - } else if (GET_CMD_SP(sp) && - !ha->flags.eeh_busy && - (!test_bit(ABORT_ISP_ACTIVE, - >dpc_flags)) && - (sp->type == SRB_SCSI_CMD)) { - /* -* Don't abort commands in -* adapter during EEH -* recovery as it's not -* accessible/responding. -* -* Get a reference to the sp -* and drop the lock. The -* reference ensures this -* sp->done() call and not the -* call in qla2xxx_eh_abort() -* ends the SCSI command (with -* result 'res'). -*/ - sp_get(sp); - spin_unlock_irqrestore( - >hardware_lock, flags); - status = qla2xxx_eh_abort( - GET_CMD_SP(sp)); - spin_lock_irqsave( - >hardware_lock, flags); - /* -* Get rid of extra reference -* if immediate exit from -* ql2xxx_eh_abort -*/ - if (status == FAILED && - (qla2x00_isp_reg_stat(ha))) - atomic_dec( - >ref_count); - } - qla_put_iocbs(sp->qpair, >iores); - sp->done(sp, res); - } else { -
[PATCH 14/43] qla2xxx: Add option for use reserve exch for ELS
From: Quinn TranAdd option to tell FW to reserve 1/2 of emergency exchanges for ELS. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 6 ++ drivers/scsi/qla2xxx/qla_os.c | 6 ++ 3 files changed, 13 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index fb1c9ffdc05a..88c7746c023a 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -149,6 +149,7 @@ extern int ql2xnvmeenable; extern int ql2xautodetectsfp; extern int ql2xenablemsix; extern int ql2xtrackfwres; +extern int qla2xuseresexchforels; extern int qla2x00_loop_reset(scsi_qla_host_t *); extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 61b74fd220a3..6223dfe20767 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3387,6 +3387,12 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) ha->fw_options[2] |= BIT_4; else ha->fw_options[2] &= ~BIT_4; + + /* Reserve 1/2 of emergency exchanges for ELS.*/ + if (qla2xuseresexchforels) + ha->fw_options[2] |= BIT_8; + else + ha->fw_options[2] &= ~BIT_8; } ql_dbg(ql_dbg_init, vha, 0x00e8, diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 66e6fe73a035..fd107c4feda5 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -282,6 +282,12 @@ module_param(ql2xtrackfwres, int, 0444); MODULE_PARM_DESC(ql2xtrackfwres, "Track FW resource. 0(default): disabled"); +int qla2xuseresexchforels; +module_param(qla2xuseresexchforels, int, 0444); +MODULE_PARM_DESC(qla2xuseresexchforels, +"Reserve 1/2 of emergency exchanges for ELS.\n" +" 0 (default): disabled"); + /* * SCSI host template entry points */ -- 2.12.0
[PATCH 16/43] qla2xxx: Don't call dma_free_coherent with IRQ disabled.
From: Giridhar MalavaliThe logo ELS command allocates dma coherent memory for the data payload and serialize the completions. When this command times out, the timeout routine completes the thread waiting for completion which in turn cleanup resources allocated for this ELS command processing. Don't call generic sp->free routine when this ELS command times out to avoid to double freeing of the same resources. Signed-off-by: Giridhar Malavali Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 900f6d3f3a3a..28248adb611d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -59,7 +59,8 @@ qla2x00_sp_timeout(struct timer_list *t) req->outstanding_cmds[sp->handle] = NULL; iocb = >u.iocb_cmd; iocb->timeout(sp); - sp->free(sp); + if (sp->type != SRB_ELS_DCMD) + sp->free(sp); spin_unlock_irqrestore(>hw->hardware_lock, flags); } -- 2.12.0
[PATCH 10/43] qla2xxx: Replace GPDB with async ADISC command
From: Quinn TranReplace call to Get Port DataBase MB with PDO_FORCE_ADISC flag with async ADISC command so driver can see ADISC command has error or not. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 2 ++ drivers/scsi/qla2xxx/qla_gs.c | 20 +++- drivers/scsi/qla2xxx/qla_init.c | 68 +++-- 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 8fbe1736a1a4..18b393453002 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2320,6 +2320,7 @@ enum discovery_state { DSC_GPSC, DSC_UPD_FCPORT, DSC_LOGIN_COMPLETE, + DSC_ADISC, DSC_DELETE_PEND, }; @@ -2346,6 +2347,7 @@ enum fcport_mgt_event { FCME_GPNID_DONE, FCME_GFFID_DONE, FCME_DELETE_DONE, + FCME_ADISC_DONE, }; enum rscn_addr_format { diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 6aa6dd74fe86..b1c6485c307b 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -2867,15 +2867,19 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea) "%s %d %8phC post %s\n", __func__, __LINE__, fcport->port_name, (atomic_read(>state) == - FCS_ONLINE) ? "gpdb" : "gnl"); + FCS_ONLINE) ? "adisc" : "gnl"); if (atomic_read(>state) == - FCS_ONLINE) - qla24xx_post_gpdb_work(vha, - fcport, PDO_FORCE_ADISC); - else + FCS_ONLINE) { + u16 data[2]; + + data[0] = data[1] = 0; + qla2x00_post_async_adisc_work( + vha, fcport, data); + } else { qla24xx_post_gnl_work(vha, fcport); + } break; } } else { /* fcport->d_id.b24 != ea->id.b24 */ @@ -3216,6 +3220,7 @@ void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp) void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) { fc_port_t *fcport, *conflict, *t; + u16 data[2]; ql_dbg(ql_dbg_disc, vha, 0x, "%s %d port_id: %06x\n", @@ -3290,8 +3295,9 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) ql_dbg(ql_dbg_disc, vha, 0x210d, "%s %d %8phC revalidate session with ADISC\n", __func__, __LINE__, fcport->port_name); - qla24xx_post_gpdb_work(vha, fcport, - PDO_FORCE_ADISC); + data[0] = data[1] = 0; + qla2x00_post_async_adisc_work(vha, fcport, + data); break; case DSC_DELETED: ql_dbg(ql_dbg_disc, vha, 0x210d, diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 5cd04bfa5cae..0a1c287c2d66 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -41,6 +41,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *, struct event_arg *); static void qla24xx_handle_prli_done_event(struct scsi_qla_host *, struct event_arg *); +static void qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *); /* SRB Extensions -- */ @@ -277,17 +278,31 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) fcport->flags &= ~FCF_ASYNC_SENT; return rval; } +static +void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) +{ + qla24xx_handle_gpdb_event(vha, ea); +} static void qla2x00_async_adisc_sp_done(void *ptr, int res) { srb_t *sp = ptr; struct scsi_qla_host *vha = sp->vha; - struct srb_iocb *lio = >u.iocb_cmd; + struct event_arg ea; + + ql_dbg(ql_dbg_disc, vha, 0x2066, + "Async done-%s res %x %8phC\n", +
[PATCH 21/43] qla2xxx: Remove calling cancel_work_sync()
From: Sawan ChandakThis is blocking call and issue is seen, when called in interrupt context. __cancel_work_timer+0x140/0x210 ? ql_dbg+0xcb/0x110 [qla2xxx] cancel_work_sync+0x10/0x20 qlt_schedule_sess_for_deletion+0x89/0x170 [qla2xxx] qla24xx_handle_gpnid_event+0x146/0x4a0 [qla2xxx] qla2x00_fcport_event_handler+0x14b/0x290 [qla2xxx] qla2x00_async_gpnid_sp_done+0x118/0x240 [qla2xxx] qla24xx_els_ct_entry.isra.15+0x1df/0x2b0 [qla2xxx] ? qla24xx_msix_rsp_q+0x39/0xf0 [qla2xxx] qla24xx_process_response_queue+0xae/0x270 [qla2xxx] qla24xx_msix_rsp_q+0x8a/0xf0 [qla2xxx] __handle_irq_event_percpu+0x3c/0x350 handle_irq_event_percpu+0x32/0x80 handle_irq_event+0x39/0x60 handle_edge_irq+0x8c/0x140 handle_irq+0xab/0x130 ? _local_bh_enable+0x21/0x50 do_IRQ+0x5e/0x120 common_interrupt+0x9d/0x9d RIP: 0010:cpuidle_enter_state+0xe9/0x320 Signed-off-by: Sawan Chandak Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_target.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 71be1a95ba86..002fe05dd344 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1234,8 +1234,6 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess, ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, "Scheduling sess %p for deletion\n", sess); - /* use cancel to push work element through before re-queue */ - cancel_work_sync(>del_work); INIT_WORK(>del_work, qla24xx_delete_sess_fn); queue_work(sess->vha->hw->wq, >del_work); } -- 2.12.0
[PATCH 04/43] qla2xxx: Use chip reset to bring down laser on unload.
From: Quinn TranCurrent code uses Stop Firmware MB cmd to stop the chip before driver unload. This will leave the laser in its current state. This give the illusion of this adapter is still alive. For 8G & newer adapters, use chip reset to stop the chip and bring down the laser. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_os.c | 52 ++- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 789030c9dd26..987bade1c606 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -294,7 +294,6 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *); static void qla2x00_clear_drv_active(struct qla_hw_data *); static void qla2x00_free_device(scsi_qla_host_t *); -static void qla83xx_disable_laser(scsi_qla_host_t *vha); static int qla2xxx_map_queues(struct Scsi_Host *shost); static void qla2x00_destroy_deferred_work(struct qla_hw_data *); @@ -3449,8 +3448,13 @@ qla2x00_shutdown(struct pci_dev *pdev) if (ha->eft) qla2x00_disable_eft_trace(vha); - /* Stop currently executing firmware. */ - qla2x00_try_to_stop_firmware(vha); + if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) { + if (ha->flags.fw_started) + qla2x00_abort_isp_cleanup(vha); + } else { + /* Stop currently executing firmware. */ + qla2x00_try_to_stop_firmware(vha); + } /* Turn adapter off line */ vha->flags.online = 0; @@ -3629,10 +3633,6 @@ qla2x00_remove_one(struct pci_dev *pdev) qla84xx_put_chip(base_vha); - /* Laser should be disabled only for ISP2031 */ - if (IS_QLA2031(ha)) - qla83xx_disable_laser(base_vha); - /* Disable timer */ if (base_vha->timer_active) qla2x00_stop_timer(base_vha); @@ -3693,8 +3693,16 @@ qla2x00_free_device(scsi_qla_host_t *vha) if (ha->eft) qla2x00_disable_eft_trace(vha); - /* Stop currently executing firmware. */ - qla2x00_try_to_stop_firmware(vha); + if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) { + if (ha->flags.fw_started) + qla2x00_abort_isp_cleanup(vha); + } else { + if (ha->flags.fw_started) { + /* Stop currently executing firmware. */ + qla2x00_try_to_stop_firmware(vha); + ha->flags.fw_started = 0; + } + } vha->flags.online = 0; @@ -6617,32 +6625,6 @@ qla2xxx_pci_resume(struct pci_dev *pdev) ha->flags.eeh_busy = 0; } -static void -qla83xx_disable_laser(scsi_qla_host_t *vha) -{ - uint32_t reg, data, fn; - struct qla_hw_data *ha = vha->hw; - struct device_reg_24xx __iomem *isp_reg = >iobase->isp24; - - /* pci func #/port # */ - ql_dbg(ql_dbg_init, vha, 0x004b, - "Disabling Laser for hba: %p\n", vha); - - fn = (RD_REG_DWORD(_reg->ctrl_status) & - (BIT_15|BIT_14|BIT_13|BIT_12)); - - fn = (fn >> 12); - - if (fn & 1) - reg = PORT_1_2031; - else - reg = PORT_0_2031; - - data = LASER_OFF_2031; - - qla83xx_wr_reg(vha, reg, data); -} - static int qla2xxx_map_queues(struct Scsi_Host *shost) { int rc; -- 2.12.0
[PATCH 18/43] qla2xxx: Tweak resource count dump
From: Quinn TranFetch actual data from firmware instead of static data at chip reset time. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_dfs.c | 30 -- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 30 ++ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index 87a18a00d509..4f0415e158cb 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -127,21 +127,23 @@ static int qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) { struct scsi_qla_host *vha = s->private; - struct qla_hw_data *ha = vha->hw; + uint16_t mb[MAX_IOCB_MB_REG]; + int rc; - seq_puts(s, "FW Resource count\n\n"); - seq_printf(s, "Original TGT exchg count[%d]\n", - ha->orig_fw_tgt_xcb_count); - seq_printf(s, "current TGT exchg count[%d]\n", - ha->cur_fw_tgt_xcb_count); - seq_printf(s, "original Initiator Exchange count[%d]\n", - ha->orig_fw_xcb_count); - seq_printf(s, "Current Initiator Exchange count[%d]\n", - ha->cur_fw_xcb_count); - seq_printf(s, "Original IOCB count[%d]\n", ha->orig_fw_iocb_count); - seq_printf(s, "Current IOCB count[%d]\n", ha->cur_fw_iocb_count); - seq_printf(s, "MAX VP count[%d]\n", ha->max_npiv_vports); - seq_printf(s, "MAX FCF count[%d]\n", ha->fw_max_fcf_count); + rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG); + if (rc != QLA_SUCCESS) { + seq_printf(s, "Mailbox Command failed %d, mb %#x", rc, mb[0]); + } else { + seq_puts(s, "FW Resource count\n\n"); + seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]); + seq_printf(s, "current TGT exchg count[%d]\n", mb[2]); + seq_printf(s, "original Initiator Exchange count[%d]\n", mb[3]); + seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[6]); + seq_printf(s, "Original IOCB count[%d]\n", mb[7]); + seq_printf(s, "Current IOCB count[%d]\n", mb[10]); + seq_printf(s, "MAX VP count[%d]\n", mb[11]); + seq_printf(s, "MAX FCF count[%d]\n", mb[12]); + } return 0; } diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index ea8f24e07409..2e0907994579 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -504,6 +504,7 @@ int qla24xx_get_port_login_templ(scsi_qla_host_t *, dma_addr_t, extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *); extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t); +int qla24xx_res_count_wait(struct scsi_qla_host *, uint16_t *, int); /* * Global Function Prototypes in qla_isr.c source file. diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 956d121cc396..0c8ad7b31294 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -18,6 +18,7 @@ static struct mb_cmd_name { {MBC_GET_PORT_DATABASE, "GPDB"}, {MBC_GET_ID_LIST, "GIDList"}, {MBC_GET_LINK_PRIV_STATS, "Stats"}, + {MBC_GET_RESOURCE_COUNTS, "ResCnt"}, }; static const char *mb_to_str(uint16_t cmd) @@ -6273,3 +6274,32 @@ qla2x00_read_sfp_dev(struct scsi_qla_host *vha, char *buf, int count) return rval; } + +int qla24xx_res_count_wait(struct scsi_qla_host *vha, +uint16_t *out_mb, int out_mb_sz) +{ + int rval = QLA_FUNCTION_FAILED; + mbx_cmd_t mc; + + if (!vha->hw->flags.fw_started) + goto done; + + memset(, 0, sizeof(mc)); + mc.mb[0] = MBC_GET_RESOURCE_COUNTS; + + rval = qla24xx_send_mb_cmd(vha, ); + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0x, + "%s: fail\n", __func__); + } else { + if (out_mb_sz <= SIZEOF_IOCB_MB_REG) + memcpy(out_mb, mc.mb, out_mb_sz); + else + memcpy(out_mb, mc.mb, SIZEOF_IOCB_MB_REG); + + ql_dbg(ql_dbg_mbx, vha, 0x, + "%s: done\n", __func__); + } +done: + return rval; +} -- 2.12.0
[PATCH 29/43] qla2xxx: Fix GPNFT/GNNFT error handling
From: Quinn Tranretry gpnft/gnnft if error is encountered. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_gs.c | 15 +++ drivers/scsi/qla2xxx/qla_init.c | 8 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 0e84381e227e..0fcbdcaba127 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3927,6 +3927,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) ql_dbg(ql_dbg_disc, vha, 0x, "GPNFT failed. FC4type %x. Rescanning.\n", fc4type); + set_bit(LOCAL_LOOP_UPDATE, >dpc_flags); set_bit(LOOP_RESYNC_NEEDED, >dpc_flags); goto out; } @@ -4036,6 +4037,19 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) "Async done-%s res %x FC4Type %x\n", sp->name, res, sp->gen2); + if (res) { + unsigned long flags; + + ql_dbg(ql_dbg_disc, sp->vha, 0x, + "Async done-%s timed out.\n", + sp->name); + sp->free(sp); + set_bit(LOCAL_LOOP_UPDATE, >dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, >dpc_flags); + qla2xxx_wake_dpc(vha); + return; + } + if (!res) { port_id_t id; u64 wwn; @@ -4097,6 +4111,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) "Async done-%s unable to alloc work element\n", sp->name); sp->free(sp); + set_bit(LOCAL_LOOP_UPDATE, >dpc_flags); set_bit(LOOP_RESYNC_NEEDED, >dpc_flags); return; } diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 152c808b272b..e58faa1e984c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -683,15 +683,15 @@ qla24xx_async_gnl_sp_done(void *s, int res) } } - id.b.domain = e->port_id[0]; + id.b.domain = e->port_id[2]; id.b.area = e->port_id[1]; - id.b.al_pa = e->port_id[2]; + id.b.al_pa = e->port_id[0]; id.b.rsvd_1 = 0; if (!found && wwn && !IS_SW_RESV_ADDR(id)) { ql_dbg(ql_dbg_disc, vha, 0x2065, - "%s %d %8phC post new sess\n", - __func__, __LINE__, (u8 *)); + "%s %d %8phC %06x post new sess\n", + __func__, __LINE__, (u8 *), id.b24); wwnn = wwn_to_u64(e->node_name); qla24xx_post_newsess_work(vha, , (u8 *), (u8 *), NULL, FC4_TYPE_UNKNOWN); -- 2.12.0
[PATCH 12/43] qla2xxx: Enable ATIO interrupt handshake for ISP27XX
From: Quinn TranEnable ATIO Q interrupt handshake for ISP27XX. This patch coalesce ATIO's interrupts for Quad port ISP27XX adapter. Interrupt coalesce allows performance to scale for this specific case. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_target.c | 39 +-- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0d77b2f67077..835721f077f6 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -6598,7 +6598,9 @@ void qlt_24xx_config_rings(struct scsi_qla_host *vha) { struct qla_hw_data *ha = vha->hw; - struct init_cb_24xx *icb; + struct qla_msix_entry *msix = >msix_entries[2]; + struct init_cb_24xx *icb = (struct init_cb_24xx *)ha->init_cb; + if (!QLA_TGT_MODE_ENABLED()) return; @@ -6606,19 +6608,28 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha) WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), 0); RD_REG_DWORD(ISP_ATIO_Q_OUT(vha)); - icb = (struct init_cb_24xx *)ha->init_cb; - - if ((ql2xenablemsix != 0) && IS_ATIO_MSIX_CAPABLE(ha)) { - struct qla_msix_entry *msix = >msix_entries[2]; - - icb->msix_atio = cpu_to_le16(msix->entry); - ql_dbg(ql_dbg_init, vha, 0xf072, - "Registering ICB vector 0x%x for atio que.\n", - msix->entry); - } else if (ql2xenablemsix == 0) { - icb->firmware_options_2 |= cpu_to_le32(BIT_26); - ql_dbg(ql_dbg_init, vha, 0xf07f, - "Registering INTx vector for ATIO.\n"); + if (ha->flags.msix_enabled) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA2071(ha)) { + /* 4 ports Baker: Enable Interrupt Handshake */ + icb->msix_atio = 0; + icb->firmware_options_2 |= BIT_26; + } else { + icb->msix_atio = cpu_to_le16(msix->entry); + icb->firmware_options_2 &= ~BIT_26; + } + ql_dbg(ql_dbg_init, vha, 0xf072, + "Registering ICB vector 0x%x for atio que.\n", + msix->entry); + } + } else { + /* INTx|MSI */ + if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + icb->msix_atio = 0; + icb->firmware_options_2 |= BIT_26; + ql_dbg(ql_dbg_init, vha, 0xf072, + "%s: Use INTx for ATIOQ.\n", __func__); + } } } -- 2.12.0
[PATCH 15/43] qla2xxx: Add ability to send PRLO
From: Quinn TranAdd ability to send Implicit PRLO to flush IOs from FW back to driver. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 5 drivers/scsi/qla2xxx/qla_gbl.h | 8 ++ drivers/scsi/qla2xxx/qla_gs.c | 1 + drivers/scsi/qla2xxx/qla_init.c | 59 + drivers/scsi/qla2xxx/qla_iocb.c | 17 drivers/scsi/qla2xxx/qla_os.c | 9 +++ 6 files changed, 99 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a2c0f3d78b35..ba659aa9ae83 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -514,6 +514,7 @@ enum { SPCN_NVME_LS, SPCN_NVME_CMD, SPCN_CTRL_VP, + SPCN_PRLO, }; struct sp_name { @@ -544,6 +545,8 @@ struct sp_name { #define SRB_NVME_LS20 #define SRB_PRLI_CMD 21 #define SRB_CTRL_VP22 +#define SRB_PRLO_CMD 23 + enum { TYPE_SRB, TYPE_TGT_CMD, @@ -3184,6 +3187,8 @@ enum qla_work_type { QLA_EVT_GNL, QLA_EVT_NACK, QLA_EVT_RELOGIN, + QLA_EVT_ASYNC_PRLO, + QLA_EVT_ASYNC_PRLO_DONE, }; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 88c7746c023a..ea8f24e07409 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -66,6 +66,7 @@ extern void qla84xx_put_chip(struct scsi_qla_host *); extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); +extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); @@ -109,6 +110,13 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); int qla24xx_detect_sfp(scsi_qla_host_t *vha); int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); +void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *, +uint16_t *); +extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *, +uint16_t *); +extern int qla2x00_post_async_prlo_done_work(struct scsi_qla_host *, +fc_port_t *, uint16_t *); + /* * Global Data in qla_os.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index b1c6485c307b..22702a8f5ce6 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -42,6 +42,7 @@ struct sp_name sp_str[] = { { SPCN_NVME_LS, "nvme_ls" }, { SPCN_NVME_CMD, "nvme_cmd" }, { SPCN_CTRL_VP, "ctrl_vp" }, + { SPCN_PRLO, "prlo" }, }; const char *sp_to_str(uint16_t cmd) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 6223dfe20767..900f6d3f3a3a 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -278,6 +278,65 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) fcport->flags &= ~FCF_ASYNC_SENT; return rval; } + +void +qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport, +uint16_t *data) +{ + /* Don't re-login in target mode */ + if (!fcport->tgt_session) + qla2x00_mark_device_lost(vha, fcport, 1, 0); + qlt_logo_completion_handler(fcport, data[0]); +} + +static void +qla2x00_async_prlo_sp_done(void *s, int res) +{ + srb_t *sp = (srb_t *)s; + struct srb_iocb *lio = >u.iocb_cmd; + struct scsi_qla_host *vha = sp->vha; + + if (!test_bit(UNLOADING, >dpc_flags)) + qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport, + lio->u.logio.data); + sp->free(sp); +} + +int +qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport) +{ + srb_t *sp; + struct srb_iocb *lio; + int rval; + + rval = QLA_FUNCTION_FAILED; + sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + if (!sp) + goto done; + + sp->type = SRB_PRLO_CMD; + sp->name = sp_to_str(SPCN_PRLO); + qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); + + lio = >u.iocb_cmd; + lio->timeout = qla2x00_async_iocb_timeout; + sp->done = qla2x00_async_prlo_sp_done; + rval = qla2x00_start_sp(sp); + if (rval != QLA_SUCCESS) + goto done_free_sp; + + ql_dbg(ql_dbg_disc, vha, 0x2070, + "Async-prlo - 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: + sp->free(sp); +done: + return rval; +} + static void
[PATCH 07/43] qla2xxx: Add ability to track IOCB resource for FW
From: Quinn TranFW has a finite number of IOCB resource. Driver will track it via the ql2xtrackfwres module parameter. User will be able to reserve X number of IOCBs for either the target path or initiator path. The left over IOCBs are shared between the 2 modes. The shared pool will be used 1st before tapping into the reserve pool. usage: modprobe qla2xxx ql2xtrackfwres=1 qlini_mode=dual echo 256 > /sys/class/scsi_host/hostX/device/reserve_ini_iocbs echo 256 > /sys/class/scsi_host/hostX/device/reserve_tgt_iocbs Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h| 50 +- drivers/scsi/qla2xxx/qla_dfs.c| 315 ++ drivers/scsi/qla2xxx/qla_gbl.h| 1 + drivers/scsi/qla2xxx/qla_init.c | 36 + drivers/scsi/qla2xxx/qla_inline.h | 102 drivers/scsi/qla2xxx/qla_iocb.c | 45 ++ drivers/scsi/qla2xxx/qla_isr.c| 10 +- drivers/scsi/qla2xxx/qla_os.c | 10 ++ drivers/scsi/qla2xxx/qla_target.c | 24 +++ drivers/scsi/qla2xxx/qla_target.h | 3 +- 10 files changed, 592 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 5e509763a419..8fbe1736a1a4 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -549,6 +549,12 @@ enum { TYPE_TGT_CMD, }; +struct iocb_resource { + u8 res_type; + u8 pad; + u16 iocb_cnt; +}; + typedef struct srb { /* * Do not move cmd_type field, it needs to @@ -556,6 +562,7 @@ typedef struct srb { */ uint8_t cmd_type; uint8_t pad[3]; + struct iocb_resource iores; atomic_t ref_count; wait_queue_head_t nvme_ls_waitq; struct fc_port *fcport; @@ -3396,6 +3403,7 @@ struct qla_qpair { uint32_t fw_started:1; uint32_t enable_class_2:1; uint32_t enable_explicit_conf:1; + uint32_t fw_res_tracking:1; uint32_t use_shadow_reg:1; uint16_t id;/* qp number used with FW */ @@ -3433,6 +3441,24 @@ struct scsi_qlt_host { struct qla_tgt *qla_tgt; }; +struct qla_fw_resources { + spinlock_t rescnt_lock; +#define DEF_RES_INI_IOCBS 256 +#define DEF_RES_TGT_IOCBS 256 +#define DEF_RES_BUSY_IOCBS 32 + u32 tgt_iocbs_reserve; + u32 ini_iocbs_reserve; + u32 busy_iocbs_reserve; + u32 tgt_iocbs_max; + u32 ini_iocbs_max; + u32 share_iocbs_max; + + /* these fields start high */ + atomic_t share_iocbs_used; + atomic_t tgt_iocbs_used; + atomic_t ini_iocbs_used; +}; + struct qlt_hw_data { /* Protected by hw lock */ uint32_t node_name_set:1; @@ -3461,6 +3487,9 @@ struct qlt_hw_data { struct dentry *dfs_tgt_sess; struct dentry *dfs_tgt_port_database; struct dentry *dfs_naqp; + struct dentry *dfs_ini_iocbs; + struct dentry *dfs_tgt_iocbs; + struct dentry *dfs_busy_iocbs; struct list_head q_full_list; uint32_t num_pend_cmds; @@ -3540,7 +3569,6 @@ struct qla_hw_data { uint32_tn2n_ae:1; uint32_tfw_started:1; uint32_tfw_init_done:1; - uint32_tdetected_lr_sfp:1; uint32_tusing_lr_setting:1; } flags; @@ -4103,6 +4131,7 @@ struct qla_hw_data { struct qlt_hw_data tgt; int allow_cna_fw_dump; + struct qla_fw_resources fwres; uint32_t fw_ability_mask; uint16_t min_link_speed; uint16_t max_speed_sup; @@ -4406,7 +4435,6 @@ struct qla2_sgx { #define QLA_QPAIR_MARK_NOT_BUSY(__qpair) \ atomic_dec(&__qpair->ref_count);\ - #define QLA_ENA_CONF(_ha) {\ int i;\ _ha->base_qpair->enable_explicit_conf = 1; \ @@ -4425,6 +4453,24 @@ struct qla2_sgx { } \ } +#define QLA_ENA_FW_RES_TRACKING(_ha) { \ + int i; \ + _ha->base_qpair->fw_res_tracking = 1; \ + for (i = 0; i < _ha->max_qpairs; i++) { \ + if (_ha->queue_pair_map[i]) \ + _ha->queue_pair_map[i]->fw_res_tracking = 1; \ + } \ +} + +#define QLA_DIS_FW_RES_TRACKING(_ha) { \ + int i; \ + _ha->base_qpair->fw_res_tracking = 0; \ + for (i = 0; i < _ha->max_qpairs; i++) { \ + if (_ha->queue_pair_map[i]) \ + _ha->queue_pair_map[i]->fw_res_tracking = 0; \ + } \ +} + /* * qla2x00 local function return status codes */ diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index d231e7156134..87a18a00d509 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -418,6 +418,278 @@ static const struct file_operations dfs_naqp_ops = { .write =
[PATCH 05/43] qla2xxx: Add boundary checks for exchanges to be offloaded
From: Quinn TranMax boundary for exchange off load is 32k exchanges. If system is unable to allocate large memory buffer to support this feature, then driver will reduce the number exchanges down to a value system can support. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 3 +++ drivers/scsi/qla2xxx/qla_os.c | 39 ++- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 50a570595969..ca3ef9360ab9 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -288,6 +288,8 @@ struct name_list_extended { #define ATIO_ENTRY_CNT_24XX4096/* Number of ATIO entries. */ #define RESPONSE_ENTRY_CNT_FX00256 /* Number of response entries.*/ #define FW_DEF_EXCHANGES_CNT 2048 +#define FW_MAX_EXCHANGES_CNT (32 * 1024) +#define REDUCE_EXCHANGES_CNT (8 * 1024) struct req_que; struct qla_tgt_sess; @@ -3542,6 +3544,7 @@ struct qla_hw_data { uint32_tusing_lr_setting:1; } flags; + uint16_t max_exchg; uint16_t long_range_distance; /* 32G & above */ #define LR_DISTANCE_5K 1 #define LR_DISTANCE_10K 0 diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 987bade1c606..029b95b2bd8a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2789,6 +2789,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->init_cb_size = sizeof(init_cb_t); ha->link_data_rate = PORT_SPEED_UNKNOWN; ha->optrom_size = OPTROM_SIZE_2300; + ha->max_exchg = FW_MAX_EXCHANGES_CNT; /* Assign ISP specific operations. */ if (IS_QLA2100(ha)) { @@ -4230,6 +4231,9 @@ qla2x00_number_of_exch(scsi_qla_host_t *vha, u32 *ret_cnt, u16 max_cnt) u32 temp; *ret_cnt = FW_DEF_EXCHANGES_CNT; + if (max_cnt > vha->hw->max_exchg) + max_cnt = vha->hw->max_exchg; + if (qla_ini_mode_enabled(vha)) { if (ql2xiniexchg > max_cnt) ql2xiniexchg = max_cnt; @@ -4259,8 +4263,8 @@ int qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha) { int rval; - u16 size, max_cnt; - u32 temp; + u16 size, max_cnt; + u32 actual_cnt, totsz; struct qla_hw_data *ha = vha->hw; if (!ha->flags.exchoffld_enabled) @@ -4277,16 +4281,19 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha) return rval; } - qla2x00_number_of_exch(vha, , max_cnt); - temp *= size; + qla2x00_number_of_exch(vha, _cnt, max_cnt); + ql_log(ql_log_info, vha, 0xd014, + "Actual exchange offload count: %d.\n", actual_cnt); + + totsz = actual_cnt * size; - if (temp != ha->exchoffld_size) { + if (totsz != ha->exchoffld_size) { qla2x00_free_exchoffld_buffer(ha); - ha->exchoffld_size = temp; + ha->exchoffld_size = totsz; ql_log(ql_log_info, vha, 0xd016, - "Exchange offload: max_count=%d, buffers=0x%x, total=%d.\n", - max_cnt, size, temp); + "Exchange offload: max_count=%d, actual count=%d entry sz=0x%x, total sz=0x%x\n", + max_cnt, actual_cnt, size, totsz); ql_log(ql_log_info, vha, 0xd017, "Exchange Buffers requested size = 0x%x\n", @@ -4297,7 +4304,21 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha) ha->exchoffld_size, >exchoffld_buf_dma, GFP_KERNEL); if (!ha->exchoffld_buf) { ql_log_pci(ql_log_fatal, ha->pdev, 0xd013, - "Failed to allocate memory for exchoffld_buf_dma.\n"); + "Failed to allocate memory for Exchange Offload.\n"); + + if (ha->max_exchg > + (FW_DEF_EXCHANGES_CNT + REDUCE_EXCHANGES_CNT)) { + ha->max_exchg -= REDUCE_EXCHANGES_CNT; + } else if (ha->max_exchg > + (FW_DEF_EXCHANGES_CNT + 512)) { + ha->max_exchg -= 512; + } else { + ha->flags.exchoffld_enabled = 0; + ql_log_pci(ql_log_fatal, ha->pdev, 0xd013, + "Disabling Exchange offload due to lack of memory\n"); + } + ha->exchoffld_size = 0; + return -ENOMEM; } } -- 2.12.0
[PATCH 06/43] qla2xxx: Fix stale mem access for IRQ name
From: Quinn TranIRQ name pointer for INTx/MSI was pointing at stale stack frame. cat /proc/interrupts will trigger stale mem access. Fix it by creating dedicated space for IRQ name. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h | 4 +++- drivers/scsi/qla2xxx/qla_isr.c | 10 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ca3ef9360ab9..5e509763a419 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3140,12 +3140,13 @@ struct scsi_qla_host; #define QLA83XX_RSPQ_MSIX_ENTRY_NUMBER 1 /* refer to qla83xx_msix_entries */ +#define IRQNAME_SZ 32 struct qla_msix_entry { int have_irq; int in_use; uint32_t vector; uint16_t entry; - char name[30]; + char name[IRQNAME_SZ]; void *handle; int cpuid; }; @@ -4025,6 +4026,7 @@ struct qla_hw_data { uint16_tzio_timer; struct qla_msix_entry *msix_entries; + u8 irqname[IRQNAME_SZ]; /* msi/intx */ struct list_headvp_list;/* list of VP */ unsigned long vp_idx_map[(MAX_MULTI_ID_FABRIC / 8) / diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index a265c2d8c9cc..33865e0bb29f 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3607,9 +3607,17 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) if (!ha->flags.msi_enabled && IS_QLA82XX(ha)) return QLA_FUNCTION_FAILED; + memset(ha->irqname, 0, IRQNAME_SZ); + if (ha->flags.msi_enabled) + scnprintf(ha->irqname, IRQNAME_SZ, + "qla2xxx%lu_msi", vha->host_no); + else + scnprintf(ha->irqname, IRQNAME_SZ, + "qla2xxx%lu_intx", vha->host_no); ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, ha->flags.msi_enabled ? 0 : IRQF_SHARED, - QLA2XXX_DRIVER_NAME, rsp); + ha->irqname, rsp); + if (ret) { ql_log(ql_log_warn, vha, 0x003a, "Failed to reserve interrupt %d already in use.\n", -- 2.12.0
[PATCH 03/43] qla2xxx: Use IOCB path to submit Control VP MBX command
From: Quinn TranUse IOCB patch to submit Control VP MBX command to reduce bottle-neck for mbx interface. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_def.h| 9 - drivers/scsi/qla2xxx/qla_gs.c | 1 + drivers/scsi/qla2xxx/qla_init.c | 1 + drivers/scsi/qla2xxx/qla_inline.h | 1 + drivers/scsi/qla2xxx/qla_iocb.c | 23 +++ drivers/scsi/qla2xxx/qla_isr.c| 35 drivers/scsi/qla2xxx/qla_mbx.c| 77 --- drivers/scsi/qla2xxx/qla_mid.c| 85 +++ 8 files changed, 154 insertions(+), 78 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 4d65fd973a12..50a570595969 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -472,6 +472,10 @@ struct srb_iocb { uint32_t timeout_sec; struct list_head entry; } nvme; + struct { + u16 cmd; + u16 vp_index; + } ctrlvp; } u; struct timer_list timer; @@ -507,6 +511,7 @@ enum { SPCN_PRLI, SPCN_NVME_LS, SPCN_NVME_CMD, + SPCN_CTRL_VP, }; struct sp_name { @@ -536,7 +541,7 @@ struct sp_name { #define SRB_NVME_CMD 19 #define SRB_NVME_LS20 #define SRB_PRLI_CMD 21 - +#define SRB_CTRL_VP22 enum { TYPE_SRB, TYPE_TGT_CMD, @@ -562,6 +567,8 @@ typedef struct srb { struct list_head elem; u32 gen1; /* scratch */ u32 gen2; /* scratch */ + int rc; + struct completion comp; union { struct srb_iocb iocb_cmd; struct bsg_job *bsg_job; diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 7e88e8289157..6aa6dd74fe86 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -41,6 +41,7 @@ struct sp_name sp_str[] = { { SPCN_PRLI, "prli" }, { SPCN_NVME_LS, "nvme_ls" }, { SPCN_NVME_CMD, "nvme_cmd" }, + { SPCN_CTRL_VP, "ctrl_vp" }, }; const char *sp_to_str(uint16_t cmd) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 9d65fbe85e30..24d0f9d419d2 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -135,6 +135,7 @@ qla2x00_async_iocb_timeout(void *data) case SRB_NACK_PLOGI: case SRB_NACK_PRLI: case SRB_NACK_LOGO: + case SRB_CTRL_VP: sp->done(sp, QLA_FUNCTION_TIMEOUT); break; } diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 17d2c20f1f75..4d32426393c7 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -273,6 +273,7 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo) sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ; add_timer(>u.iocb_cmd.timer); sp->free = qla2x00_sp_free; + init_completion(>comp); if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD)) init_completion(>u.iocb_cmd.u.fxiocb.fxiocb_comp); if (sp->type == SRB_ELS_DCMD) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index b5d1423f933d..62b3d0a8a961 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -3368,6 +3368,26 @@ qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt) return rval; } +static void +qla25xx_ctrlvp_iocb(srb_t *sp, struct vp_ctrl_entry_24xx *vce) +{ + int map, pos; + + vce->entry_type = VP_CTRL_IOCB_TYPE; + vce->handle = sp->handle; + vce->entry_count = 1; + vce->command = cpu_to_le16(sp->u.iocb_cmd.u.ctrlvp.cmd); + vce->vp_count = cpu_to_le16(1); + + /* +* index map in firmware starts with 1; decrement index +* this is ok as we never use index 0 +*/ + map = (sp->u.iocb_cmd.u.ctrlvp.vp_index - 1) / 8; + pos = (sp->u.iocb_cmd.u.ctrlvp.vp_index - 1) & 7; + vce->vp_idx_map[map] |= 1 << pos; +} + int qla2x00_start_sp(srb_t *sp) { @@ -3446,6 +3466,9 @@ qla2x00_start_sp(srb_t *sp) case SRB_NACK_LOGO: qla2x00_send_notify_ack_iocb(sp, pkt); break; + case SRB_CTRL_VP: + qla25xx_ctrlvp_iocb(sp, pkt); + break; default: break; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index a55bfaa790a3..a265c2d8c9cc 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1937,6 +1937,37 @@ qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) sp->done(sp, ret); } +static void qla_ctrlvp_completed(scsi_qla_host_t
[PATCH 02/43] qla2xxx: Fix NULL pointer access for fcport structure
From: Quinn Tranwhen preocessing iocb in a timeout case, driver was trying to log messages without verifying if the fcport structure could have valid data. This results in a NULL pointer access. Fixes: 726b85487067("qla2xxx: Add framework for async fabric discovery") Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_init.c | 13 + 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7fa71170d6ff..9d65fbe85e30 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -102,11 +102,16 @@ qla2x00_async_iocb_timeout(void *data) struct srb_iocb *lio = >u.iocb_cmd; struct event_arg ea; - ql_dbg(ql_dbg_disc, fcport->vha, 0x2071, - "Async-%s timeout - hdl=%x portid=%06x %8phC.\n", - sp->name, sp->handle, fcport->d_id.b24, fcport->port_name); + if (fcport) { + ql_dbg(ql_dbg_disc, fcport->vha, 0x2071, + "Async-%s timeout - hdl=%x portid=%06x %8phC.\n", + sp->name, sp->handle, fcport->d_id.b24, fcport->port_name); - fcport->flags &= ~FCF_ASYNC_SENT; + fcport->flags &= ~FCF_ASYNC_SENT; + } else { + pr_info("Async-%s timeout - hdl=%x.\n", + sp->name, sp->handle); + } switch (sp->type) { case SRB_LOGIN_CMD: -- 2.12.0
[PATCH 01/43] qla2xxx: Fix stale memory access for name pointer
From: Quinn TranName pointer for sp describing each command is assigned with stack frame's memory. The stack frame could eventually be re-use, where name pointer access can get get garbage. This patch designates static memory for name pointer to fix this problem. Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani --- drivers/scsi/qla2xxx/qla_bsg.c| 7 +++--- drivers/scsi/qla2xxx/qla_def.h| 36 +++ drivers/scsi/qla2xxx/qla_gbl.h| 1 + drivers/scsi/qla2xxx/qla_gs.c | 51 --- drivers/scsi/qla2xxx/qla_init.c | 16 ++-- drivers/scsi/qla2xxx/qla_iocb.c | 4 +-- drivers/scsi/qla2xxx/qla_mbx.c| 5 ++-- drivers/scsi/qla2xxx/qla_mr.c | 2 +- drivers/scsi/qla2xxx/qla_nvme.c | 4 +-- drivers/scsi/qla2xxx/qla_target.c | 2 +- 10 files changed, 105 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index e3ac7078d2aa..3fc3ae9abb39 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -376,7 +376,8 @@ qla2x00_process_els(struct bsg_job *bsg_job) SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); sp->name = (bsg_request->msgcode == FC_BSG_RPT_ELS ? -"bsg_els_rpt" : "bsg_els_hst"); +sp_to_str(SPCN_BSG_RPT) : sp_to_str(SPCN_BSG_HST)); + sp->u.bsg_job = bsg_job; sp->free = qla2x00_bsg_sp_free; sp->done = qla2x00_bsg_job_done; @@ -522,7 +523,7 @@ qla2x00_process_ct(struct bsg_job *bsg_job) } sp->type = SRB_CT_CMD; - sp->name = "bsg_ct"; + sp->name = sp_to_str(SPCN_BSG_CT); sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt); sp->u.bsg_job = bsg_job; sp->free = qla2x00_bsg_sp_free; @@ -2028,7 +2029,7 @@ qlafx00_mgmt_cmd(struct bsg_job *bsg_job) fcport->loop_id = piocb_rqst->dataword; sp->type = SRB_FXIOCB_BCMD; - sp->name = "bsg_fx_mgmt"; + sp->name = sp_to_str(SPCN_BSG_FX_MGMT); sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt); sp->u.bsg_job = bsg_job; sp->free = qla2x00_bsg_sp_free; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 93ff92e2363f..4d65fd973a12 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -478,6 +478,42 @@ struct srb_iocb { void (*timeout)(void *); }; +enum { + SPCN_UNKNOWN, + SPCN_GIDPN, + SPCN_GPSC, + SPCN_GPNID, + SPCN_GPNFT, + SPCN_GNNID, + SPCN_GFPNID, + SPCN_LOGIN, + SPCN_LOGOUT, + SPCN_ADISC, + SPCN_GNLIST, + SPCN_GPDB, + SPCN_TMF, + SPCN_ABORT, + SPCN_NACK, + SPCN_BSG_RPT, + SPCN_BSG_HST, + SPCN_BSG_CT, + SPCN_BSG_FX_MGMT, + SPCN_ELS_DCMD, + SPCN_FXDISC, + SPCN_GIDLIST, + SPCN_STATS, + SPCN_MB_GPDB, + SPCN_GFFID, + SPCN_PRLI, + SPCN_NVME_LS, + SPCN_NVME_CMD, +}; + +struct sp_name { + uint16_t cmd; + const char *str; +}; + /* Values for srb_ctx type */ #define SRB_LOGIN_CMD 1 #define SRB_LOGOUT_CMD 2 diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index fa115c7433e5..bf907386f177 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -647,6 +647,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *); int qla2x00_mgmt_svr_login(scsi_qla_host_t *); void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea); int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport); +const char *sp_to_str(uint16_t); /* * Global Function Prototypes in qla_attr.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 07fe17a986b0..7e88e8289157 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -15,6 +15,49 @@ static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *); static int qla2x00_sns_rft_id(scsi_qla_host_t *); static int qla2x00_sns_rnn_id(scsi_qla_host_t *); +struct sp_name sp_str[] = { + { SPCN_UNKNOWN, "unknown" }, + { SPCN_GIDPN, "gidpn" }, + { SPCN_GPSC, "gpsc" }, + { SPCN_GPNID, "gpnid" }, + { SPCN_GPNFT, "gpnft" }, + { SPCN_GNNID, "gnnid" }, + { SPCN_GFPNID, "gfpnid" }, + { SPCN_GFFID, "gffid" }, + { SPCN_LOGIN, "login" }, + { SPCN_LOGOUT, "logout" }, + { SPCN_ADISC, "adisc" }, + { SPCN_GNLIST, "gnlist" }, + { SPCN_GPDB, "gpdb" }, + { SPCN_TMF, "tmf" }, + { SPCN_ABORT, "abort" }, + { SPCN_NACK, "nack" }, + { SPCN_BSG_RPT, "bsg_els_rpt" }, + { SPCN_BSG_HST, "bsg_els_hst" }, + { SPCN_BSG_CT, "bsg_ct" }, + { SPCN_BSG_FX_MGMT, "bsg_fx_mgmt" }, + { SPCN_ELS_DCMD, "ELS_DCMD" }, +
[PATCH 00/43] qla2xxx: Driver update
Hi Martin, This series contains number of improvments in handling of switch registration commands in the driver. Switch commands are now submitted via IOCB patch asynchronously instead of mailbox interface. Please apply this series to 4.16/scsi-queue branch at your earliest convenience. Thanks, Himanshu Anil Gurumurthy (1): qla2xxx: Add counters for Exchange Buffer to debugfs Giridhar Malavali (1): qla2xxx: Don't call dma_free_coherent with IRQ disabled. Himanshu Madhani (4): qla2xxx: Use known NPort ID for Management Server login qla2xxx: Allow relogin and session creation after reset qla2xxx: Check FCF_ASYNC_SENT flag qla2xxx: Update driver version to 10.00.00.04-k Quinn Tran (36): qla2xxx: Fix stale memory access for name pointer qla2xxx: Fix NULL pointer access for fcport structure qla2xxx: Use IOCB path to submit Control VP MBX command qla2xxx: Use chip reset to bring down laser on unload. qla2xxx: Add boundary checks for exchanges to be offloaded qla2xxx: Fix stale mem access for IRQ name qla2xxx: Add ability to track IOCB resource for FW qla2xxx: Chip reset uses wrong lock during IO flush. qla2xxx: Fix Firmware dump size for Extended login and Exchange Offload qla2xxx: Replace GPDB with async ADISC command qla2xxx: Move work element processing out of DPC thread qla2xxx: Enable ATIO interrupt handshake for ISP27XX qla2xxx: Use shadow register for ISP27XX qla2xxx: Add option for use reserve exch for ELS qla2xxx: Add ability to send PRLO qla2xxx: Allow target mode to accept PRLI in dual mode qla2xxx: Tweak resource count dump qla2xxx: Fix session cleanup for N2N qla2xxx: Add switch command to simplify fabric discovery qla2xxx: Add lock protection around host lookup qla2xxx: Reduce the use of terminate exchange qla2xxx: Reduce trace noise for Async Events qla2xxx: Fix login state machine freeze qla2xxx: Migrate switch registration commands away from mailbox interface qla2xxx: Remove session creation redundant code qla2xxx: Fix GPNFT/GNNFT error handling qla2xxx: Properly extract ADISC error codes qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling qla2xxx: Increase verbosity of debug messages logged qla2xxx: Delay loop id allocation at login qla2xxx: Add retry limit for fabric scan logic qla2xxx: Prevent multiple active discovery commands per session qla2xxx: Prevent relogin trigger from sending too many commands qla2xxx: Remove unused argument from qlt_schedule_sess_for_deletion() qla2xxx: Serialize session deletion by using work_lock qla2xxx: Serialize session free in qlt_free_session_done Sawan Chandak (1): qla2xxx: Remove calling cancel_work_sync() drivers/scsi/qla2xxx/qla_attr.c|2 + drivers/scsi/qla2xxx/qla_bsg.c |7 +- drivers/scsi/qla2xxx/qla_def.h | 220 +- drivers/scsi/qla2xxx/qla_dfs.c | 354 +- drivers/scsi/qla2xxx/qla_fw.h |2 +- drivers/scsi/qla2xxx/qla_gbl.h | 37 +- drivers/scsi/qla2xxx/qla_gs.c | 1339 +++- drivers/scsi/qla2xxx/qla_init.c| 1019 +-- drivers/scsi/qla2xxx/qla_inline.h | 103 +++ drivers/scsi/qla2xxx/qla_iocb.c| 93 ++- drivers/scsi/qla2xxx/qla_isr.c | 64 +- drivers/scsi/qla2xxx/qla_mbx.c | 153 ++-- drivers/scsi/qla2xxx/qla_mid.c | 113 ++- drivers/scsi/qla2xxx/qla_mr.c |2 +- drivers/scsi/qla2xxx/qla_nvme.c|4 +- drivers/scsi/qla2xxx/qla_os.c | 449 drivers/scsi/qla2xxx/qla_target.c | 728 +++- drivers/scsi/qla2xxx/qla_target.h |7 +- drivers/scsi/qla2xxx/qla_tmpl.c| 40 +- drivers/scsi/qla2xxx/qla_version.h |2 +- 20 files changed, 3593 insertions(+), 1145 deletions(-) -- 2.12.0
Re: [PATCH 2/2 v2] scsi: ufs: use sysfs entry for health info
On Tue, 2017-12-19 at 14:46 -0800, Jaegeuk Kim wrote: > Subject: [PATCH 2/2] scsi: ufs: introduce sysfs entries exposing UFS health > info > > This patch adds a new sysfs group, namely health, via: > >/sys/devices/soc/X.ufshc/health/ Thanks for the quick respin. This looks a lot better to me. I will leave it to a UFS expert to do an in-depth review. Bart.
Re: [PATCH net-next] qed*: Utilize FW 8.33.1.0
On Tue, 19 Dec 2017 16:05:23 +0200, Tomer Tayar wrote: > Sorry for the very long patch. > The firmware changes are spread all over w/o a good modularity. Rings false. Significant portion of this patch is just whitespace and comment changes.
RE: Driver version for PMC Adaptec HBA in Linux and from vendor
Hi Paul, > -Original Message- > From: Paul Menzel [mailto:pmen...@molgen.mpg.de] > Sent: Tuesday, December 19, 2017 3:12 PM > To: Raghava Aditya Renukunta >; dl-esc-Aacraid Linux Driver > > Cc: linux-scsi@vger.kernel.org; it+linux-s...@molgen.mpg.de > Subject: Re: Driver version for PMC Adaptec HBA in Linux and from vendor > > EXTERNAL EMAIL > > > Dear Raghava Aditya, > > > Thank you for your answer. > > Am 18.12.2017 um 19:09 schrieb Raghava Aditya Renukunta: > > >> -Original Message- > >> From: Paul Menzel [mailto:pmen...@molgen.mpg.de] > >> Sent: Saturday, December 16, 2017 1:39 AM > >> To: Raghava Aditya Renukunta > >> ; dl-esc-Aacraid Linux Driver > >> > >> Cc: linux-scsi@vger.kernel.org; it+linux-s...@vger.kernel.org > >> Subject: Re: Driver version for PMC Adaptec HBA in Linux and from > vendor > > >> Am 17.02.2017 um 20:29 schrieb Raghava Aditya Renukunta: > >> > Using a PMC Adaptec HBA 1000-8e with latest Linux, it only initializes > in sync mode, instead of async mode. > >>> > >>> The patches that enable async mode in HBA 1000-8e, have been > included in > >> the James Bottomley's linux-scsi Branch and are on track be > >>> Included into Linux 4.11. > >>> > >>> https://git.kernel.org/cgit/linux/kernel/git/jejb/scsi.git/ > >>> > ``` > $ git describe --tag > v4.10-rc8-47-g0722f57bf > $ dmesg > [ 21.359635] Adaptec aacraid driver 1.2-1[41066]-ms > [ 21.360017] aacraid :04:00.0: can't disable ASPM; OS doesn't have > ASPM control > [ 21.363987] AAC0: Async. mode not supported by current driver, sync. > mode enforced. > [ 21.363987] Please update driver to get full performance. > [ 21.364949] AAC0: kernel 1.2-0[0] Nov 5 2015 > [ 21.365275] AAC0: monitor 0.0-0[0] > [ 21.371382] AAC0: bios 0.13-209[32000] > [ 21.371711] AAC0: serial 10F447 > [ 21.372035] AAC0: Non-DASD support enabled. > [ 21.372360] AAC0: 64bit support enabled. > [ 21.372688] AAC0: 64 Bit DAC enabled > […] > $ git grep 'AAC_DRIVER_BUILD 41066' > drivers/scsi/aacraid/aacraid.h:# define AAC_DRIVER_BUILD 41066 > ``` > > Searching the vendor Web site, there is *Linux Driver Source > 1.2.1-53005* available for download [1]. > >>> > >>> The latest upstream driver version is 50740. We will be reaching version > 53005 in couple of patch sets ( ~ 3). > >>> > >> > http://git.kernel.org/cgit/linux/kernel/git/jejb/scsi.git/commit/?id=96f6a613 > >> 4766de0d42a98c7758736dde16e0add5 > >> > >> Thank you for the details. At our infrastructure we only want to use LTS > >> Linux kernels, and the latest in 4.14. So right now, Linux 4.14.6 > >> includes version 50834 [1], which is the same version currently in Linus > >> master branch (4.15-rc3). Is that save to use with async mode, or are > >> you aware of problems and we should always use the latest out of tree > >> driver, which is at version 55022 and can be download from the Microsemi > >> server [3]. > > > > Well at this point I am in the process of creating a patch set that solves a > kdump regression issue(Should be out before the new year), other than that > the upstream driver is pretty much up to date. If kdump support is a must > for you I would recommend that 55022 be used. > > From your answer the state of async support is unclear to me. Could you > please clarify, if that’s support in 4.14.x? (What source line do I need > to check?) It is supported in 4.14, there is no single line specifically, but if the variable sa_firmware is set then async mode is enabled. > How does the upstream process work? Is there a git repository > somewhere > from Microsemi? Are the patches already up for review? (I didn’t find > them.) > >>> > >>> We try to push out patch sets to kernel.org for every major driver > release we make. Usually they go into the > >>> sub component maintainers branch (linux-scsi ) , which is then pushed > out to Linus when the merge > >>> window for opens (currently the merge window for 4.10 is closed , > barring fixes). So Linux version 4.11 should have > >>> full async support and more for HBA1000-8e. > >>> > >>> We do not maintain a git repository unfortunately, but we do release the > >>> source code for every release as you indicated. > >>> > >>> For further reference the patches are sent out in the scsi mailing list > linux-scsi@vger.kernel.org , > >>> the archive is here http://marc.info/?l=linux-scsi=1=2 . > >>> > >>> Hope I cleared up your doubts. Please do reach out if you have other > concerns or questions. > >> > >> Yes, thank you for your elaborate answer, which cleared up a lot of my > >> doubts. We would be even more satisfied if you moved your > development > >> fully to the Linux kernel tree, so that it always carries the latest > >> driver. If
Re: Driver version for PMC Adaptec HBA in Linux and from vendor
Dear Raghava Aditya, Thank you for your answer. Am 18.12.2017 um 19:09 schrieb Raghava Aditya Renukunta: -Original Message- From: Paul Menzel [mailto:pmen...@molgen.mpg.de] Sent: Saturday, December 16, 2017 1:39 AM To: Raghava Aditya Renukunta; dl-esc-Aacraid Linux Driver Cc: linux-scsi@vger.kernel.org; it+linux-s...@vger.kernel.org Subject: Re: Driver version for PMC Adaptec HBA in Linux and from vendor Am 17.02.2017 um 20:29 schrieb Raghava Aditya Renukunta: Using a PMC Adaptec HBA 1000-8e with latest Linux, it only initializes in sync mode, instead of async mode. The patches that enable async mode in HBA 1000-8e, have been included in the James Bottomley's linux-scsi Branch and are on track be Included into Linux 4.11. https://git.kernel.org/cgit/linux/kernel/git/jejb/scsi.git/ ``` $ git describe --tag v4.10-rc8-47-g0722f57bf $ dmesg [ 21.359635] Adaptec aacraid driver 1.2-1[41066]-ms [ 21.360017] aacraid :04:00.0: can't disable ASPM; OS doesn't have ASPM control [ 21.363987] AAC0: Async. mode not supported by current driver, sync. mode enforced. [ 21.363987] Please update driver to get full performance. [ 21.364949] AAC0: kernel 1.2-0[0] Nov 5 2015 [ 21.365275] AAC0: monitor 0.0-0[0] [ 21.371382] AAC0: bios 0.13-209[32000] [ 21.371711] AAC0: serial 10F447 [ 21.372035] AAC0: Non-DASD support enabled. [ 21.372360] AAC0: 64bit support enabled. [ 21.372688] AAC0: 64 Bit DAC enabled […] $ git grep 'AAC_DRIVER_BUILD 41066' drivers/scsi/aacraid/aacraid.h:# define AAC_DRIVER_BUILD 41066 ``` Searching the vendor Web site, there is *Linux Driver Source 1.2.1-53005* available for download [1]. The latest upstream driver version is 50740. We will be reaching version 53005 in couple of patch sets ( ~ 3). http://git.kernel.org/cgit/linux/kernel/git/jejb/scsi.git/commit/?id=96f6a613 4766de0d42a98c7758736dde16e0add5 Thank you for the details. At our infrastructure we only want to use LTS Linux kernels, and the latest in 4.14. So right now, Linux 4.14.6 includes version 50834 [1], which is the same version currently in Linus master branch (4.15-rc3). Is that save to use with async mode, or are you aware of problems and we should always use the latest out of tree driver, which is at version 55022 and can be download from the Microsemi server [3]. Well at this point I am in the process of creating a patch set that solves a kdump regression issue(Should be out before the new year), other than that the upstream driver is pretty much up to date. If kdump support is a must for you I would recommend that 55022 be used. From your answer the state of async support is unclear to me. Could you please clarify, if that’s support in 4.14.x? (What source line do I need to check?) How does the upstream process work? Is there a git repository somewhere from Microsemi? Are the patches already up for review? (I didn’t find them.) We try to push out patch sets to kernel.org for every major driver release we make. Usually they go into the sub component maintainers branch (linux-scsi ) , which is then pushed out to Linus when the merge window for opens (currently the merge window for 4.10 is closed , barring fixes). So Linux version 4.11 should have full async support and more for HBA1000-8e. We do not maintain a git repository unfortunately, but we do release the >>> source code for every release as you indicated. For further reference the patches are sent out in the scsi mailing list linux-scsi@vger.kernel.org , the archive is here http://marc.info/?l=linux-scsi=1=2 . Hope I cleared up your doubts. Please do reach out if you have other concerns or questions. Yes, thank you for your elaborate answer, which cleared up a lot of my doubts. We would be even more satisfied if you moved your development fully to the Linux kernel tree, so that it always carries the latest driver. If we can help with that by contacting certain people, please tell us. We would love to, but we have lots of customers who are on the older kernel versions 2.6.32, 3.10.0 etc and It becomes almost impossible for us to fully move our development to the Linux kernel tree and support our customers at the same time. Hopefully we will start being up to date with the upstream kernel in the coming months. Hope that answered your questions. I understand, but doesn’t it make more sense to adapt the model like done for Linux Long Term Support (LTS) series to develop against the latest Linux kernel, and then backport the corresponding patches? Maybe you should talk to Red Hat and SUSE? I guess that’s the systems you have to support. Probably you already talk to them. Kind regards, Paul [1] https://storage.microsemi.com/en-us/speed/raid/aac/linux/aacraid-linux-src-1_2_1-53005_tgz.php [2] https://elixir.free-electrons.com/linux/v4.14.6/source/drivers/scsi/aacraid/aacraid.h#L100 [3]
Re: [PATCH 2/2 v2] scsi: ufs: use sysfs entry for health info
>From 3368207da5988b8fed4e41e6c0f49a60ac014222 Mon Sep 17 00:00:00 2001 From: Jaegeuk KimDate: Tue, 26 Sep 2017 20:53:48 -0700 Subject: [PATCH 2/2] scsi: ufs: introduce sysfs entries exposing UFS health info This patch adds a new sysfs group, namely health, via: /sys/devices/soc/X.ufshc/health/ This directory contains the below entries, each of which shows an 8-bytes hex number representing different meanings defined by JEDEC specfication. Users can simply read these entries to check how their underlying flash storage is getting reached out to its end of life. For example, if lifetimeA shows 0xb, it would be the right time to consider device swap. - length : must be 25h - type : must be 09h - eol 00h: Not defined 01h: Normal 02h: Warning 03h: Critical - lifetimeA/B 00h: Not defined 01h: 0% ~ 10% device life time used 02h: 10% ~ 20% device life time used 03h: 20% ~ 30% device life time used 04h: 30% ~ 40% device life time used 05h: 40% ~ 50% device life time used 06h: 50% ~ 60% device life time used 07h: 60% ~ 70% device life time used 08h: 70% ~ 80% device life time used 09h: 80% ~ 90% device life time used 0Ah: 90% ~ 100% device life time used 0Bh: Exceeded its maximum estimated device life time Cc: Greg KH Signed-off-by: Jaegeuk Kim --- Documentation/ABI/testing/sysfs-devices-soc-ufs | 25 + MAINTAINERS | 1 + drivers/scsi/ufs/ufs.h | 2 + drivers/scsi/ufs/ufshcd.c | 69 - drivers/scsi/ufs/ufshcd.h | 1 + 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-devices-soc-ufs diff --git a/Documentation/ABI/testing/sysfs-devices-soc-ufs b/Documentation/ABI/testing/sysfs-devices-soc-ufs new file mode 100644 index ..313771a383e4 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-soc-ufs @@ -0,0 +1,25 @@ +What: /sys/devices/soc/X.ufshc/health +Date: September 2017 +contact: Jaegeuk Kim +Description: + This directory contains health information reported by UFS. + - length must be 25h + - type must be 09h + - eol represent + 00h: Not defined + 01h: Normal + 02h: Warning + 03h: Critical + - lifetimeA/B + 00h: Not defined + 01h: 0% ~ 10% device life time used + 02h: 10% ~ 20% device life time used + 03h: 20% ~ 30% device life time used + 04h: 30% ~ 40% device life time used + 05h: 40% ~ 50% device life time used + 06h: 50% ~ 60% device life time used + 07h: 60% ~ 70% device life time used + 08h: 70% ~ 80% device life time used + 09h: 80% ~ 90% device life time used + 0Ah: 90% ~ 100% device life time used + 0Bh: Exceeded its maximum estimated device life time diff --git a/MAINTAINERS b/MAINTAINERS index aa71ab52fd76..947034319bb4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13999,6 +13999,7 @@ M: Vinayak Holikatti L: linux-scsi@vger.kernel.org S: Supported F: Documentation/scsi/ufs.txt +F: Documentation/ABI/testing/sysfs-devices-soc-ufs F: drivers/scsi/ufs/ UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER DWC HOOKS diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 54deeb754db5..1af541d56c7d 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -154,6 +154,7 @@ enum desc_idn { QUERY_DESC_IDN_RFU_1= 0x6, QUERY_DESC_IDN_GEOMETRY = 0x7, QUERY_DESC_IDN_POWER= 0x8, + QUERY_DESC_IDN_HEALTH = 0x9, QUERY_DESC_IDN_MAX, }; @@ -169,6 +170,7 @@ enum ufs_desc_def_size { QUERY_DESC_INTERCONNECT_DEF_SIZE= 0x06, QUERY_DESC_GEOMETRY_DEF_SIZE= 0x44, QUERY_DESC_POWER_DEF_SIZE = 0x62, + QUERY_DESC_HEALTH_DEF_SIZE = 0x25, }; /* Unit descriptor parameters offsets in bytes*/ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 12ff7daebb00..5cbb08fff0f4 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2991,6 +2991,9 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, case QUERY_DESC_IDN_RFU_1: *desc_len = 0; break; + case QUERY_DESC_IDN_HEALTH: + *desc_len = hba->desc_size.health_desc; + break; default: *desc_len = 0; return -EINVAL; @@ -6298,6 +6301,11 @@ static void ufshcd_init_desc_sizes(struct ufs_hba *hba)
Re: [PATCH 2/2 v2] scsi: ufs: use sysfs entry for health info
On 12/19, Bart Van Assche wrote: > On Tue, 2017-12-19 at 12:02 -0800, Jaegeuk Kim wrote: > > This patch introduces sysfs entries to show the information. > > What information does "the information" refer to? > > Regarding the patch title: I think this patch introduces new sysfs attributes > instead of using existing sysfs entries. If so, please reflect this in the > patch > title. > > > # cat /sys/devices/soc/1da4000.ufshc/health/eol > > # cat /sys/devices/soc/1da4000.ufshc/health/length > > # cat /sys/devices/soc/1da4000.ufshc/health/lifetimeA > > # cat /sys/devices/soc/1da4000.ufshc/health/lifetimeB > > # cat /sys/devices/soc/1da4000.ufshc/health/type > > What is the meaning of the above shell commands in the context of the patch > description? > > > struct desc_field_offset health_desc_field_name[] = { > > {"bLength", 0x00, BYTE}, > > {"bDescriptorType", 0x01, BYTE}, > > {"bPreEOLInfo", 0x02, BYTE}, > > {"bDeviceLifeTimeEstA", 0x03, BYTE}, > > {"bDeviceLifeTimeEstB", 0x04, BYTE} > > }; > > Why has the above data been mentioned in the patch description? > > > bPreEOLInfo > > - 00h: Not defined > > - 01h: Normal > > - 02h: Warning > > - 03h: Critical > > > > bDeviceLifeTimeEstA > > - 00h: Not defined > > - 01h: 0% ~ 10% device life time used > > - 02h: 10% ~ 20% device life time used > > - 03h: 20% ~ 30% device life time used > > - 04h: 30% ~ 40% device life time used > > - 05h: 40% ~ 50% device life time used > > - 06h: 50% ~ 60% device life time used > > - 07h: 60% ~ 70% device life time used > > - 08h: 70% ~ 80% device life time used > > - 09h: 80% ~ 90% device life time used > > - 0Ah: 90% ~ 100% device life time used > > - 0Bh: Exceeded its maximum estimated device life time > > Again, why has the above information been mentioned in the patch description? Let me send v2. > > > +static ssize_t health_attr_show(struct device *dev, > > + struct health_attr *attr, char *buf) > > +{ > > + struct ufs_hba *hba = dev_get_drvdata(dev); > > + int buff_len = hba->desc_size.health_desc; > > + u8 desc_buf[hba->desc_size.health_desc]; > > Is desc_buf[] a variable-length array? If so, how big can > hba->desc_size.health_desc be? Can that number have a negative value? IIUC, it is given by UFS which must be valid. Otherwise, it should be QUERY_DESC_HEALTH_DEF_SIZE which is valid again. This is similarly being done in other sysfs entries here. > > > + return scnprintf(buf, PAGE_SIZE, "0x%02x", desc_buf[attr->bytes]); > > Please check whether attr->bytes falls inside the bounds of the desc_buf[] > array > before using that value as an index. Okay. > > > +#define HEALTH_ATTR_RO(_name, _bytes) > > \ > > +static struct health_attr ufs_health_##_name = { \ > > + .attr = {.name = __stringify(_name), .mode = 0444}, \ > > + .show = health_attr_show, \ > > + .bytes = _bytes,\ > > +} > > + > > +HEALTH_ATTR_RO(length, 0); > > +HEALTH_ATTR_RO(type, 1); > > +HEALTH_ATTR_RO(eol, 2); > > +HEALTH_ATTR_RO(lifetimeA, 3); > > +HEALTH_ATTR_RO(lifetimeB, 4); > > The above makes clear that the value stored in the structure member with the > name > "bytes" represents an array index. Please choose a better name for that > structure > member. Changed to byte_offset. > Additionally, since this patch introduces new sysfs attributes, why doesn't it > add any documentation under Documentation/ABI/? Added. Thanks, > > Thanks, > > Bart.
Re: [PATCH 2/2] scsi: ufs: use sysfs entry for health info
On Tue, 2017-12-19 at 12:02 -0800, Jaegeuk Kim wrote: > This patch introduces sysfs entries to show the information. What information does "the information" refer to? Regarding the patch title: I think this patch introduces new sysfs attributes instead of using existing sysfs entries. If so, please reflect this in the patch title. > # cat /sys/devices/soc/1da4000.ufshc/health/eol > # cat /sys/devices/soc/1da4000.ufshc/health/length > # cat /sys/devices/soc/1da4000.ufshc/health/lifetimeA > # cat /sys/devices/soc/1da4000.ufshc/health/lifetimeB > # cat /sys/devices/soc/1da4000.ufshc/health/type What is the meaning of the above shell commands in the context of the patch description? > struct desc_field_offset health_desc_field_name[] = { > {"bLength", 0x00, BYTE}, > {"bDescriptorType", 0x01, BYTE}, > {"bPreEOLInfo", 0x02, BYTE}, > {"bDeviceLifeTimeEstA", 0x03, BYTE}, > {"bDeviceLifeTimeEstB", 0x04, BYTE} > }; Why has the above data been mentioned in the patch description? > bPreEOLInfo > - 00h: Not defined > - 01h: Normal > - 02h: Warning > - 03h: Critical > > bDeviceLifeTimeEstA > - 00h: Not defined > - 01h: 0% ~ 10% device life time used > - 02h: 10% ~ 20% device life time used > - 03h: 20% ~ 30% device life time used > - 04h: 30% ~ 40% device life time used > - 05h: 40% ~ 50% device life time used > - 06h: 50% ~ 60% device life time used > - 07h: 60% ~ 70% device life time used > - 08h: 70% ~ 80% device life time used > - 09h: 80% ~ 90% device life time used > - 0Ah: 90% ~ 100% device life time used > - 0Bh: Exceeded its maximum estimated device life time Again, why has the above information been mentioned in the patch description? > +static ssize_t health_attr_show(struct device *dev, > + struct health_attr *attr, char *buf) > +{ > + struct ufs_hba *hba = dev_get_drvdata(dev); > + int buff_len = hba->desc_size.health_desc; > + u8 desc_buf[hba->desc_size.health_desc]; Is desc_buf[] a variable-length array? If so, how big can hba->desc_size.health_desc be? Can that number have a negative value? > + return scnprintf(buf, PAGE_SIZE, "0x%02x", desc_buf[attr->bytes]); Please check whether attr->bytes falls inside the bounds of the desc_buf[] array before using that value as an index. > +#define HEALTH_ATTR_RO(_name, _bytes) > \ > +static struct health_attr ufs_health_##_name = { \ > + .attr = {.name = __stringify(_name), .mode = 0444}, \ > + .show = health_attr_show, \ > + .bytes = _bytes,\ > +} > + > +HEALTH_ATTR_RO(length, 0); > +HEALTH_ATTR_RO(type, 1); > +HEALTH_ATTR_RO(eol, 2); > +HEALTH_ATTR_RO(lifetimeA, 3); > +HEALTH_ATTR_RO(lifetimeB, 4); The above makes clear that the value stored in the structure member with the name "bytes" represents an array index. Please choose a better name for that structure member. Additionally, since this patch introduces new sysfs attributes, why doesn't it add any documentation under Documentation/ABI/? Thanks, Bart.
RE: crash in iscsi/scsi initiator with linux-4.15.0-rc1
On Tue, 2017-12-19 at 13:31 -0600, Steve Wise wrote: > > > Hey, > > > > > > I'm seeing this null pointer dereference with linux-4.15.0-rc1. To > > > reproduce > > > it, I connect two ram disks via iscsi/TCP, and start an fio: > > > > > > iscsiadm -m discovery --op update --type sendtargets -p 172.16.1.10:3260 > > > iscsiadm -m node -p 172.16.1.10:3260 -l > > > ISCSI_DISKS=/dev/sdd:/dev/sde; fio --rw=randrw --name=random -- > > norandommap > > > --ioengine=libaio --size=400m --group_reporting --exitall > > > --fsync_on_close=1 > > > --invalidate=1 --direct=1 --filename=$ISCSI_DISKS --time_based > > > --runtime=300 > > > --iodepth=128 --numjobs=8 --unit_base=1 --bs=64k --kb_base=1000 > > > > > > Then on the initiator node, while the fio test is running, I detach the > > > devices: > > > > > > iscsiadm -m node -p 172.16.1.10:3260 -I iser -u > > > > > > Then I hit this crash. Has anyone else encountered this issue? > > > Wondering if > > > there is a fix handy. :) > > > > > > > This is the same problem that is being discussed under the thread: > > "[PATCH] scsi: fix race condition when removing target". > > > > We had good test results with both Jason Yan's patch and Bart's patch > > applied, however the ultimate solution is still in progress, see James' > > comments. > > > > You could also try reverting fbce4d97fd "scsi: fixup kernel warning > > during rmmod()" if you just need to get past this. > > > > -Ewan > > > > Hey Ewan, Yan, Bart, > > I'm still seeing this issue with 4.15-rc4. Is the issue still outstanding? > > Steve. > Please apply the following commit from the 4.15/scsi-fixes branch of git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git and advise if it does not fix your issue. It should. commit 81b6c999897919d5a16fedc018fe375dbab091c5 Author: Hannes ReineckeDate: Wed Dec 13 14:21:37 2017 +0100 scsi: core: check for device state in __scsi_remove_target() As it turned out device_get() doesn't use kref_get_unless_zero(), so we will be always getting a device pointer. Consequently, we need to check for the device state in __scsi_remove_target() to avoid tripping over deleted objects. Fixes: fbce4d97fd43 ("scsi: fixup kernel warning during rmmod()") Reported-by: Jason Yan Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Reviewed-by: Ewan D. Milne Signed-off-by: Martin K. Petersen > --- > > [ 1002.205103] BUG: unable to handle kernel NULL pointer dereference at > (null) > [ 1002.213022] IP: _raw_spin_lock_irqsave+0x1e/0x40 > [ 1002.217740] PGD 0 P4D 0 > [ 1002.220382] Oops: 0002 [#1] SMP > [ 1002.223637] Modules linked in: iw_cxgb4 cxgb4 nvme_rdma nvme_fabrics > rdma_ktest(O) rpcrdma ib_isert iscsi_target_mod ib_iser libiscsi > scsi_transport_iscsi ib_srpt target_core_mod ib_srp scsi_transport_srp > ib_ipoib rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm iw_cm mlx4_ib > ib_core libcxgb vfat intel_rapl fat iosf_mbi x86_pkg_temp_thermal > intel_powerclamp coretemp kvm irqbypass crct10dif_pclmul crc32_pclmul > ghash_clmulni_intel pcbc aesni_intel crypto_simd glue_helper cryptd iTCO_wdt > iTCO_vendor_support mxm_wmi mei_me ipmi_si lpc_ich mei pcspkr i2c_i801 > mfd_core ipmi_devintf shpchp sg ipmi_msghandler wmi nfsd auth_rpcgss nfs_acl > lockd grace sunrpc ip_tables ext4 mbcache jbd2 mlx4_en mgag200 drm_kms_helper > syscopyarea sysfillrect sysimgblt fb_sys_fops ttm sd_mod igb drm ahci libahci > dca mlx4_core > [ 1002.295663] ptp libata pps_core crc32c_intel nvme i2c_algo_bit i2c_core > nvme_core [last unloaded: cxgb4] > [ 1002.305563] CPU: 4 PID: 5156 Comm: fio Tainted: G O > 4.15.0-rc4 #3 > [ 1002.313223] Hardware name: Supermicro X9DR3-F/X9DR3-F, BIOS 3.2a 07/09/2015 > [ 1002.320555] RIP: 0010:_raw_spin_lock_irqsave+0x1e/0x40 > [ 1002.326077] RSP: 0018:c900070cbd10 EFLAGS: 00010046 > [ 1002.331692] RAX: RBX: 0246 RCX: > > [ 1002.339225] RDX: 0001 RSI: 88085fd0e038 RDI: > > [ 1002.346763] RBP: 880855a65f18 R08: R09: > 0744 > [ 1002.354315] R10: 03ff R11: 0001 R12: > 88084992e180 > [ 1002.361873] R13: 880855a67000 R14: 880855a65800 R15: > 880856d7d5a8 > [ 1002.369447] FS: () GS:88085fd0() > knlGS: > [ 1002.377995] CS: 0010 DS: ES: CR0: 80050033 > [ 1002.384209] CR2: CR3: 01c09005 CR4: > 000606e0 > [ 1002.391826] Call Trace: > [ 1002.394774] scsi_device_dev_release_usercontext+0x40/0x230 > [ 1002.400858] execute_in_process_context+0x58/0x60 > [ 1002.406085] device_release+0x2d/0x80 > [ 1002.410277] kobject_cleanup+0x5e/0x180 > [ 1002.414659] scsi_disk_put+0x2b/0x40
[PATCH 2/2] scsi: ufs: use sysfs entry for health info
From: Jaegeuk KimThis patch introduces sysfs entries to show the information. # cat /sys/devices/soc/1da4000.ufshc/health/eol # cat /sys/devices/soc/1da4000.ufshc/health/length # cat /sys/devices/soc/1da4000.ufshc/health/lifetimeA # cat /sys/devices/soc/1da4000.ufshc/health/lifetimeB # cat /sys/devices/soc/1da4000.ufshc/health/type struct desc_field_offset health_desc_field_name[] = { {"bLength", 0x00, BYTE}, {"bDescriptorType", 0x01, BYTE}, {"bPreEOLInfo", 0x02, BYTE}, {"bDeviceLifeTimeEstA", 0x03, BYTE}, {"bDeviceLifeTimeEstB", 0x04, BYTE} }; bPreEOLInfo - 00h: Not defined - 01h: Normal - 02h: Warning - 03h: Critical bDeviceLifeTimeEstA - 00h: Not defined - 01h: 0% ~ 10% device life time used - 02h: 10% ~ 20% device life time used - 03h: 20% ~ 30% device life time used - 04h: 30% ~ 40% device life time used - 05h: 40% ~ 50% device life time used - 06h: 50% ~ 60% device life time used - 07h: 60% ~ 70% device life time used - 08h: 70% ~ 80% device life time used - 09h: 80% ~ 90% device life time used - 0Ah: 90% ~ 100% device life time used - 0Bh: Exceeded its maximum estimated device life time Cc: Greg KH Signed-off-by: Jaegeuk Kim --- drivers/scsi/ufs/ufs.h| 2 ++ drivers/scsi/ufs/ufshcd.c | 66 ++- drivers/scsi/ufs/ufshcd.h | 1 + 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 54deeb754db5..1af541d56c7d 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -154,6 +154,7 @@ enum desc_idn { QUERY_DESC_IDN_RFU_1= 0x6, QUERY_DESC_IDN_GEOMETRY = 0x7, QUERY_DESC_IDN_POWER= 0x8, + QUERY_DESC_IDN_HEALTH = 0x9, QUERY_DESC_IDN_MAX, }; @@ -169,6 +170,7 @@ enum ufs_desc_def_size { QUERY_DESC_INTERCONNECT_DEF_SIZE= 0x06, QUERY_DESC_GEOMETRY_DEF_SIZE= 0x44, QUERY_DESC_POWER_DEF_SIZE = 0x62, + QUERY_DESC_HEALTH_DEF_SIZE = 0x25, }; /* Unit descriptor parameters offsets in bytes*/ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 12ff7daebb00..6809f1786efe 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2991,6 +2991,9 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, case QUERY_DESC_IDN_RFU_1: *desc_len = 0; break; + case QUERY_DESC_IDN_HEALTH: + *desc_len = hba->desc_size.health_desc; + break; default: *desc_len = 0; return -EINVAL; @@ -6298,6 +6301,11 @@ static void ufshcd_init_desc_sizes(struct ufs_hba *hba) >desc_size.geom_desc); if (err) hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; + + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_HEALTH, 0, + >desc_size.health_desc); + if (err) + hba->desc_size.health_desc = QUERY_DESC_HEALTH_DEF_SIZE; } static void ufshcd_def_desc_sizes(struct ufs_hba *hba) @@ -6308,6 +6316,7 @@ static void ufshcd_def_desc_sizes(struct ufs_hba *hba) hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; + hba->desc_size.health_desc = QUERY_DESC_HEALTH_DEF_SIZE; } /** @@ -7688,14 +7697,69 @@ static const struct attribute_group ufshcd_attr_group = { .attrs = ufshcd_attrs, }; +struct health_attr { + struct attribute attr; + ssize_t (*show)(struct device *dev, + struct health_attr *attr, char *buf); + int bytes; +}; + +static ssize_t health_attr_show(struct device *dev, + struct health_attr *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + int buff_len = hba->desc_size.health_desc; + u8 desc_buf[hba->desc_size.health_desc]; + int err; + + pm_runtime_get_sync(hba->dev); + err = ufshcd_read_desc(hba, QUERY_DESC_IDN_HEALTH, 0, + desc_buf, buff_len); + pm_runtime_put_sync(hba->dev); + if (err) + return 0; + + return scnprintf(buf, PAGE_SIZE, "0x%02x", desc_buf[attr->bytes]); +} + +#define HEALTH_ATTR_RO(_name, _bytes) \ +static struct health_attr ufs_health_##_name = { \ + .attr = {.name = __stringify(_name), .mode = 0444}, \ + .show = health_attr_show, \ + .bytes = _bytes,\ +} + +HEALTH_ATTR_RO(length, 0); +HEALTH_ATTR_RO(type, 1); +HEALTH_ATTR_RO(eol, 2);
[PATCH 1/2] scsi: ufs: introduce static sysfs entries
From: Jaegeuk KimThis patch introduces attribute group to show existing sysfs entries. Cc: Greg KH Signed-off-by: Jaegeuk Kim --- drivers/scsi/ufs/ufshcd.c | 48 +++ drivers/scsi/ufs/ufshcd.h | 2 -- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 011c3369082c..12ff7daebb00 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7605,7 +7605,7 @@ static inline ssize_t ufshcd_pm_lvl_store(struct device *dev, return count; } -static ssize_t ufshcd_rpm_lvl_show(struct device *dev, +static ssize_t rpm_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ufs_hba *hba = dev_get_drvdata(dev); @@ -7634,24 +7634,13 @@ static ssize_t ufshcd_rpm_lvl_show(struct device *dev, return curr_len; } -static ssize_t ufshcd_rpm_lvl_store(struct device *dev, +static ssize_t rpm_lvl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { return ufshcd_pm_lvl_store(dev, attr, buf, count, true); } -static void ufshcd_add_rpm_lvl_sysfs_nodes(struct ufs_hba *hba) -{ - hba->rpm_lvl_attr.show = ufshcd_rpm_lvl_show; - hba->rpm_lvl_attr.store = ufshcd_rpm_lvl_store; - sysfs_attr_init(>rpm_lvl_attr.attr); - hba->rpm_lvl_attr.attr.name = "rpm_lvl"; - hba->rpm_lvl_attr.attr.mode = 0644; - if (device_create_file(hba->dev, >rpm_lvl_attr)) - dev_err(hba->dev, "Failed to create sysfs for rpm_lvl\n"); -} - -static ssize_t ufshcd_spm_lvl_show(struct device *dev, +static ssize_t spm_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ufs_hba *hba = dev_get_drvdata(dev); @@ -7680,33 +7669,34 @@ static ssize_t ufshcd_spm_lvl_show(struct device *dev, return curr_len; } -static ssize_t ufshcd_spm_lvl_store(struct device *dev, +static ssize_t spm_lvl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { return ufshcd_pm_lvl_store(dev, attr, buf, count, false); } -static void ufshcd_add_spm_lvl_sysfs_nodes(struct ufs_hba *hba) -{ - hba->spm_lvl_attr.show = ufshcd_spm_lvl_show; - hba->spm_lvl_attr.store = ufshcd_spm_lvl_store; - sysfs_attr_init(>spm_lvl_attr.attr); - hba->spm_lvl_attr.attr.name = "spm_lvl"; - hba->spm_lvl_attr.attr.mode = 0644; - if (device_create_file(hba->dev, >spm_lvl_attr)) - dev_err(hba->dev, "Failed to create sysfs for spm_lvl\n"); -} +static DEVICE_ATTR_RW(rpm_lvl); +static DEVICE_ATTR_RW(spm_lvl); + +static struct attribute *ufshcd_attrs[] = { + _attr_rpm_lvl.attr, + _attr_spm_lvl.attr, + NULL +}; + +static const struct attribute_group ufshcd_attr_group = { + .attrs = ufshcd_attrs, +}; static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba) { - ufshcd_add_rpm_lvl_sysfs_nodes(hba); - ufshcd_add_spm_lvl_sysfs_nodes(hba); + if (sysfs_create_group(>dev->kobj, _attr_group)) + dev_err(hba->dev, "Failed to create sysfs group\n"); } static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba) { - device_remove_file(hba->dev, >rpm_lvl_attr); - device_remove_file(hba->dev, >spm_lvl_attr); + sysfs_remove_group(>dev->kobj, _attr_group); } /** diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 1332e544da92..56e26eb15185 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -526,8 +526,6 @@ struct ufs_hba { enum ufs_pm_level rpm_lvl; /* Desired UFS power management level during system PM */ enum ufs_pm_level spm_lvl; - struct device_attribute rpm_lvl_attr; - struct device_attribute spm_lvl_attr; int pm_op_in_progress; struct ufshcd_lrb *lrb; -- 2.15.0.531.g2ccb3012c9-goog
RE: crash in iscsi/scsi initiator with linux-4.15.0-rc1
> > Hey, > > > > I'm seeing this null pointer dereference with linux-4.15.0-rc1. To > > reproduce > > it, I connect two ram disks via iscsi/TCP, and start an fio: > > > > iscsiadm -m discovery --op update --type sendtargets -p 172.16.1.10:3260 > > iscsiadm -m node -p 172.16.1.10:3260 -l > > ISCSI_DISKS=/dev/sdd:/dev/sde; fio --rw=randrw --name=random -- > norandommap > > --ioengine=libaio --size=400m --group_reporting --exitall --fsync_on_close=1 > > --invalidate=1 --direct=1 --filename=$ISCSI_DISKS --time_based --runtime=300 > > --iodepth=128 --numjobs=8 --unit_base=1 --bs=64k --kb_base=1000 > > > > Then on the initiator node, while the fio test is running, I detach the > > devices: > > > > iscsiadm -m node -p 172.16.1.10:3260 -I iser -u > > > > Then I hit this crash. Has anyone else encountered this issue? Wondering > > if > > there is a fix handy. :) > > > > This is the same problem that is being discussed under the thread: > "[PATCH] scsi: fix race condition when removing target". > > We had good test results with both Jason Yan's patch and Bart's patch > applied, however the ultimate solution is still in progress, see James' > comments. > > You could also try reverting fbce4d97fd "scsi: fixup kernel warning > during rmmod()" if you just need to get past this. > > -Ewan > Hey Ewan, Yan, Bart, I'm still seeing this issue with 4.15-rc4. Is the issue still outstanding? Steve. --- [ 1002.205103] BUG: unable to handle kernel NULL pointer dereference at (null) [ 1002.213022] IP: _raw_spin_lock_irqsave+0x1e/0x40 [ 1002.217740] PGD 0 P4D 0 [ 1002.220382] Oops: 0002 [#1] SMP [ 1002.223637] Modules linked in: iw_cxgb4 cxgb4 nvme_rdma nvme_fabrics rdma_ktest(O) rpcrdma ib_isert iscsi_target_mod ib_iser libiscsi scsi_transport_iscsi ib_srpt target_core_mod ib_srp scsi_transport_srp ib_ipoib rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm iw_cm mlx4_ib ib_core libcxgb vfat intel_rapl fat iosf_mbi x86_pkg_temp_thermal intel_powerclamp coretemp kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc aesni_intel crypto_simd glue_helper cryptd iTCO_wdt iTCO_vendor_support mxm_wmi mei_me ipmi_si lpc_ich mei pcspkr i2c_i801 mfd_core ipmi_devintf shpchp sg ipmi_msghandler wmi nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables ext4 mbcache jbd2 mlx4_en mgag200 drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm sd_mod igb drm ahci libahci dca mlx4_core [ 1002.295663] ptp libata pps_core crc32c_intel nvme i2c_algo_bit i2c_core nvme_core [last unloaded: cxgb4] [ 1002.305563] CPU: 4 PID: 5156 Comm: fio Tainted: G O 4.15.0-rc4 #3 [ 1002.313223] Hardware name: Supermicro X9DR3-F/X9DR3-F, BIOS 3.2a 07/09/2015 [ 1002.320555] RIP: 0010:_raw_spin_lock_irqsave+0x1e/0x40 [ 1002.326077] RSP: 0018:c900070cbd10 EFLAGS: 00010046 [ 1002.331692] RAX: RBX: 0246 RCX: [ 1002.339225] RDX: 0001 RSI: 88085fd0e038 RDI: [ 1002.346763] RBP: 880855a65f18 R08: R09: 0744 [ 1002.354315] R10: 03ff R11: 0001 R12: 88084992e180 [ 1002.361873] R13: 880855a67000 R14: 880855a65800 R15: 880856d7d5a8 [ 1002.369447] FS: () GS:88085fd0() knlGS: [ 1002.377995] CS: 0010 DS: ES: CR0: 80050033 [ 1002.384209] CR2: CR3: 01c09005 CR4: 000606e0 [ 1002.391826] Call Trace: [ 1002.394774] scsi_device_dev_release_usercontext+0x40/0x230 [ 1002.400858] execute_in_process_context+0x58/0x60 [ 1002.406085] device_release+0x2d/0x80 [ 1002.410277] kobject_cleanup+0x5e/0x180 [ 1002.414659] scsi_disk_put+0x2b/0x40 [sd_mod] [ 1002.419559] __blkdev_put+0x1b5/0x1d0 [ 1002.423777] ? disk_flush_events+0x24/0x60 [ 1002.428430] blkdev_close+0x21/0x30 [ 1002.432484] __fput+0xd5/0x210 [ 1002.436111] task_work_run+0x82/0xa0 [ 1002.440262] do_exit+0x2be/0xb20 [ 1002.444074] ? syscall_trace_enter+0x1af/0x290 [ 1002.449110] do_group_exit+0x39/0xa0 [ 1002.453287] SyS_exit_group+0x10/0x10 [ 1002.457557] do_syscall_64+0x61/0x1a0 [ 1002.461829] entry_SYSCALL64_slow_path+0x25/0x25 [ 1002.467064] RIP: 0033:0x7f9abb1c8529 [ 1002.471266] RSP: 002b:7ffe53be40d8 EFLAGS: 0206 ORIG_RAX: 00e7 [ 1002.479482] RAX: ffda RBX: 0010 RCX: 7f9abb1c8529 [ 1002.487279] RDX: 0005 RSI: 000a RDI: 0005 [ 1002.495079] RBP: 7f9a9c9de818 R08: 003c R09: 00e7 [ 1002.502882] R10: ff60 R11: 0206 R12: 0006 [ 1002.510690] R13: 0006 R14: R15: 0172a440 [ 1002.518497] Code: f4 66 90 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 53 9c 58 66 66 90 66 90 48 89 c3 fa 66 66 90 66 66 90 31 c0 ba 01 00 00 00 0f b1 17 85 c0 75 05 48 89 d8 5b c3 89 c6 e8 77 06 9e ff eb [ 1002.538742] RIP:
Re: [-next PATCH 0/4] sysfs and DEVICE_ATTR_
On 12/19/2017 12:15 PM, Joe Perches wrote: drivers/char/ipmi/ipmi_msghandler.c| 17 +++--- For ipmi: Acked-by: Corey Minyard
[PATCH] lpfc: correct sg_seg_cnt attribute min vs default
Prior patch mixed up what argument in the macro was what, so min value was placed as the "default" argument, and the default value was placed as the "min" argument. Thus, when the default was applied, it looked like the default was smaller than the allowed min. swap argument postions to correct. Signed-off-by: James Smart--- drivers/scsi/lpfc/lpfc_attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 797bb42a6306..8938c867ed2c 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -5174,7 +5174,7 @@ LPFC_ATTR(delay_discovery, 0, 0, 1, * this parameter will be limited to 128 if BlockGuard is enabled under SLI4 * and will be limited to 512 if BlockGuard is enabled under SLI3. */ -LPFC_ATTR_R(sg_seg_cnt, LPFC_MIN_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT, +LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_MIN_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count"); /* -- 2.13.1
Re: [-next PATCH 0/4] sysfs and DEVICE_ATTR_
On Tue, 19 Dec 2017, Joe Percheswrote: > drivers/gpu/drm/i915/i915_sysfs.c | 12 ++-- For i915, Acked-by: Jani Nikula -- Jani Nikula, Intel Open Source Technology Center
Re: [-next PATCH 4/4] treewide: Use DEVICE_ATTR_WO
On Tue, Dec 19, 2017 at 10:51:14AM -0800, Joe Perches wrote: > > The reason for the code churn being? > > Consistency for easier grep by use-type. Please explain that in the commit message so that we know why it was changed. -- Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply.
Re: [-next PATCH 4/4] treewide: Use DEVICE_ATTR_WO
On Tue, 2017-12-19 at 19:44 +0100, Borislav Petkov wrote: > On Tue, Dec 19, 2017 at 10:15:09AM -0800, Joe Perches wrote: > > Convert DEVICE_ATTR uses to DEVICE_ATTR_WO where possible. > > > > Done with perl script: > > > > $ git grep -w --name-only DEVICE_ATTR | \ > > xargs perl -i -e 'local $/; while (<>) { > > s/\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?(?:\s*S_IWUSR\s*|\s*0200\s*)\)?\s*,\s*NULL\s*,\s*\s_store\s*\)/DEVICE_ATTR_WO(\1)/g; > > print;}' [] > > diff --git a/arch/x86/kernel/cpu/microcode/core.c > > b/arch/x86/kernel/cpu/microcode/core.c [] > > @@ -560,7 +560,7 @@ static ssize_t pf_show(struct device *dev, > > return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); > > } > > > > -static DEVICE_ATTR(reload, 0200, NULL, reload_store); > > +static DEVICE_ATTR_WO(reload); > > static DEVICE_ATTR(version, 0400, version_show, NULL); > > static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL); > > > > # cat /sys/devices/system/cpu/microcode/reload > cat: /sys/devices/system/cpu/microcode/reload: Permission denied Not different behavior. It was and remains write only. > The reason for the code churn being? Consistency for easier grep by use-type.
Re: [-next PATCH 4/4] treewide: Use DEVICE_ATTR_WO
On Tue, Dec 19, 2017 at 10:15:09AM -0800, Joe Perches wrote: > Convert DEVICE_ATTR uses to DEVICE_ATTR_WO where possible. > > Done with perl script: > > $ git grep -w --name-only DEVICE_ATTR | \ > xargs perl -i -e 'local $/; while (<>) { > s/\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?(?:\s*S_IWUSR\s*|\s*0200\s*)\)?\s*,\s*NULL\s*,\s*\s_store\s*\)/DEVICE_ATTR_WO(\1)/g; > print;}' > > Signed-off-by: Joe Perches> --- > arch/s390/kernel/smp.c | 2 +- > arch/x86/kernel/cpu/microcode/core.c | 2 +- > drivers/input/touchscreen/elants_i2c.c | 2 +- > drivers/net/ethernet/ibm/ibmvnic.c | 2 +- > drivers/net/wimax/i2400m/sysfs.c | 3 +-- > drivers/scsi/lpfc/lpfc_attr.c | 3 +-- > drivers/thermal/thermal_sysfs.c| 2 +- > 7 files changed, 7 insertions(+), 9 deletions(-) > > diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c > index b8c1a85bcf2d..a919b2f0141d 100644 > --- a/arch/s390/kernel/smp.c > +++ b/arch/s390/kernel/smp.c > @@ -1151,7 +1151,7 @@ static ssize_t __ref rescan_store(struct device *dev, > rc = smp_rescan_cpus(); > return rc ? rc : count; > } > -static DEVICE_ATTR(rescan, 0200, NULL, rescan_store); > +static DEVICE_ATTR_WO(rescan); > #endif /* CONFIG_HOTPLUG_CPU */ > > static int __init s390_smp_init(void) > diff --git a/arch/x86/kernel/cpu/microcode/core.c > b/arch/x86/kernel/cpu/microcode/core.c > index c4fa4a85d4cb..09c74b0560dd 100644 > --- a/arch/x86/kernel/cpu/microcode/core.c > +++ b/arch/x86/kernel/cpu/microcode/core.c > @@ -560,7 +560,7 @@ static ssize_t pf_show(struct device *dev, > return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); > } > > -static DEVICE_ATTR(reload, 0200, NULL, reload_store); > +static DEVICE_ATTR_WO(reload); > static DEVICE_ATTR(version, 0400, version_show, NULL); > static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL); > # cat /sys/devices/system/cpu/microcode/reload cat: /sys/devices/system/cpu/microcode/reload: Permission denied The reason for the code churn being? -- Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply.
Re: [-next PATCH 2/4] treewide: Use DEVICE_ATTR_RW
On Tue, Dec 19, 2017 at 8:15 PM, Joe Percheswrote: > Convert DEVICE_ATTR uses to DEVICE_ATTR_RW where possible. > > Done with perl script: > > $ git grep -w --name-only DEVICE_ATTR | \ > xargs perl -i -e 'local $/; while (<>) { > s/\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?(\s*S_IRUGO\s*\|\s*S_IWUSR|\s*S_IWUSR\s*\|\s*S_IRUGO\s*|\s*0644\s*)\)?\s*,\s*\1_show\s*,\s*\1_store\s*\)/DEVICE_ATTR_RW(\1)/g; > print;}' > drivers/platform/x86/compal-laptop.c | 18 +-- > --- a/drivers/platform/x86/compal-laptop.c > +++ b/drivers/platform/x86/compal-laptop.c > @@ -679,18 +679,12 @@ static int bat_writeable_property(struct power_supply > *psy, > /* == */ > /* Driver Globals */ > /* == */ > -static DEVICE_ATTR(wake_up_pme, > - 0644, wake_up_pme_show, wake_up_pme_store); > -static DEVICE_ATTR(wake_up_modem, > - 0644, wake_up_modem_show, wake_up_modem_store); > -static DEVICE_ATTR(wake_up_lan, > - 0644, wake_up_lan_show, wake_up_lan_store); > -static DEVICE_ATTR(wake_up_wlan, > - 0644, wake_up_wlan_show,wake_up_wlan_store); > -static DEVICE_ATTR(wake_up_key, > - 0644, wake_up_key_show, wake_up_key_store); > -static DEVICE_ATTR(wake_up_mouse, > - 0644, wake_up_mouse_show, wake_up_mouse_store); > +static DEVICE_ATTR_RW(wake_up_pme); > +static DEVICE_ATTR_RW(wake_up_modem); > +static DEVICE_ATTR_RW(wake_up_lan); > +static DEVICE_ATTR_RW(wake_up_wlan); > +static DEVICE_ATTR_RW(wake_up_key); > +static DEVICE_ATTR_RW(wake_up_mouse); Acked-by: Andy Shevchenko for PDx86 bits. Have to say that while it doesn't change the attributes here, it might require still to be revisited by security people, if they wish. -- With Best Regards, Andy Shevchenko
Re: [PATCH] scsi: storvsc: Fix scsi_cmd error assignments in storvsc_handle_error
On Tue, 19 Dec 2017 13:32:48 -0500 Cathy Averywrote: > When an I/O is returned with an srb_status of SRB_STATUS_INVALID_LUN > which has zero good_bytes it must be assigned an error. Otherwise > the I/O will be continuously requeued and will cause a deadlock in the > case where disks are being hot added and removed. sd_probe_async will > wait forever for its I/O to complete while holding scsi_sd_probe_domain. > > Also returning the default error of DID_TARGET_FAILURE causes > multipath to not retry the I/O resulting in applications receiving I/O > errors before a failover can occur. > > Signed-off-by: Cathy Avery > Signed-off-by: Long Li When working on the DVD probe issue I saw that error handling was problematic. Thanks for fixing. Reviewed-by: Stephen Hemminger
[PATCH] scsi: storvsc: Fix scsi_cmd error assignments in storvsc_handle_error
When an I/O is returned with an srb_status of SRB_STATUS_INVALID_LUN which has zero good_bytes it must be assigned an error. Otherwise the I/O will be continuously requeued and will cause a deadlock in the case where disks are being hot added and removed. sd_probe_async will wait forever for its I/O to complete while holding scsi_sd_probe_domain. Also returning the default error of DID_TARGET_FAILURE causes multipath to not retry the I/O resulting in applications receiving I/O errors before a failover can occur. Signed-off-by: Cathy AverySigned-off-by: Long Li --- drivers/scsi/storvsc_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 1b06cf0..3b3d1d0 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -953,10 +953,11 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, case TEST_UNIT_READY: break; default: - set_host_byte(scmnd, DID_TARGET_FAILURE); + set_host_byte(scmnd, DID_ERROR); } break; case SRB_STATUS_INVALID_LUN: + set_host_byte(scmnd, DID_NO_CONNECT); do_work = true; process_err_fn = storvsc_remove_lun; break; -- 2.5.0
[-next PATCH 0/4] sysfs and DEVICE_ATTR_
Joe Perches (4): sysfs.h: Use octal permissions treewide: Use DEVICE_ATTR_RW treewide: Use DEVICE_ATTR_RO treewide: Use DEVICE_ATTR_WO arch/arm/mach-pxa/sharpsl_pm.c | 4 +- arch/s390/kernel/smp.c | 2 +- arch/s390/kernel/topology.c| 3 +- arch/sh/drivers/push-switch.c | 2 +- arch/tile/kernel/sysfs.c | 12 ++-- arch/x86/kernel/cpu/microcode/core.c | 2 +- drivers/acpi/device_sysfs.c| 6 +- drivers/char/ipmi/ipmi_msghandler.c| 17 +++--- drivers/gpu/drm/i915/i915_sysfs.c | 12 ++-- drivers/input/touchscreen/elants_i2c.c | 2 +- drivers/net/ethernet/ibm/ibmvnic.c | 2 +- drivers/net/wimax/i2400m/sysfs.c | 3 +- drivers/nvme/host/core.c | 10 ++-- drivers/platform/x86/compal-laptop.c | 18 ++ drivers/s390/cio/css.c | 8 +-- drivers/s390/cio/device.c | 10 ++-- drivers/s390/crypto/ap_card.c | 2 +- drivers/scsi/hpsa.c| 10 ++-- drivers/scsi/lpfc/lpfc_attr.c | 64 -- .../staging/media/atomisp/pci/atomisp2/hmm/hmm.c | 8 +-- drivers/thermal/thermal_sysfs.c| 17 +++--- drivers/tty/serial/sh-sci.c| 2 +- drivers/usb/host/xhci-dbgcap.c | 2 +- drivers/usb/phy/phy-tahvo.c| 2 +- drivers/video/fbdev/auo_k190x.c| 4 +- drivers/video/fbdev/w100fb.c | 4 +- include/linux/sysfs.h | 14 ++--- lib/test_firmware.c| 14 ++--- lib/test_kmod.c| 14 ++--- sound/soc/omap/mcbsp.c | 4 +- sound/soc/soc-core.c | 2 +- sound/soc/soc-dapm.c | 2 +- 32 files changed, 120 insertions(+), 158 deletions(-) -- 2.15.0
[-next PATCH 4/4] treewide: Use DEVICE_ATTR_WO
Convert DEVICE_ATTR uses to DEVICE_ATTR_WO where possible. Done with perl script: $ git grep -w --name-only DEVICE_ATTR | \ xargs perl -i -e 'local $/; while (<>) { s/\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?(?:\s*S_IWUSR\s*|\s*0200\s*)\)?\s*,\s*NULL\s*,\s*\s_store\s*\)/DEVICE_ATTR_WO(\1)/g; print;}' Signed-off-by: Joe Perches--- arch/s390/kernel/smp.c | 2 +- arch/x86/kernel/cpu/microcode/core.c | 2 +- drivers/input/touchscreen/elants_i2c.c | 2 +- drivers/net/ethernet/ibm/ibmvnic.c | 2 +- drivers/net/wimax/i2400m/sysfs.c | 3 +-- drivers/scsi/lpfc/lpfc_attr.c | 3 +-- drivers/thermal/thermal_sysfs.c| 2 +- 7 files changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index b8c1a85bcf2d..a919b2f0141d 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -1151,7 +1151,7 @@ static ssize_t __ref rescan_store(struct device *dev, rc = smp_rescan_cpus(); return rc ? rc : count; } -static DEVICE_ATTR(rescan, 0200, NULL, rescan_store); +static DEVICE_ATTR_WO(rescan); #endif /* CONFIG_HOTPLUG_CPU */ static int __init s390_smp_init(void) diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index c4fa4a85d4cb..09c74b0560dd 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -560,7 +560,7 @@ static ssize_t pf_show(struct device *dev, return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); } -static DEVICE_ATTR(reload, 0200, NULL, reload_store); +static DEVICE_ATTR_WO(reload); static DEVICE_ATTR(version, 0400, version_show, NULL); static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL); diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index a458e5ec9e41..819213e88f32 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1000,7 +1000,7 @@ static ssize_t show_iap_mode(struct device *dev, "Normal" : "Recovery"); } -static DEVICE_ATTR(calibrate, S_IWUSR, NULL, calibrate_store); +static DEVICE_ATTR_WO(calibrate); static DEVICE_ATTR(iap_mode, S_IRUGO, show_iap_mode, NULL); static DEVICE_ATTR(update_fw, S_IWUSR, NULL, write_update_fw); diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 1dc4aef37d3a..42b96e1a1b13 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -4411,7 +4411,7 @@ static ssize_t failover_store(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR(failover, 0200, NULL, failover_store); +static DEVICE_ATTR_WO(failover); static unsigned long ibmvnic_get_desired_dma(struct vio_dev *vdev) { diff --git a/drivers/net/wimax/i2400m/sysfs.c b/drivers/net/wimax/i2400m/sysfs.c index 1237109f251a..8c67df11105c 100644 --- a/drivers/net/wimax/i2400m/sysfs.c +++ b/drivers/net/wimax/i2400m/sysfs.c @@ -65,8 +65,7 @@ ssize_t i2400m_idle_timeout_store(struct device *dev, } static -DEVICE_ATTR(i2400m_idle_timeout, S_IWUSR, - NULL, i2400m_idle_timeout_store); +DEVICE_ATTR_WO(i2400m_idle_timeout); static struct attribute *i2400m_dev_attrs[] = { diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 517ff203cfde..6ddaf51a23f6 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2418,8 +2418,7 @@ lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, - lpfc_soft_wwn_enable_store); +static DEVICE_ATTR_WO(lpfc_soft_wwn_enable); /** * lpfc_soft_wwpn_show - Return the cfg soft ww port name of the adapter diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 2bc964392924..ba81c9080f6e 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -317,7 +317,7 @@ emul_temp_store(struct device *dev, struct device_attribute *attr, return ret ? ret : count; } -static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); +static DEVICE_ATTR_WO(emul_temp); #endif static ssize_t -- 2.15.0
[-next PATCH 2/4] treewide: Use DEVICE_ATTR_RW
Convert DEVICE_ATTR uses to DEVICE_ATTR_RW where possible. Done with perl script: $ git grep -w --name-only DEVICE_ATTR | \ xargs perl -i -e 'local $/; while (<>) { s/\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?(\s*S_IRUGO\s*\|\s*S_IWUSR|\s*S_IWUSR\s*\|\s*S_IRUGO\s*|\s*0644\s*)\)?\s*,\s*\1_show\s*,\s*\1_store\s*\)/DEVICE_ATTR_RW(\1)/g; print;}' Signed-off-by: Joe Perches--- arch/s390/kernel/topology.c | 3 +-- arch/tile/kernel/sysfs.c | 2 +- drivers/gpu/drm/i915/i915_sysfs.c| 6 ++--- drivers/platform/x86/compal-laptop.c | 18 +-- drivers/s390/cio/device.c| 2 +- drivers/scsi/lpfc/lpfc_attr.c| 43 drivers/thermal/thermal_sysfs.c | 9 drivers/tty/serial/sh-sci.c | 2 +- drivers/usb/host/xhci-dbgcap.c | 2 +- drivers/usb/phy/phy-tahvo.c | 2 +- drivers/video/fbdev/auo_k190x.c | 4 ++-- drivers/video/fbdev/w100fb.c | 4 ++-- lib/test_firmware.c | 14 +--- lib/test_kmod.c | 14 +--- sound/soc/omap/mcbsp.c | 4 ++-- 15 files changed, 49 insertions(+), 80 deletions(-) diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 4d5b65e527b5..4b6e0397f66d 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -404,8 +404,7 @@ static ssize_t dispatching_store(struct device *dev, put_online_cpus(); return rc ? rc : count; } -static DEVICE_ATTR(dispatching, 0644, dispatching_show, -dispatching_store); +static DEVICE_ATTR_RW(dispatching); static ssize_t cpu_polarization_show(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c index 825867c53853..af5024f0fb5a 100644 --- a/arch/tile/kernel/sysfs.c +++ b/arch/tile/kernel/sysfs.c @@ -184,7 +184,7 @@ static ssize_t hv_stats_store(struct device *dev, return n < 0 ? n : count; } -static DEVICE_ATTR(hv_stats, 0644, hv_stats_show, hv_stats_store); +static DEVICE_ATTR_RW(hv_stats); static int hv_stats_device_add(struct device *dev, struct subsys_interface *sif) { diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index c74a20b80182..1d0ab8ff5915 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -447,9 +447,9 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, static DEVICE_ATTR(gt_act_freq_mhz, S_IRUGO, gt_act_freq_mhz_show, NULL); static DEVICE_ATTR(gt_cur_freq_mhz, S_IRUGO, gt_cur_freq_mhz_show, NULL); -static DEVICE_ATTR(gt_boost_freq_mhz, S_IRUGO | S_IWUSR, gt_boost_freq_mhz_show, gt_boost_freq_mhz_store); -static DEVICE_ATTR(gt_max_freq_mhz, S_IRUGO | S_IWUSR, gt_max_freq_mhz_show, gt_max_freq_mhz_store); -static DEVICE_ATTR(gt_min_freq_mhz, S_IRUGO | S_IWUSR, gt_min_freq_mhz_show, gt_min_freq_mhz_store); +static DEVICE_ATTR_RW(gt_boost_freq_mhz); +static DEVICE_ATTR_RW(gt_max_freq_mhz); +static DEVICE_ATTR_RW(gt_min_freq_mhz); static DEVICE_ATTR(vlv_rpe_freq_mhz, S_IRUGO, vlv_rpe_freq_mhz_show, NULL); diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 6bcb750e1865..4f9bc72f0584 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -679,18 +679,12 @@ static int bat_writeable_property(struct power_supply *psy, /* == */ /* Driver Globals */ /* == */ -static DEVICE_ATTR(wake_up_pme, - 0644, wake_up_pme_show, wake_up_pme_store); -static DEVICE_ATTR(wake_up_modem, - 0644, wake_up_modem_show, wake_up_modem_store); -static DEVICE_ATTR(wake_up_lan, - 0644, wake_up_lan_show, wake_up_lan_store); -static DEVICE_ATTR(wake_up_wlan, - 0644, wake_up_wlan_show,wake_up_wlan_store); -static DEVICE_ATTR(wake_up_key, - 0644, wake_up_key_show, wake_up_key_store); -static DEVICE_ATTR(wake_up_mouse, - 0644, wake_up_mouse_show, wake_up_mouse_store); +static DEVICE_ATTR_RW(wake_up_pme); +static DEVICE_ATTR_RW(wake_up_modem); +static DEVICE_ATTR_RW(wake_up_lan); +static DEVICE_ATTR_RW(wake_up_wlan); +static DEVICE_ATTR_RW(wake_up_key); +static DEVICE_ATTR_RW(wake_up_mouse); static DEVICE_ATTR(fan1_input, S_IRUGO, fan_show, NULL); static DEVICE_ATTR(temp1_input, S_IRUGO, temp_cpu, NULL); diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 75a245f38e2e..6eefb67b31f3 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -600,7 +600,7 @@ static ssize_t vpm_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); static DEVICE_ATTR(cutype, 0444, cutype_show, NULL); static DEVICE_ATTR(modalias, 0444, modalias_show,
[-next PATCH 3/4] treewide: Use DEVICE_ATTR_RO
Convert DEVICE_ATTR uses to DEVICE_ATTR_RO where possible. Done with perl script: $ git grep -w --name-only DEVICE_ATTR | \ xargs perl -i -e 'local $/; while (<>) { s/\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?(?:\s*S_IRUGO\s*|\s*0444\s*)\)?\s*,\s*\1_show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(\1)/g; print;}' Signed-off-by: Joe Perches--- arch/arm/mach-pxa/sharpsl_pm.c | 4 ++-- arch/sh/drivers/push-switch.c| 2 +- arch/tile/kernel/sysfs.c | 10 +- drivers/acpi/device_sysfs.c | 6 +++--- drivers/char/ipmi/ipmi_msghandler.c | 17 - drivers/gpu/drm/i915/i915_sysfs.c| 6 +++--- drivers/nvme/host/core.c | 10 +- drivers/s390/cio/css.c | 8 drivers/s390/cio/device.c| 8 drivers/s390/crypto/ap_card.c| 2 +- drivers/scsi/hpsa.c | 10 +- drivers/scsi/lpfc/lpfc_attr.c| 18 -- drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm.c | 8 drivers/thermal/thermal_sysfs.c | 6 +++--- sound/soc/soc-core.c | 2 +- sound/soc/soc-dapm.c | 2 +- 16 files changed, 58 insertions(+), 61 deletions(-) diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 398ba9ba2632..ef9fd9b759cb 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -802,8 +802,8 @@ static ssize_t battery_voltage_show(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", sharpsl_pm.battstat.mainbat_voltage); } -static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL); -static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL); +static DEVICE_ATTR_RO(battery_percentage); +static DEVICE_ATTR_RO(battery_voltage); extern void (*apm_get_power_status)(struct apm_power_info *); diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c index a17181160233..762bc5619910 100644 --- a/arch/sh/drivers/push-switch.c +++ b/arch/sh/drivers/push-switch.c @@ -24,7 +24,7 @@ static ssize_t switch_show(struct device *dev, struct push_switch_platform_info *psw_info = dev->platform_data; return sprintf(buf, "%s\n", psw_info->name); } -static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL); +static DEVICE_ATTR_RO(switch); static void switch_timer(struct timer_list *t) { diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c index af5024f0fb5a..b09456a3d77a 100644 --- a/arch/tile/kernel/sysfs.c +++ b/arch/tile/kernel/sysfs.c @@ -38,7 +38,7 @@ static ssize_t chip_width_show(struct device *dev, { return sprintf(page, "%u\n", smp_width); } -static DEVICE_ATTR(chip_width, 0444, chip_width_show, NULL); +static DEVICE_ATTR_RO(chip_width); static ssize_t chip_height_show(struct device *dev, struct device_attribute *attr, @@ -46,7 +46,7 @@ static ssize_t chip_height_show(struct device *dev, { return sprintf(page, "%u\n", smp_height); } -static DEVICE_ATTR(chip_height, 0444, chip_height_show, NULL); +static DEVICE_ATTR_RO(chip_height); static ssize_t chip_serial_show(struct device *dev, struct device_attribute *attr, @@ -54,7 +54,7 @@ static ssize_t chip_serial_show(struct device *dev, { return get_hv_confstr(page, HV_CONFSTR_CHIP_SERIAL_NUM); } -static DEVICE_ATTR(chip_serial, 0444, chip_serial_show, NULL); +static DEVICE_ATTR_RO(chip_serial); static ssize_t chip_revision_show(struct device *dev, struct device_attribute *attr, @@ -62,7 +62,7 @@ static ssize_t chip_revision_show(struct device *dev, { return get_hv_confstr(page, HV_CONFSTR_CHIP_REV); } -static DEVICE_ATTR(chip_revision, 0444, chip_revision_show, NULL); +static DEVICE_ATTR_RO(chip_revision); static ssize_t type_show(struct device *dev, @@ -71,7 +71,7 @@ static ssize_t type_show(struct device *dev, { return sprintf(page, "tilera\n"); } -static DEVICE_ATTR(type, 0444, type_show, NULL); +static DEVICE_ATTR_RO(type); #define HV_CONF_ATTR(name, conf) \ static ssize_t name ## _show(struct device *dev,\ diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index a041689e5701..545e91420cde 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -357,7 +357,7 @@ static ssize_t real_power_state_show(struct device *dev, return sprintf(buf, "%s\n", acpi_power_state_string(state)); } -static DEVICE_ATTR(real_power_state, 0444, real_power_state_show, NULL); +static DEVICE_ATTR_RO(real_power_state); static ssize_t
[PATCH v1] libsas: remove private hex2bin() implementation
The function sas_parse_addr() could be easily substituted by hex2bin() which is in kernel library code. Cc: Christoph HellwigSigned-off-by: Andy Shevchenko --- drivers/scsi/libsas/sas_scsi_host.c | 20 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 58476b728c57..626727207889 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "sas_internal.h" @@ -946,21 +947,6 @@ void sas_target_destroy(struct scsi_target *starget) sas_put_device(found_dev); } -static void sas_parse_addr(u8 *sas_addr, const char *p) -{ - int i; - for (i = 0; i < SAS_ADDR_SIZE; i++) { - u8 h, l; - if (!*p) - break; - h = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10; - p++; - l = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10; - p++; - sas_addr[i] = (h<<4) | l; - } -} - #define SAS_STRING_ADDR_SIZE 16 int sas_request_addr(struct Scsi_Host *shost, u8 *addr) @@ -977,7 +963,9 @@ int sas_request_addr(struct Scsi_Host *shost, u8 *addr) goto out; } - sas_parse_addr(addr, fw->data); + res = hex2bin(addr, fw->data, strnlen(fw->data, SAS_ADDR_SIZE * 2) / 2); + if (res) + goto out; out: release_firmware(fw); -- 2.15.1
[PATCH v1] scsi: hpsa: Use vsnprintf extension %phN
Using this extension reduces the object size. Signed-off-by: Andy Shevchenko--- drivers/scsi/hpsa.c | 14 +++--- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b0aa5dc1d54c..4c018b653f18 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4619,21 +4619,13 @@ static int hpsa_scatter_gather(struct ctlr_info *h, return 0; } -#define BUFLEN 128 static inline void warn_zero_length_transfer(struct ctlr_info *h, u8 *cdb, int cdb_len, const char *func) { - char buf[BUFLEN]; - int outlen; - int i; - - outlen = scnprintf(buf, BUFLEN, - "%s: Blocking zero-length request: CDB:", func); - for (i = 0; i < cdb_len; i++) - outlen += scnprintf(buf+outlen, BUFLEN - outlen, - "%02hhx", cdb[i]); - dev_warn(>pdev->dev, "%s\n", buf); + dev_warn(>pdev->dev, +"%s: Blocking zero-length request: CDB:%*phN\n", +func, cdb_len, cdb); } #define IO_ACCEL_INELIGIBLE 1 -- 2.15.1
Re: [trivial PATCH] treewide: Align function definition open/close braces
Em Sun, 17 Dec 2017 16:28:44 -0800 Joe Perchesescreveu: > Some functions definitions have either the initial open brace and/or > the closing brace outside of column 1. > > Move those braces to column 1. > > This allows various function analyzers like gnu complexity to work > properly for these modified functions. > > Miscellanea: > > o Remove extra trailing ; and blank line from xfs_agf_verify > > Signed-off-by: Joe Perches For the media patch: Acked-by: Mauro Carvalho Chehab > --- > git diff -w shows no difference other than the above 'Miscellanea' > > (this is against -next, but it applies against Linus' tree > with a couple offsets) > > arch/x86/include/asm/atomic64_32.h | 2 +- > drivers/acpi/custom_method.c | 2 +- > drivers/acpi/fan.c | 2 +- > drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- > drivers/media/i2c/msp3400-kthreads.c | 2 +- > drivers/message/fusion/mptsas.c | 2 +- > drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | 2 +- > drivers/net/wireless/ath/ath9k/xmit.c| 2 +- > drivers/platform/x86/eeepc-laptop.c | 2 +- > drivers/rtc/rtc-ab-b5ze-s3.c | 2 +- > drivers/scsi/dpt_i2o.c | 2 +- > drivers/scsi/sym53c8xx_2/sym_glue.c | 2 +- > fs/locks.c | 2 +- > fs/ocfs2/stack_user.c| 2 +- > fs/xfs/libxfs/xfs_alloc.c| 5 ++--- > fs/xfs/xfs_export.c | 2 +- > kernel/audit.c | 6 +++--- > kernel/trace/trace_printk.c | 4 ++-- > lib/raid6/sse2.c | 14 +++--- > sound/soc/fsl/fsl_dma.c | 2 +- > 20 files changed, 30 insertions(+), 31 deletions(-) > > diff --git a/arch/x86/include/asm/atomic64_32.h > b/arch/x86/include/asm/atomic64_32.h > index 97c46b8169b7..d4d4883080fa 100644 > --- a/arch/x86/include/asm/atomic64_32.h > +++ b/arch/x86/include/asm/atomic64_32.h > @@ -122,7 +122,7 @@ static inline long long atomic64_read(const atomic64_t *v) > long long r; > alternative_atomic64(read, "=" (r), "c" (v) : "memory"); > return r; > - } > +} > > /** > * atomic64_add_return - add and return > diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c > index c68e72414a67..e967c1173ba3 100644 > --- a/drivers/acpi/custom_method.c > +++ b/drivers/acpi/custom_method.c > @@ -94,7 +94,7 @@ static void __exit acpi_custom_method_exit(void) > { > if (cm_dentry) > debugfs_remove(cm_dentry); > - } > +} > > module_init(acpi_custom_method_init); > module_exit(acpi_custom_method_exit); > diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c > index 6cf4988206f2..3563103590c6 100644 > --- a/drivers/acpi/fan.c > +++ b/drivers/acpi/fan.c > @@ -219,7 +219,7 @@ fan_set_cur_state(struct thermal_cooling_device *cdev, > unsigned long state) > return fan_set_state_acpi4(device, state); > else > return fan_set_state(device, state); > - } > +} > > static const struct thermal_cooling_device_ops fan_cooling_ops = { > .get_max_state = fan_get_max_state, > diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c > b/drivers/gpu/drm/amd/display/dc/core/dc.c > index d1488d5ee028..1e0d1e7c5324 100644 > --- a/drivers/gpu/drm/amd/display/dc/core/dc.c > +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c > @@ -461,7 +461,7 @@ static void disable_dangling_plane(struct dc *dc, struct > dc_state *context) > > **/ > > struct dc *dc_create(const struct dc_init_data *init_params) > - { > +{ > struct dc *dc = kzalloc(sizeof(*dc), GFP_KERNEL); > unsigned int full_pipe_count; > > diff --git a/drivers/media/i2c/msp3400-kthreads.c > b/drivers/media/i2c/msp3400-kthreads.c > index 4dd01e9f553b..dc6cb8d475b3 100644 > --- a/drivers/media/i2c/msp3400-kthreads.c > +++ b/drivers/media/i2c/msp3400-kthreads.c > @@ -885,7 +885,7 @@ static int msp34xxg_modus(struct i2c_client *client) > } > > static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) > - { > +{ > struct msp_state *state = to_state(i2c_get_clientdata(client)); > int source, matrix; > > diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c > index 345f6035599e..69a62d23514b 100644 > --- a/drivers/message/fusion/mptsas.c > +++ b/drivers/message/fusion/mptsas.c > @@ -2968,7 +2968,7 @@ mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc, > mutex_unlock(>sas_mgmt.mutex); > out: > return ret; > - } > +} > > static void >