RE: [PATCH v1 0/2] scsi: ufs: Fix broken hba->outstanding_tasks
Stanley, > > Hi Avri, > > On Mon, 2019-07-22 at 06:10 +, Avri Altman wrote: > > > > > > > > > > > Hi, > > > > > > > > > > > > > > Currently bits in hba->outstanding_tasks are cleared only after their > > > > > corresponding task management commands are successfully done > by > > > > > __ufshcd_issue_tm_cmd(). > > > > > > > > > > If timeout happens in a task management command, its > corresponding > > > > > bit in hba->outstanding_tasks will not be cleared until next task > > > > > management command with the same tag used successfully > finishes.‧ > > > > ufshcd_clear_tm_cmd is also called as part of ufshcd_err_handler. > > > > Does this change something in your assumptions? > > > And BTW there is a specific __clear_bit in __ufshcd_issue_tm_cmd() in > case > > > of a TO. > > > > Gave it another look - > > If indeed this bit isn't cleared as part of the error flow that the timeout > triggers, > > I think you should relate to ufshcd_clear_tm_cmd specifically in your > commit log - > > Because this is the obvious place where the bit cleanup should take > place. > > > > Also the fix should be much more intuitive IMO - > > Today we do __clear_bit() on success, ufshcd_clear_tm_cmd() on error, > > And also ufshcd_put_tm_slot() either way? > > > > Maybe you can choose a single place to clear it, without any additional > code? > > ufshcd_clear_tm_cmd() is similar to ufshcd_clear_cmd() which tries to > write timed-out bit in "clear register". They do not clean bits in both > outstanding masks. > > Another reason to not to do outstanding bits cleanup in > ufshcd_clear_tm_cmd() is: if host is unable to clear TM command by > setting "clear register", the TM command may be still "outstanding" in > the device. In this case, it may be better to do cleanup after reset is > done. Cleanup includes bits in hba->outstanding_tasks and > hba->tm_slots_in_use which is possibly cleaned too early by > ufshcd_put_tm_slot() if command is timed-out now. > > Referring to error handling flow of hba->outstanding_reqs, all timed-out > bits will be cleaned by ufshcd_reset_and_restore() => > ufshcd_transfer_req_compl() after reset is done. Similar handling for > hba->outstanding_tasks could be applied, i.e., do cleanup by > ufshcd_reset_and_restore() => ufshcd_tmc_handler(). Fair enough. Thank you for the detailed explanation. > > The next thing is what you suggested: How to make the fix more > intuitive. Patchset v2 will be uploaded for review: It tries to > "re-factor" cleanup jobs first, and then add fixed flow to make the > whole patch more readable. > > One more thing, above description and flow is done through UFSHCD SCSI > error handling routines registered with SCSI Midlayer. For TM command > timeout happening in bsg path without error handling triggered by SCSI > layer, we may need to consider to handle those tasks in future patches. Please do. Thanks, Avri
[PATCH 3/3] fcoe: pass in fcoe_rport structure instead of fc_rport_priv
Instead of using the generic 'fc_rport_priv' structure as argument and then having to painstakingly outcast this to fcoe_rport we should be passing the fcoe_rport structure itself and reduce complexity. Signed-off-by: Hannes Reinecke Reviewed-by: Christoph Hellwig --- drivers/scsi/fcoe/fcoe_ctlr.c | 99 ++- 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 472626cfa150..267d68c94cb8 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2401,16 +2401,14 @@ static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip) /** * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request. * @fip: The FCoE controller - * @rdata: parsed remote port with frport from the probe request + * @frport: parsed FCoE rport from the probe request * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, - struct fc_rport_priv *rdata) + struct fcoe_rport *frport) { - struct fcoe_rport *frport = fcoe_ctlr_rport(rdata); - - if (rdata->ids.port_id != fip->port_id) + if (frport->rdata.ids.port_id != fip->port_id) return; switch (fip->state) { @@ -2430,7 +2428,7 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, * Probe's REC bit is not set. * If we don't reply, we will change our address. */ - if (fip->lp->wwpn > rdata->ids.port_name && + if (fip->lp->wwpn > frport->rdata.ids.port_name && !(frport->flags & FIP_FL_REC_OR_P2P)) { LIBFCOE_FIP_DBG(fip, "vn_probe_req: " "port_id collision\n"); @@ -2454,14 +2452,14 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, /** * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply. * @fip: The FCoE controller - * @rdata: parsed remote port with frport from the probe request + * @frport: parsed FCoE rport from the probe request * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip, - struct fc_rport_priv *rdata) +struct fcoe_rport *frport) { - if (rdata->ids.port_id != fip->port_id) + if (frport->rdata.ids.port_id != fip->port_id) return; switch (fip->state) { case FIP_ST_VNMP_START: @@ -2484,11 +2482,11 @@ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip, /** * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply. * @fip: The FCoE controller - * @new: newly-parsed remote port with frport as a template for new rdata + * @new: newly-parsed FCoE rport as a template for new rdata * * Called with ctlr_mutex held. */ -static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) +static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fcoe_rport *new) { struct fc_lport *lport = fip->lp; struct fc_rport_priv *rdata; @@ -2496,7 +2494,7 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) struct fcoe_rport *frport; u32 port_id; - port_id = new->ids.port_id; + port_id = new->rdata.ids.port_id; if (port_id == fip->port_id) return; @@ -2513,22 +2511,28 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) rdata->disc_id = lport->disc.disc_id; ids = &rdata->ids; - if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) || - (ids->node_name != -1 && ids->node_name != new->ids.node_name)) { + if ((ids->port_name != -1 && +ids->port_name != new->rdata.ids.port_name) || + (ids->node_name != -1 && +ids->node_name != new->rdata.ids.node_name)) { mutex_unlock(&rdata->rp_mutex); LIBFCOE_FIP_DBG(fip, "vn_add rport logoff %6.6x\n", port_id); fc_rport_logoff(rdata); mutex_lock(&rdata->rp_mutex); } - ids->port_name = new->ids.port_name; - ids->node_name = new->ids.node_name; + ids->port_name = new->rdata.ids.port_name; + ids->node_name = new->rdata.ids.node_name; mutex_unlock(&rdata->rp_mutex); frport = fcoe_ctlr_rport(rdata); LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s state %d\n", port_id, frport->fcoe_len ? "old" : "new", rdata->rp_state); - *frport = *fcoe_ctlr_rport(new); + frport->fcoe_len = new->fcoe_len; + frport->flags = new->flags; + frport->login_count = new->login_count; + memcpy(frport->enode_mac, new->enode_mac, ETH_ALEN); + memcpy(frport->vn_mac, new->vn_mac, ETH_
[PATCH 2/3] fcoe: Embed fc_rport_priv in fcoe_rport structure
Gcc-9 complains for a memset across pointer boundaries, which happens as the code tries to allocate a flexible array on the stack. Turns out we cannot do this without relying on gcc-isms, so with this patch we'll embed the fc_rport_priv structure into fcoe_rport, can use the normal 'container_of' outcast, and will only have to do a memset over one structure. Signed-off-by: Hannes Reinecke --- drivers/scsi/fcoe/fcoe_ctlr.c | 51 +-- drivers/scsi/libfc/fc_rport.c | 5 - include/scsi/libfcoe.h| 1 + 3 files changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 0d7770d07405..472626cfa150 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2005,7 +2005,7 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); */ static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata) { - return (struct fcoe_rport *)(rdata + 1); + return container_of(rdata, struct fcoe_rport, rdata); } /** @@ -2269,7 +2269,7 @@ static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip) */ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip, struct sk_buff *skb, - struct fc_rport_priv *rdata) + struct fcoe_rport *frport) { struct fip_header *fiph; struct fip_desc *desc = NULL; @@ -2277,16 +2277,12 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip, struct fip_wwn_desc *wwn = NULL; struct fip_vn_desc *vn = NULL; struct fip_size_desc *size = NULL; - struct fcoe_rport *frport; size_t rlen; size_t dlen; u32 desc_mask = 0; u32 dtype; u8 sub; - memset(rdata, 0, sizeof(*rdata) + sizeof(*frport)); - frport = fcoe_ctlr_rport(rdata); - fiph = (struct fip_header *)skb->data; frport->flags = ntohs(fiph->fip_flags); @@ -2349,15 +2345,17 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip, if (dlen != sizeof(struct fip_wwn_desc)) goto len_err; wwn = (struct fip_wwn_desc *)desc; - rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn); + frport->rdata.ids.node_name = + get_unaligned_be64(&wwn->fd_wwn); break; case FIP_DT_VN_ID: if (dlen != sizeof(struct fip_vn_desc)) goto len_err; vn = (struct fip_vn_desc *)desc; memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN); - rdata->ids.port_id = ntoh24(vn->fd_fc_id); - rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn); + frport->rdata.ids.port_id = ntoh24(vn->fd_fc_id); + frport->rdata.ids.port_name = + get_unaligned_be64(&vn->fd_wwpn); break; case FIP_DT_FC4F: if (dlen != sizeof(struct fip_fc4_feat)) @@ -2738,10 +2736,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) { struct fip_header *fiph; enum fip_vn2vn_subcode sub; - struct { - struct fc_rport_priv rdata; - struct fcoe_rport frport; - } buf; + struct fcoe_rport frport = { }; int rc, vlan_id = 0; fiph = (struct fip_header *)skb->data; @@ -2757,7 +2752,7 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) goto drop; } - rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata); + rc = fcoe_ctlr_vn_parse(fip, skb, &frport); if (rc) { LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc); goto drop; @@ -2766,19 +2761,19 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) mutex_lock(&fip->ctlr_mutex); switch (sub) { case FIP_SC_VN_PROBE_REQ: - fcoe_ctlr_vn_probe_req(fip, &buf.rdata); + fcoe_ctlr_vn_probe_req(fip, &frport.rdata); break; case FIP_SC_VN_PROBE_REP: - fcoe_ctlr_vn_probe_reply(fip, &buf.rdata); + fcoe_ctlr_vn_probe_reply(fip, &frport.rdata); break; case FIP_SC_VN_CLAIM_NOTIFY: - fcoe_ctlr_vn_claim_notify(fip, &buf.rdata); + fcoe_ctlr_vn_claim_notify(fip, &frport.rdata); break; case FIP_SC_VN_CLAIM_REP: - fcoe_ctlr_vn_claim_resp(fip, &buf.rdata); + fcoe_ctlr_vn_claim_resp(fip, &frport.rdata); break; case FIP_SC_VN_BEACON: - fcoe_ctlr_vn_beacon(fip, &buf.rdata); + fcoe_ctlr_vn_beacon(fip, &frport.rdata);
[PATCH 1/3] libfc: Whitespqce cleanup in libfc.h
No functional change. Signed-off-by: Hannes Reinecke Reviewed-by: Christoph Hellwig --- include/scsi/libfc.h | 52 ++-- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 76cb9192319a..aab23934f662 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -115,7 +115,7 @@ struct fc_disc_port { struct fc_lport*lp; struct list_head peers; struct work_struct rport_work; - u32port_id; + u32port_id; }; /** @@ -155,14 +155,14 @@ struct fc_rport_operations { */ struct fc_rport_libfc_priv { struct fc_lport*local_port; - enum fc_rport_staterp_state; + enum fc_rport_staterp_state; u16flags; #define FC_RP_FLAGS_REC_SUPPORTED (1 << 0) #define FC_RP_FLAGS_RETRY (1 << 1) #define FC_RP_STARTED (1 << 2) #define FC_RP_FLAGS_CONF_REQ(1 << 3) - unsigned int e_d_tov; - unsigned int r_a_tov; + unsigned int e_d_tov; + unsigned int r_a_tov; }; /** @@ -191,24 +191,24 @@ struct fc_rport_priv { struct fc_lport *local_port; struct fc_rport *rport; struct kref kref; - enum fc_rport_state rp_state; + enum fc_rport_state rp_state; struct fc_rport_identifiers ids; u16 flags; - u16 max_seq; + u16 max_seq; u16 disc_id; u16 maxframe_size; - unsigned intretries; - unsigned intmajor_retries; - unsigned inte_d_tov; - unsigned intr_a_tov; - struct mutexrp_mutex; + unsigned intretries; + unsigned intmajor_retries; + unsigned inte_d_tov; + unsigned intr_a_tov; + struct mutexrp_mutex; struct delayed_work retry_work; - enum fc_rport_event event; + enum fc_rport_event event; struct fc_rport_operations *ops; - struct list_headpeers; - struct work_struct event_work; + struct list_headpeers; + struct work_struct event_work; u32 supported_classes; - u16 prli_count; + u16 prli_count; struct rcu_head rcu; u16 sp_features; u8 spp_type; @@ -618,12 +618,12 @@ struct libfc_function_template { * @disc_callback: Callback routine called when discovery completes */ struct fc_disc { - unsigned char retry_count; - unsigned char pending; - unsigned char requested; - unsigned shortseq_count; - unsigned char buf_len; - u16 disc_id; + unsigned char retry_count; + unsigned char pending; + unsigned char requested; + unsigned shortseq_count; + unsigned char buf_len; + u16 disc_id; struct list_head rports; void *priv; @@ -697,7 +697,7 @@ struct fc_lport { struct fc_rport_priv *ms_rdata; struct fc_rport_priv *ptp_rdata; void *scsi_priv; - struct fc_disc disc; + struct fc_disc disc; /* Virtual port information */ struct list_head vports; @@ -715,7 +715,7 @@ struct fc_lport { u8 retry_count; /* Fabric information */ - u32port_id; + u32port_id; u64wwpn; u64wwnn; unsigned int service_params; @@ -743,11 +743,11 @@ struct fc_lport { struct fc_ns_fts fcts; /* Miscellaneous */ - struct mutex lp_mutex; - struct list_head list; + struct mutex lp_mutex; + struct list_head list; struct delayed_workretry_work; void *prov[FC_FC4_PROV_SIZE]; - struct list_head lport_list; + struct list_head lport_list; }; /** -- 2.16.4
[PATCHv3 0/3] fcoe: cleanup fc_rport_priv usage
Hi all, the fcoe vn2vn code is using the 'fc_rport_priv' structure as argument to its internal function, but is really expecting a struct fcoe_rport to immediately follow this one. This is not only confusing but also an error for new compilers. So clean up the usage by embedding fc_rport_priv into fcoe_rport, and use the fcoe_rport structure wherever possible. This patchset also contains some minor whitespace cleanups for libfc.h. As usual, comments and reviews are welcome. Changes to v1: - Drop patch to remove lld_event_callback Changes to v2: - Include reviews from Christoph Hannes Reinecke (3): libfc: Whitespqce cleanup in libfc.h fcoe: Embed fc_rport_priv in fcoe_rport structure fcoe: pass in fcoe_rport structure instead of fc_rport_priv drivers/scsi/fcoe/fcoe_ctlr.c | 138 -- drivers/scsi/libfc/fc_rport.c | 5 +- include/scsi/libfc.h | 52 include/scsi/libfcoe.h| 1 + 4 files changed, 96 insertions(+), 100 deletions(-) -- 2.16.4
LOANS !!!
Dial Direct Loan SA Consolidate your debts with Dial Direct Loan SA for your peace of mind at a fixed interest rate of 4.75%,personal and business loans are also welcome.For details file in your applications by sending an email to:dialdirectloan...@mail2consultant.com. Yours in Service, Susan Muller (Mrs.), Senior Consultant, Loan Application Team Dial Direct Loan SA Tel No: +27717231058
[PATCH 0/2] hpsa updates
These patches are based on Linus's tree The changes are: hpsa-correct-scsi-command-status-issue-after-reset . ensure command status is 0 for submitted commands. hpsa-remove-printing-internal-cdb-on-tag-collision . remove racy call to print an scsi command from our internal submission queue. . completion thread can be cleaning up the command in parallel --- Don Brace (2): hpsa: correct scsi command status issue after reset hpsa: remove printing internal cdb on tag collision drivers/scsi/hpsa.c | 14 +++--- 1 file changed, 11 insertions(+), 3 deletions(-) -- Signature
[PATCH 1/2] hpsa: correct scsi command status issue after reset
Reviewed-by: Bader Ali - Saleh Reviewed-by: Scott Teel Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 43a6b5350775..89e71ebc5964 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2334,6 +2334,8 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, case IOACCEL2_SERV_RESPONSE_COMPLETE: switch (c2->error_data.status) { case IOACCEL2_STATUS_SR_TASK_COMP_GOOD: + if (cmd) + cmd->result = 0; break; case IOACCEL2_STATUS_SR_TASK_COMP_CHK_COND: cmd->result |= SAM_STAT_CHECK_CONDITION; @@ -2483,8 +2485,10 @@ static void process_ioaccel2_completion(struct ctlr_info *h, /* check for good status */ if (likely(c2->error_data.serv_response == 0 && - c2->error_data.status == 0)) + c2->error_data.status == 0)) { + cmd->result = 0; return hpsa_cmd_free_and_done(h, c, cmd); + } /* * Any RAID offload error results in retry which will use @@ -5653,6 +5657,12 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) if (c == NULL) return SCSI_MLQUEUE_DEVICE_BUSY; + /* +* This is necessary because the SML doesn't zero out this field during +* error recovery. +*/ + cmd->result = 0; + /* * Call alternate submit routine for I/O accelerated commands. * Retries always go down the normal I/O path.
[PATCH 2/2] hpsa: remove printing internal cdb on tag collision
- remove racy printing of internal commands. . completion thread can be cleaning up the command in parallel Reviewed-by: Bader Ali - Saleh Reviewed-by: Scott Teel Reviewed-by: Scott Benesh Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 89e71ebc5964..bba099e53266 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6091,8 +6091,6 @@ static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h, if (idx != h->last_collision_tag) { /* Print once per tag */ dev_warn(&h->pdev->dev, "%s: tag collision (tag=%d)\n", __func__, idx); - if (c->scsi_cmd != NULL) - scsi_print_command(c->scsi_cmd); if (scmd) scsi_print_command(scmd); h->last_collision_tag = idx;
[PATCH] scsi: qla2xxx: replace snprintf with strscpy
As commit a86028f8e3ee ("staging: most: sound: replace snprintf with strscpy") suggested, using snprintf without a format specifier is potentially risky if a0->vendor_name or a0->vendor_pn mistakenly contain format specifiers. In addition, as compared in the implementation, strscpy looks more light-weight than snprintf. This patch does not incur any functional change. Signed-off-by: Wang Xiayang --- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 4059655639d9..068b54218ff4 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3461,12 +3461,12 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha) int leftover, len; memset(str, 0, STR_LEN); - snprintf(str, SFF_VEN_NAME_LEN+1, a0->vendor_name); + strscpy(str, a0->vendor_name, SFF_VEN_NAME_LEN+1); ql_dbg(ql_dbg_init, vha, 0x015a, "SFP MFG Name: %s\n", str); memset(str, 0, STR_LEN); - snprintf(str, SFF_PART_NAME_LEN+1, a0->vendor_pn); + strscpy(str, a0->vendor_pn, SFF_PART_NAME_LEN+1); ql_dbg(ql_dbg_init, vha, 0x015c, "SFP Part Name: %s\n", str); -- 2.11.0