From 4d2095cc42a2d8062590891f929d9d694cbd927f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:14 +0200 Subject: scsi: libfc: Revisit kref handling The kref handling in fc_rport is a mess. This patch updates the kref handling according to the following rules: - Take a reference whenever scheduling a workqueue - Take a reference whenever an ELS command is send - Drop the reference at the end of the workqueue function - Drop the reference at the end of handling ELS replies - Take a reference when allocating an rport - Drop the reference when removing an rport Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 131 ++++++++++++++++++++++++++++++++---------- 1 file changed, 101 insertions(+), 30 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 97aeaddd600d..4ec896e42120 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -44,6 +44,19 @@ * path this potential over-use of the mutex is acceptable. */ +/* + * RPORT REFERENCE COUNTING + * + * A rport reference should be taken when: + * - an rport is allocated + * - a workqueue item is scheduled + * - an ELS request is send + * The reference should be dropped when: + * - the workqueue function has finished + * - the ELS response is handled + * - an rport is removed + */ + #include #include #include @@ -242,6 +255,8 @@ static void fc_rport_state_enter(struct fc_rport_priv *rdata, /** * fc_rport_work() - Handler for remote port events in the rport_event_queue * @work: Handle to the remote port being dequeued + * + * Reference counting: drops kref on return */ static void fc_rport_work(struct work_struct *work) { @@ -329,7 +344,8 @@ static void fc_rport_work(struct work_struct *work) FC_RPORT_DBG(rdata, "lld callback ev %d\n", event); rdata->lld_event_callback(lport, rdata, event); } - cancel_delayed_work_sync(&rdata->retry_work); + if (cancel_delayed_work_sync(&rdata->retry_work)) + kref_put(&rdata->kref, lport->tt.rport_destroy); /* * Reset any outstanding exchanges before freeing rport. @@ -381,6 +397,7 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); break; } + kref_put(&rdata->kref, lport->tt.rport_destroy); } /** @@ -431,10 +448,14 @@ static int fc_rport_login(struct fc_rport_priv *rdata) * Set the new event so that the old pending event will not occur. * Since we have the mutex, even if fc_rport_work() is already started, * it'll see the new event. + * + * Reference counting: does not modify kref */ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, enum fc_rport_event event) { + struct fc_lport *lport = rdata->local_port; + if (rdata->rp_state == RPORT_ST_DELETE) return; @@ -442,8 +463,11 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, fc_rport_state_enter(rdata, RPORT_ST_DELETE); - if (rdata->event == RPORT_EV_NONE) - queue_work(rport_event_queue, &rdata->event_work); + kref_get(&rdata->kref); + if (rdata->event == RPORT_EV_NONE && + !queue_work(rport_event_queue, &rdata->event_work)) + kref_put(&rdata->kref, lport->tt.rport_destroy); + rdata->event = event; } @@ -496,15 +520,22 @@ out: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: schedules workqueue, does not modify kref */ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) { + struct fc_lport *lport = rdata->local_port; + fc_rport_state_enter(rdata, RPORT_ST_READY); FC_RPORT_DBG(rdata, "Port is Ready\n"); - if (rdata->event == RPORT_EV_NONE) - queue_work(rport_event_queue, &rdata->event_work); + kref_get(&rdata->kref); + if (rdata->event == RPORT_EV_NONE && + !queue_work(rport_event_queue, &rdata->event_work)) + kref_put(&rdata->kref, lport->tt.rport_destroy); + rdata->event = RPORT_EV_READY; } @@ -515,11 +546,14 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) * Locking Note: Called without the rport lock held. This * function will hold the rport lock, call an _enter_* * function and then unlock the rport. + * + * Reference counting: Drops kref on return. */ static void fc_rport_timeout(struct work_struct *work) { struct fc_rport_priv *rdata = container_of(work, struct fc_rport_priv, retry_work.work); + struct fc_lport *lport = rdata->local_port; mutex_lock(&rdata->rp_mutex); @@ -547,6 +581,7 @@ static void fc_rport_timeout(struct work_struct *work) } mutex_unlock(&rdata->rp_mutex); + kref_put(&rdata->kref, lport->tt.rport_destroy); } /** @@ -556,6 +591,8 @@ static void fc_rport_timeout(struct work_struct *work) * * Locking Note: The rport lock is expected to be held before * calling this routine + * + * Reference counting: does not modify kref */ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) { @@ -602,11 +639,14 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) * * Locking Note: The rport lock is expected to be held before * calling this routine + * + * Reference counting: increments kref when scheduling retry_work */ static void fc_rport_error_retry(struct fc_rport_priv *rdata, struct fc_frame *fp) { unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV); + struct fc_lport *lport = rdata->local_port; /* make sure this isn't an FC_EX_CLOSED error, never retry those */ if (PTR_ERR(fp) == -FC_EX_CLOSED) @@ -619,7 +659,9 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, /* no additional delay on exchange timeouts */ if (PTR_ERR(fp) == -FC_EX_TIMEOUT) delay = 0; - schedule_delayed_work(&rdata->retry_work, delay); + kref_get(&rdata->kref); + if (!schedule_delayed_work(&rdata->retry_work, delay)) + kref_put(&rdata->kref, lport->tt.rport_destroy); return; } @@ -740,6 +782,8 @@ bad: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) { @@ -758,18 +802,21 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) if (!fp) return fc_rport_error_retry(rdata, fp); + kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI, fc_rport_flogi_resp, rdata, - 2 * lport->r_a_tov)) + 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** * fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode * @lport: The local port that received the PLOGI request * @rx_fp: The PLOGI request frame + * + * Reference counting: drops kref on return */ static void fc_rport_recv_flogi_req(struct fc_lport *lport, struct fc_frame *rx_fp) @@ -824,8 +871,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, * RPORT wouldn;t have created and 'rport_lookup' would have * failed anyway in that case. */ - if (lport->point_to_multipoint) - break; + break; case RPORT_ST_DELETE: mutex_unlock(&rdata->rp_mutex); rjt_data.reason = ELS_RJT_FIP; @@ -969,6 +1015,8 @@ fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata) * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) { @@ -995,12 +1043,13 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) } rdata->e_d_tov = lport->e_d_tov; + kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, fc_rport_plogi_resp, rdata, - 2 * lport->r_a_tov)) + 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** @@ -1108,6 +1157,8 @@ err: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) { @@ -1151,11 +1202,12 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) fc_host_port_id(lport->host), FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); + kref_get(&rdata->kref); if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp, - NULL, rdata, 2 * lport->r_a_tov)) + NULL, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** @@ -1230,6 +1282,8 @@ err: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) { @@ -1247,12 +1301,13 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) return; } + kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, fc_rport_rtv_resp, rdata, - 2 * lport->r_a_tov)) + 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** @@ -1262,15 +1317,16 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) * @lport_arg: The local port */ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, - void *lport_arg) + void *rdata_arg) { - struct fc_lport *lport = lport_arg; + struct fc_rport_priv *rdata = rdata_arg; + struct fc_lport *lport = rdata->local_port; FC_RPORT_ID_DBG(lport, fc_seq_exch(sp)->did, "Received a LOGO %s\n", fc_els_resp_type(fp)); - if (IS_ERR(fp)) - return; - fc_frame_free(fp); + if (!IS_ERR(fp)) + fc_frame_free(fp); + kref_put(&rdata->kref, lport->tt.rport_destroy); } /** @@ -1279,6 +1335,8 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) { @@ -1291,8 +1349,10 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo)); if (!fp) return; - (void)lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, - fc_rport_logo_resp, lport, 0); + kref_get(&rdata->kref); + if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, + fc_rport_logo_resp, rdata, 0)) + kref_put(&rdata->kref, lport->tt.rport_destroy); } /** @@ -1359,6 +1419,8 @@ err: * * Locking Note: The rport lock is expected to be held before calling * this routine. + * + * Reference counting: increments kref when sending ELS */ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) { @@ -1375,12 +1437,13 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) fc_rport_error_retry(rdata, fp); return; } + kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, fc_rport_adisc_resp, rdata, - 2 * lport->r_a_tov)) + 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, NULL); - else - kref_get(&rdata->kref); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } } /** @@ -1494,6 +1557,8 @@ out: * The ELS opcode has already been validated by the caller. * * Locking Note: Called with the lport lock held. + * + * Reference counting: does not modify kref */ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) { @@ -1561,6 +1626,8 @@ reject: * @fp: The request frame * * Locking Note: Called with the lport lock held. + * + * Reference counting: does not modify kref */ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) { @@ -1605,6 +1672,8 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) * @rx_fp: The PLOGI request frame * * Locking Note: The rport lock is held before calling this function. + * + * Reference counting: increments kref on return */ static void fc_rport_recv_plogi_req(struct fc_lport *lport, struct fc_frame *rx_fp) @@ -1919,6 +1988,8 @@ drop: * * Locking Note: The rport lock is expected to be held before calling * this function. + * + * Reference counting: drops kref on return */ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) { -- cgit v1.2.3 From a407c593398c886db4fa1fc5c6fec55e61187a09 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:15 +0200 Subject: scsi: libfc: Fixup disc_mutex handling The list of attached 'rdata' remote port structures is RCU protected, so there is no need to take the 'disc_mutex' when traversing it. Rather we should be using rcu_read_lock() and kref_get_unless_zero() to validate the entries. We need, however, take the disc_mutex when deleting an entry; otherwise we risk clashes with list_add. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_disc.c | 38 +++++++++++++++++++++++++------------- drivers/scsi/libfc/fc_lport.c | 9 +++++++-- drivers/scsi/libfc/fc_rport.c | 2 ++ 3 files changed, 34 insertions(+), 15 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 880a9068ca12..ad3965f9d03d 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -68,10 +68,14 @@ static void fc_disc_stop_rports(struct fc_disc *disc) lport = fc_disc_lport(disc); - mutex_lock(&disc->disc_mutex); - list_for_each_entry_rcu(rdata, &disc->rports, peers) - lport->tt.rport_logoff(rdata); - mutex_unlock(&disc->disc_mutex); + rcu_read_lock(); + list_for_each_entry_rcu(rdata, &disc->rports, peers) { + if (kref_get_unless_zero(&rdata->kref)) { + lport->tt.rport_logoff(rdata); + kref_put(&rdata->kref, lport->tt.rport_destroy); + } + } + rcu_read_unlock(); } /** @@ -289,15 +293,19 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) * Skip ports which were never discovered. These are the dNS port * and ports which were created by PLOGI. */ + rcu_read_lock(); list_for_each_entry_rcu(rdata, &disc->rports, peers) { - if (!rdata->disc_id) + if (!kref_get_unless_zero(&rdata->kref)) continue; - if (rdata->disc_id == disc->disc_id) - lport->tt.rport_login(rdata); - else - lport->tt.rport_logoff(rdata); + if (rdata->disc_id) { + if (rdata->disc_id == disc->disc_id) + lport->tt.rport_login(rdata); + else + lport->tt.rport_logoff(rdata); + } + kref_put(&rdata->kref, lport->tt.rport_destroy); } - + rcu_read_unlock(); mutex_unlock(&disc->disc_mutex); disc->disc_callback(lport, event); mutex_lock(&disc->disc_mutex); @@ -592,7 +600,6 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, lport = rdata->local_port; disc = &lport->disc; - mutex_lock(&disc->disc_mutex); if (PTR_ERR(fp) == -FC_EX_CLOSED) goto out; if (IS_ERR(fp)) @@ -607,16 +614,19 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, goto redisc; pn = (struct fc_ns_gid_pn *)(cp + 1); port_name = get_unaligned_be64(&pn->fn_wwpn); + mutex_lock(&rdata->rp_mutex); if (rdata->ids.port_name == -1) rdata->ids.port_name = port_name; else if (rdata->ids.port_name != port_name) { FC_DISC_DBG(disc, "GPN_ID accepted. WWPN changed. " "Port-id %6.6x wwpn %16.16llx\n", rdata->ids.port_id, port_name); + mutex_unlock(&rdata->rp_mutex); lport->tt.rport_logoff(rdata); - + mutex_lock(&lport->disc.disc_mutex); new_rdata = lport->tt.rport_create(lport, rdata->ids.port_id); + mutex_unlock(&lport->disc.disc_mutex); if (new_rdata) { new_rdata->disc_id = disc->disc_id; lport->tt.rport_login(new_rdata); @@ -624,6 +634,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, goto out; } rdata->disc_id = disc->disc_id; + mutex_unlock(&rdata->rp_mutex); lport->tt.rport_login(rdata); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n", @@ -633,10 +644,11 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DISC_DBG(disc, "GPN_ID unexpected response code %x\n", ntohs(cp->ct_cmd)); redisc: + mutex_lock(&disc->disc_mutex); fc_disc_restart(disc); + mutex_unlock(&disc->disc_mutex); } out: - mutex_unlock(&disc->disc_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); } diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 04ce7cfb6d1b..4e11c90c783c 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -237,16 +237,19 @@ static const char *fc_lport_state(struct fc_lport *lport) * @remote_fid: The FID of the ptp rport * @remote_wwpn: The WWPN of the ptp rport * @remote_wwnn: The WWNN of the ptp rport + * + * Locking Note: The lport lock is expected to be held before calling + * this routine. */ static void fc_lport_ptp_setup(struct fc_lport *lport, u32 remote_fid, u64 remote_wwpn, u64 remote_wwnn) { - mutex_lock(&lport->disc.disc_mutex); if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); } + mutex_lock(&lport->disc.disc_mutex); lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); kref_get(&lport->ptp_rdata->kref); lport->ptp_rdata->ids.port_name = remote_wwpn; @@ -1007,8 +1010,10 @@ EXPORT_SYMBOL(fc_lport_reset); */ static void fc_lport_reset_locked(struct fc_lport *lport) { - if (lport->dns_rdata) + if (lport->dns_rdata) { lport->tt.rport_logoff(lport->dns_rdata); + lport->dns_rdata = NULL; + } if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4ec896e42120..a0ceba10c679 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -378,7 +378,9 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); } else { FC_RPORT_DBG(rdata, "work delete\n"); + mutex_lock(&lport->disc.disc_mutex); list_del_rcu(&rdata->peers); + mutex_unlock(&lport->disc.disc_mutex); mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); } -- cgit v1.2.3 From 785141c62a26f055b27355ee9234e145955a51c6 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Fri, 30 Sep 2016 11:01:16 +0200 Subject: scsi: libfc: Do not take rdata->rp_mutex when processing a -FC_EX_CLOSED ELS response. When an ELS response handler receives a -FC_EX_CLOSED, the rdata->rp_mutex is already held which can lead to a deadlock condition like the following stack trace: [] fc_rport_plogi_resp+0x28/0x200 [libfc] [] fc_invoke_resp+0x6a/0xe0 [libfc] [] fc_exch_mgr_reset+0x1b8/0x280 [libfc] [] fc_rport_logoff+0x43/0xd0 [libfc] [] fc_disc_stop+0x6d/0xf0 [libfc] [] fc_disc_stop_final+0xe/0x20 [libfc] [] fc_fabric_logoff+0x17/0x70 [libfc] The other ELS handlers need to follow the FLOGI response handler and simply do a kref_put against the fc_rport_priv struct and exit when receving a -FC_EX_CLOSED response. Signed-off-by: Chad Dupuis Reviewed-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index a0ceba10c679..ff33ae6bdf7c 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -952,10 +952,13 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, u16 cssp_seq; u8 op; - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "Received a PLOGI %s\n", fc_els_resp_type(fp)); + if (fp == ERR_PTR(-FC_EX_CLOSED)) + goto put; + + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state != RPORT_ST_PLOGI) { FC_RPORT_DBG(rdata, "Received a PLOGI response, but in state " "%s\n", fc_rport_state(rdata)); @@ -994,6 +997,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, lport->tt.rport_destroy); } @@ -1079,10 +1083,13 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, u8 op; u8 resp_code = 0; - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "Received a PRLI %s\n", fc_els_resp_type(fp)); + if (fp == ERR_PTR(-FC_EX_CLOSED)) + goto put; + + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state != RPORT_ST_PRLI) { FC_RPORT_DBG(rdata, "Received a PRLI response, but in state " "%s\n", fc_rport_state(rdata)); @@ -1150,6 +1157,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } @@ -1230,10 +1238,13 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_rport_priv *rdata = rdata_arg; u8 op; - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "Received a RTV %s\n", fc_els_resp_type(fp)); + if (fp == ERR_PTR(-FC_EX_CLOSED)) + goto put; + + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state != RPORT_ST_RTV) { FC_RPORT_DBG(rdata, "Received a RTV response, but in state " "%s\n", fc_rport_state(rdata)); @@ -1275,6 +1286,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } @@ -1374,10 +1386,13 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_els_adisc *adisc; u8 op; - mutex_lock(&rdata->rp_mutex); - FC_RPORT_DBG(rdata, "Received a ADISC response\n"); + if (fp == ERR_PTR(-FC_EX_CLOSED)) + goto put; + + mutex_lock(&rdata->rp_mutex); + if (rdata->rp_state != RPORT_ST_ADISC) { FC_RPORT_DBG(rdata, "Received a ADISC resp but in state %s\n", fc_rport_state(rdata)); @@ -1412,6 +1427,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } -- cgit v1.2.3 From e5a20009dae054344d71a79e9bfbea84152f3eb8 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:17 +0200 Subject: scsi: libfc: Do not drop down to FLOGI for fc_rport_login() When fc_rport_login() is called while the rport is not in RPORT_ST_INIT, RPORT_ST_READY, or RPORT_ST_DELETE login is already in progress and there's no need to drop down to FLOGI; doing so will only confuse the other side. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index ff33ae6bdf7c..4e4087a00836 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -427,10 +427,14 @@ static int fc_rport_login(struct fc_rport_priv *rdata) case RPORT_ST_DELETE: FC_RPORT_DBG(rdata, "Restart deleted port\n"); break; - default: + case RPORT_ST_INIT: FC_RPORT_DBG(rdata, "Login to port\n"); fc_rport_enter_flogi(rdata); break; + default: + FC_RPORT_DBG(rdata, "Login in progress, state %s\n", + fc_rport_state(rdata)); + break; } mutex_unlock(&rdata->rp_mutex); -- cgit v1.2.3 From 06ee2571a438653bd14c33c70379a5f008a91901 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:18 +0200 Subject: scsi: libfc: Do not login if the port is already started When the port is already started we don't need to login; that will only confuse the state machine. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4e4087a00836..72a7183fdd06 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -418,6 +418,12 @@ static int fc_rport_login(struct fc_rport_priv *rdata) { mutex_lock(&rdata->rp_mutex); + if (rdata->flags & FC_RP_STARTED) { + FC_RPORT_DBG(rdata, "port already started\n"); + mutex_unlock(&rdata->rp_mutex); + return 0; + } + rdata->flags |= FC_RP_STARTED; switch (rdata->rp_state) { case RPORT_ST_READY: -- cgit v1.2.3 From f89b8d67db792a8a303e14e3d02785035e6f1a05 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 30 Sep 2016 11:01:19 +0200 Subject: scsi: libfc: don't advance state machine for incoming FLOGI When we receive an FLOGI but have already sent our own we should not advance the state machine but rather wait for our FLOGI to return before continuing with PLOGI. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 72a7183fdd06..4b9bb6dd4004 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -765,8 +765,10 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, goto bad; flogi = fc_frame_payload_get(fp, sizeof(*flogi)); - if (!flogi) + if (!flogi) { + FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); goto bad; + } r_a_tov = ntohl(flogi->fl_csp.sp_r_a_tov); if (r_a_tov > rdata->r_a_tov) rdata->r_a_tov = r_a_tov; @@ -783,7 +785,6 @@ put: kref_put(&rdata->kref, lport->tt.rport_destroy); return; bad: - FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); fc_rport_error_retry(rdata, fp); goto out; } @@ -925,10 +926,17 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); lport->tt.frame_send(lport, fp); - if (rdata->ids.port_name < lport->wwpn) - fc_rport_enter_plogi(rdata); - else - fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT); + /* + * Do not proceed with the state machine if our + * FLOGI has crossed with an FLOGI from the + * remote port; wait for the FLOGI response instead. + */ + if (rdata->rp_state != RPORT_ST_FLOGI) { + if (rdata->ids.port_name < lport->wwpn) + fc_rport_enter_plogi(rdata); + else + fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT); + } out: mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); -- cgit v1.2.3 From f8f91f3f3120b2168189100c588aeaf2ff5e9ac4 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Fri, 14 Oct 2016 16:37:29 -0400 Subject: scsi: libfc: Revert "[SCSI] libfc: use offload EM instance again instead jumping to next EM" This reverts commit 3e22760d4db6fd89e0be46c3d132390a251da9c6. This revert came about because of efforts by Ewan Milne, Curtis Taylor and I. In researching this issue, significant performance issues were seen on large CPU count systems using the software FCOE stack. Hannes also weighed in. The same was not apparent on much smaller low count CPU systems. The behavior introduced by commit 3e22760d4db6fd89e0be46c3d132390a251da9c6 lands sup with large count CPU systems seeing continual blk_requeue_request() calls due to ML_QUEUE_HOST_BUSY. fc_exch_alloc() used to try all the available exchange managers in the list for an available exchange id, but this was changed in 2010 so that if the first matched exchange manager couldn't allocate one, it fails and we end up returning host busy. This was due to commit: Setting the ddp_min module parameter to fcoe to 128MB prevents the ->match function from permitting the use of the offload exchange manager for the frame, and we no longer see the problem with host busy status, since it uses the larger non-offloaded pool. Reverting commit 3e22760d4db6fd89e0be46c3d132390a251da9c6 was tested to also prevent the host busy issue due to failing allocations. Suggested-by: Ewan Milne Suggested-by: Curtis Taylor Tested-by: Laurence Oberman Signed-off-by: Laurence Oberman --- drivers/scsi/libfc/fc_exch.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 16ca31ad5ec0..dd95e2aece66 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -888,14 +888,19 @@ err: * EM is selected when a NULL match function pointer is encountered * or when a call to a match function returns true. */ -static inline struct fc_exch *fc_exch_alloc(struct fc_lport *lport, - struct fc_frame *fp) +static struct fc_exch *fc_exch_alloc(struct fc_lport *lport, + struct fc_frame *fp) { struct fc_exch_mgr_anchor *ema; + struct fc_exch *ep; - list_for_each_entry(ema, &lport->ema_list, ema_list) - if (!ema->match || ema->match(fp)) - return fc_exch_em_alloc(lport, ema->mp); + list_for_each_entry(ema, &lport->ema_list, ema_list) { + if (!ema->match || ema->match(fp)) { + ep = fc_exch_em_alloc(lport, ema->mp); + if (ep) + return ep; + } + } return NULL; } -- cgit v1.2.3 From 57d3ec7e468bb6659d9a461294d8747906fb7231 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:37 +0200 Subject: scsi: libfc: additional debugging messages Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 59 +++++++++++++++++++++++++++++++++++-------- drivers/scsi/libfc/fc_fcp.c | 41 ++++++++++++++++++++++++------ drivers/scsi/libfc/fc_rport.c | 25 ++++++++++++++---- 3 files changed, 101 insertions(+), 24 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index dd95e2aece66..91800cb776ec 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -362,8 +362,10 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep, fc_exch_hold(ep); /* hold for timer */ if (!queue_delayed_work(fc_exch_workqueue, &ep->timeout_work, - msecs_to_jiffies(timer_msec))) + msecs_to_jiffies(timer_msec))) { + FC_EXCH_DBG(ep, "Exchange already queued\n"); fc_exch_release(ep); + } } /** @@ -632,9 +634,13 @@ static int fc_exch_abort_locked(struct fc_exch *ep, struct fc_frame *fp; int error; + FC_EXCH_DBG(ep, "exch: abort, time %d msecs\n", timer_msec); if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL) || - ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) + ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) { + FC_EXCH_DBG(ep, "exch: already completed esb %x state %x\n", + ep->esb_stat, ep->state); return -ENXIO; + } /* * Send the abort on a new sequence if possible. @@ -758,7 +764,7 @@ static void fc_exch_timeout(struct work_struct *work) u32 e_stat; int rc = 1; - FC_EXCH_DBG(ep, "Exchange timed out\n"); + FC_EXCH_DBG(ep, "Exchange timed out state %x\n", ep->state); spin_lock_bh(&ep->ex_lock); if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) @@ -1263,8 +1269,10 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) */ if (fc_sof_needs_ack(fr_sof(rx_fp))) { fp = fc_frame_alloc(lport, 0); - if (!fp) + if (!fp) { + FC_EXCH_DBG(ep, "Drop ACK request, out of memory\n"); return; + } fh = fc_frame_header_get(fp); fh->fh_r_ctl = FC_RCTL_ACK_1; @@ -1317,13 +1325,18 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, struct fc_frame_header *rx_fh; struct fc_frame_header *fh; struct fc_ba_rjt *rp; + struct fc_seq *sp; struct fc_lport *lport; unsigned int f_ctl; lport = fr_dev(rx_fp); + sp = fr_seq(rx_fp); fp = fc_frame_alloc(lport, sizeof(*rp)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(fc_seq_exch(sp), + "Drop BA_RJT request, out of memory\n"); return; + } fh = fc_frame_header_get(fp); rx_fh = fc_frame_header_get(rx_fp); @@ -1388,14 +1401,17 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) if (!ep) goto reject; + FC_EXCH_DBG(ep, "exch: ABTS received\n"); fp = fc_frame_alloc(ep->lp, sizeof(*ap)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(ep, "Drop ABTS request, out of memory\n"); goto free; + } spin_lock_bh(&ep->ex_lock); if (ep->esb_stat & ESB_ST_COMPLETE) { spin_unlock_bh(&ep->ex_lock); - + FC_EXCH_DBG(ep, "exch: ABTS rejected, exchange complete\n"); fc_frame_free(fp); goto reject; } @@ -1789,11 +1805,16 @@ static void fc_seq_ls_acc(struct fc_frame *rx_fp) struct fc_lport *lport; struct fc_els_ls_acc *acc; struct fc_frame *fp; + struct fc_seq *sp; lport = fr_dev(rx_fp); + sp = fr_seq(rx_fp); fp = fc_frame_alloc(lport, sizeof(*acc)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(fc_seq_exch(sp), + "exch: drop LS_ACC, out of memory\n"); return; + } acc = fc_frame_payload_get(fp, sizeof(*acc)); memset(acc, 0, sizeof(*acc)); acc->la_cmd = ELS_LS_ACC; @@ -1816,11 +1837,16 @@ static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason, struct fc_lport *lport; struct fc_els_ls_rjt *rjt; struct fc_frame *fp; + struct fc_seq *sp; lport = fr_dev(rx_fp); + sp = fr_seq(rx_fp); fp = fc_frame_alloc(lport, sizeof(*rjt)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(fc_seq_exch(sp), + "exch: drop LS_ACC, out of memory\n"); return; + } rjt = fc_frame_payload_get(fp, sizeof(*rjt)); memset(rjt, 0, sizeof(*rjt)); rjt->er_cmd = ELS_LS_RJT; @@ -1980,15 +2006,23 @@ static void fc_exch_els_rec(struct fc_frame *rfp) ep = fc_exch_lookup(lport, sid == fc_host_port_id(lport->host) ? oxid : rxid); explan = ELS_EXPL_OXID_RXID; - if (!ep) + if (!ep) { + FC_LPORT_DBG(lport, + "REC request from %x: rxid %x oxid %x not found\n", + sid, rxid, oxid); goto reject; + } + FC_EXCH_DBG(ep, "REC request from %x: rxid %x oxid %x\n", + sid, rxid, oxid); if (ep->oid != sid || oxid != ep->oxid) goto rel; if (rxid != FC_XID_UNKNOWN && rxid != ep->rxid) goto rel; fp = fc_frame_alloc(lport, sizeof(*acc)); - if (!fp) + if (!fp) { + FC_EXCH_DBG(ep, "Drop REC request, out of memory\n"); goto out; + } acc = fc_frame_payload_get(fp, sizeof(*acc)); memset(acc, 0, sizeof(*acc)); @@ -2181,6 +2215,7 @@ static void fc_exch_rrq(struct fc_exch *ep) return; retry: + FC_EXCH_DBG(ep, "exch: RRQ send failed\n"); spin_lock_bh(&ep->ex_lock); if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) { spin_unlock_bh(&ep->ex_lock); @@ -2223,6 +2258,8 @@ static void fc_exch_els_rrq(struct fc_frame *fp) if (!ep) goto reject; spin_lock_bh(&ep->ex_lock); + FC_EXCH_DBG(ep, "RRQ request from %x: xid %x rxid %x oxid %x\n", + sid, xid, ntohs(rp->rrq_rx_id), ntohs(rp->rrq_ox_id)); if (ep->oxid != ntohs(rp->rrq_ox_id)) goto unlock_reject; if (ep->rxid != ntohs(rp->rrq_rx_id) && diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 5121272f28fd..5c6c73a80379 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -764,8 +764,11 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) fh = fc_frame_header_get(fp); r_ctl = fh->fh_r_ctl; - if (lport->state != LPORT_ST_READY) + if (lport->state != LPORT_ST_READY) { + FC_FCP_DBG(fsp, "lport state %d, ignoring r_ctl %x\n", + lport->state, r_ctl); goto out; + } if (fc_fcp_lock_pkt(fsp)) goto out; @@ -774,8 +777,10 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) goto unlock; } - if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING)) + if (fsp->state & (FC_SRB_ABORTED | FC_SRB_ABORT_PENDING)) { + FC_FCP_DBG(fsp, "command aborted, ignoring r_ctl %x\n", r_ctl); goto unlock; + } if (r_ctl == FC_RCTL_DD_DATA_DESC) { /* @@ -910,6 +915,10 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * Wait a at least one jiffy to see if it is delivered. * If this expires without data, we may do SRR. */ + FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun " + "len %x, data len %x\n", + fsp->rport->port_id, + fsp->xfer_len, expected_len, fsp->data_len); fc_fcp_timer_set(fsp, 2); return; } @@ -959,8 +968,11 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) if (fsp->cdb_status == SAM_STAT_GOOD && fsp->xfer_len < fsp->data_len && !fsp->io_status && (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || - fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) + fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { + FC_FCP_DBG(fsp, "data underrun, xfer %zx data %x\n", + fsp->xfer_len, fsp->data_len); fsp->status_code = FC_DATA_UNDRUN; + } } seq = fsp->seq_ptr; @@ -1222,8 +1234,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp) int rc = FAILED; unsigned long ticks_left; - if (fc_fcp_send_abort(fsp)) + FC_FCP_DBG(fsp, "pkt abort state %x\n", fsp->state); + if (fc_fcp_send_abort(fsp)) { + FC_FCP_DBG(fsp, "failed to send abort\n"); return FAILED; + } init_completion(&fsp->tm_done); fsp->wait_for_comp = 1; @@ -1394,6 +1409,8 @@ static void fc_fcp_timeout(unsigned long data) if (fsp->cdb_cmd.fc_tm_flags) goto unlock; + FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n", + rpriv->flags, fsp->state); fsp->state |= FC_SRB_FCP_PROCESSING_TMO; if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) @@ -1486,8 +1503,8 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) rjt = fc_frame_payload_get(fp, sizeof(*rjt)); switch (rjt->er_reason) { default: - FC_FCP_DBG(fsp, "device %x unexpected REC reject " - "reason %d expl %d\n", + FC_FCP_DBG(fsp, + "device %x invalid REC reject %d/%d\n", fsp->rport->port_id, rjt->er_reason, rjt->er_explan); /* fall through */ @@ -1503,6 +1520,9 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) break; case ELS_RJT_LOGIC: case ELS_RJT_UNAB: + FC_FCP_DBG(fsp, "device %x REC reject %d/%d\n", + fsp->rport->port_id, rjt->er_reason, + rjt->er_explan); /* * If no data transfer, the command frame got dropped * so we just retry. If data was transferred, we @@ -1608,6 +1628,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) switch (error) { case -FC_EX_CLOSED: + FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n", + fsp, fsp->rport->port_id); fc_fcp_retry_cmd(fsp); break; @@ -1622,8 +1644,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * Assume REC or LS_ACC was lost. * The exchange manager will have aborted REC, so retry. */ - FC_FCP_DBG(fsp, "REC fid %6.6x error error %d retry %d/%d\n", - fsp->rport->port_id, error, fsp->recov_retry, + FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange timeout retry %d/%d\n", + fsp, fsp->rport->port_id, fsp->recov_retry, FC_MAX_RECOV_RETRY); if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); @@ -1642,6 +1664,7 @@ out: */ static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code) { + FC_FCP_DBG(fsp, "start recovery code %x\n", code); fsp->status_code = code; fsp->cdb_status = 0; fsp->io_status = 0; @@ -1768,12 +1791,14 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) goto out; switch (PTR_ERR(fp)) { case -FC_EX_TIMEOUT: + FC_FCP_DBG(fsp, "SRR timeout, retries %d\n", fsp->recov_retry); if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); else fc_fcp_recovery(fsp, FC_TIMED_OUT); break; case -FC_EX_CLOSED: /* e.g., link failure */ + FC_FCP_DBG(fsp, "SRR error, exchange closed\n"); /* fall through */ default: fc_fcp_retry_cmd(fsp); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4b9bb6dd4004..bcd1cd3c5285 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -287,8 +287,10 @@ static void fc_rport_work(struct work_struct *work) kref_get(&rdata->kref); mutex_unlock(&rdata->rp_mutex); - if (!rport) + if (!rport) { + FC_RPORT_DBG(rdata, "No rport!\n"); rport = fc_remote_port_add(lport->host, 0, &ids); + } if (!rport) { FC_RPORT_DBG(rdata, "Failed to add the rport\n"); lport->tt.rport_logoff(rdata); @@ -389,8 +391,10 @@ static void fc_rport_work(struct work_struct *work) * Re-open for events. Reissue READY event if ready. */ rdata->event = RPORT_EV_NONE; - if (rdata->rp_state == RPORT_ST_READY) + if (rdata->rp_state == RPORT_ST_READY) { + FC_RPORT_DBG(rdata, "work reopen\n"); fc_rport_enter_ready(rdata); + } mutex_unlock(&rdata->rp_mutex); } break; @@ -568,6 +572,7 @@ static void fc_rport_timeout(struct work_struct *work) struct fc_lport *lport = rdata->local_port; mutex_lock(&rdata->rp_mutex); + FC_RPORT_DBG(rdata, "Port timeout, state %s\n", fc_rport_state(rdata)); switch (rdata->rp_state) { case RPORT_ST_FLOGI: @@ -1095,6 +1100,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_els_spp spp; } *pp; struct fc_els_spp temp_spp; + struct fc_els_ls_rjt *rjt; struct fc4_prov *prov; u32 roles = FC_RPORT_ROLE_UNKNOWN; u32 fcp_parm = 0; @@ -1167,8 +1173,10 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, fc_rport_enter_rtv(rdata); } else { - FC_RPORT_DBG(rdata, "Bad ELS response for PRLI command\n"); - fc_rport_error_retry(rdata, fp); + rjt = fc_frame_payload_get(fp, sizeof(*rjt)); + FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n", + rjt->er_reason, rjt->er_explan); + fc_rport_error_retry(rdata, NULL); } out: @@ -1602,8 +1610,12 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) struct fc_seq_els_data els_data; rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); - if (!rdata) + if (!rdata) { + FC_RPORT_ID_DBG(lport, fc_frame_sid(fp), + "Received ELS 0x%02x from non-logged-in port\n", + fc_frame_payload_op(fp)); goto reject; + } mutex_lock(&rdata->rp_mutex); @@ -1614,6 +1626,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) case RPORT_ST_ADISC: break; default: + FC_RPORT_DBG(rdata, + "Reject ELS 0x%02x while in state %s\n", + fc_frame_payload_op(fp), fc_rport_state(rdata)); mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, lport->tt.rport_destroy); goto reject; -- cgit v1.2.3 From a0452bb45c6bcf523acff635325fee7dd961c6bd Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:38 +0200 Subject: scsi: libfc: spurious I/O error under high load If a command times out libfc is sending an REC, which also might fail (due to frames being lost or something). If no data has been transferred we can simply retry the command, but the current code sets a state of FC_ERROR, which then is being translated into DID_ERROR, resulting in an I/O error. So to handle this properly we need to set a separate state FC_TRANS_RESET and mapping it onto DID_SOFT_RETRY. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 5c6c73a80379..9f9eb7b0ba2d 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -122,6 +122,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *); #define FC_HRD_ERROR 9 #define FC_CRC_ERROR 10 #define FC_TIMED_OUT 11 +#define FC_TRANS_RESET 12 /* * Error recovery timeout values. @@ -283,7 +284,7 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) * fc_io_compl() will notify the SCSI-ml that the I/O is done. * The SCSI-ml will retry the command. */ -static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) +static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp, int status_code) { if (fsp->seq_ptr) { fsp->lp->tt.exch_done(fsp->seq_ptr); @@ -292,7 +293,7 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp) fsp->state &= ~FC_SRB_ABORT_PENDING; fsp->io_status = 0; - fsp->status_code = FC_ERROR; + fsp->status_code = status_code; fc_fcp_complete_locked(fsp); } @@ -1208,7 +1209,7 @@ static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) return; if (error == -FC_EX_CLOSED) { - fc_fcp_retry_cmd(fsp); + fc_fcp_retry_cmd(fsp, FC_ERROR); goto unlock; } @@ -1531,10 +1532,11 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) */ if (rjt->er_explan == ELS_EXPL_OXID_RXID && fsp->xfer_len == 0) { - fc_fcp_retry_cmd(fsp); + fsp->state |= FC_SRB_ABORTED; + fc_fcp_retry_cmd(fsp, FC_TRANS_RESET); break; } - fc_fcp_recovery(fsp, FC_ERROR); + fc_fcp_recovery(fsp, FC_TRANS_RESET); break; } } else if (opcode == ELS_LS_ACC) { @@ -1630,7 +1632,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) case -FC_EX_CLOSED: FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n", fsp, fsp->rport->port_id); - fc_fcp_retry_cmd(fsp); + fc_fcp_retry_cmd(fsp, FC_ERROR); break; default: @@ -1729,7 +1731,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) fc_fcp_pkt_hold(fsp); /* hold for outstanding SRR */ return; retry: - fc_fcp_retry_cmd(fsp); + fc_fcp_retry_cmd(fsp, FC_TRANS_RESET); } /** @@ -1801,7 +1803,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) FC_FCP_DBG(fsp, "SRR error, exchange closed\n"); /* fall through */ default: - fc_fcp_retry_cmd(fsp); + fc_fcp_retry_cmd(fsp, FC_ERROR); break; } fc_fcp_unlock_pkt(fsp); @@ -2014,6 +2016,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) "due to FC_CMD_RESET\n"); sc_cmd->result = (DID_RESET << 16); break; + case FC_TRANS_RESET: + FC_FCP_DBG(fsp, "Returning DID_SOFT_ERROR to scsi-ml " + "due to FC_TRANS_RESET\n"); + sc_cmd->result = (DID_SOFT_ERROR << 16); + break; case FC_HRD_ERROR: FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml " "due to FC_HRD_ERROR\n"); -- cgit v1.2.3 From f7ce413ceac01d502ea4a27c0ba542b57b728e5c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:39 +0200 Subject: scsi: libfc: use configured lport R_A_TOV We should be using the configured R_A_TOV value when sending the exchange. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 91800cb776ec..99cc5a941997 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -2140,7 +2140,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, ep->resp = resp; ep->destructor = destructor; ep->arg = arg; - ep->r_a_tov = FC_DEF_R_A_TOV; + ep->r_a_tov = lport->r_a_tov; ep->lp = lport; sp = &ep->seq; -- cgit v1.2.3 From a50cc9eccce6ae9708e8a713c4070dc2efd1b3d5 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:40 +0200 Subject: scsi: libfc: use configured rport E_D_TOV If fc_rport_error_retry() is attempting to retry the remote port state we should be waiting for the configured e_d_tov value rather than the default. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index bcd1cd3c5285..bb7e9d9a3179 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -662,7 +662,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) static void fc_rport_error_retry(struct fc_rport_priv *rdata, struct fc_frame *fp) { - unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV); + unsigned long delay = msecs_to_jiffies(rdata->e_d_tov); struct fc_lport *lport = rdata->local_port; /* make sure this isn't an FC_EX_CLOSED error, never retry those */ -- cgit v1.2.3 From 76e72ad117812bb79abf647ac40ca6df1740b729 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:41 +0200 Subject: scsi: libfc: sanitize E_D_TOV and R_A_TOV setting When setting the FCP timeout we need to ensure a lower boundary for E_D_TOV and R_A_TOV, otherwise we'd be getting spurious I/O issues due to the fcp timer firing too early. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 9 +++++---- drivers/scsi/libfc/fc_lport.c | 8 +++++--- drivers/scsi/libfc/fc_rport.c | 6 ++++-- 3 files changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 9f9eb7b0ba2d..10faca2686ba 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1137,8 +1137,11 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) { struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data; + unsigned int e_d_tov = FC_DEF_E_D_TOV; - return msecs_to_jiffies(rpriv->e_d_tov) + HZ; + if (rpriv && rpriv->e_d_tov > e_d_tov) + e_d_tov = rpriv->e_d_tov; + return msecs_to_jiffies(e_d_tov) + HZ; } /** @@ -1693,7 +1696,6 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) struct fc_seq *seq; struct fcp_srr *srr; struct fc_frame *fp; - unsigned int rec_tov; rport = fsp->rport; rpriv = rport->dd_data; @@ -1717,10 +1719,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) rpriv->local_port->port_id, FC_TYPE_FCP, FC_FCTL_REQ, 0); - rec_tov = get_fsp_rec_tov(fsp); seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, fc_fcp_pkt_destroy, - fsp, jiffies_to_msecs(rec_tov)); + fsp, get_fsp_rec_tov(fsp)); if (!seq) goto retry; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 4e11c90c783c..81ad8ac5a33d 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1777,7 +1777,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, if ((csp_flags & FC_SP_FT_FPORT) == 0) { if (e_d_tov > lport->e_d_tov) lport->e_d_tov = e_d_tov; - lport->r_a_tov = 2 * e_d_tov; + lport->r_a_tov = 2 * lport->e_d_tov; fc_lport_set_port_id(lport, did, fp); printk(KERN_INFO "host%d: libfc: " "Port (%6.6x) entered " @@ -1789,8 +1789,10 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, get_unaligned_be64( &flp->fl_wwnn)); } else { - lport->e_d_tov = e_d_tov; - lport->r_a_tov = r_a_tov; + if (e_d_tov > lport->e_d_tov) + lport->e_d_tov = e_d_tov; + if (r_a_tov > lport->r_a_tov) + lport->r_a_tov = r_a_tov; fc_host_fabric_name(lport->host) = get_unaligned_be64(&flp->fl_wwnn); fc_lport_set_port_id(lport, did, fp); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index bb7e9d9a3179..3d2baba4103e 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1296,13 +1296,15 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, tov = ntohl(rtv->rtv_r_a_tov); if (tov == 0) tov = 1; - rdata->r_a_tov = tov; + if (tov > rdata->r_a_tov) + rdata->r_a_tov = tov; tov = ntohl(rtv->rtv_e_d_tov); if (toq & FC_ELS_RTV_EDRES) tov /= 1000000; if (tov == 0) tov = 1; - rdata->e_d_tov = tov; + if (tov > rdata->e_d_tov) + rdata->e_d_tov = tov; } } -- cgit v1.2.3 From 0f4c16a2f41400dba12e5039429e780aa938aa0c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:43 +0200 Subject: scsi: libfc: do not overwrite DID_TIME_OUT status When a command is aborted it might already have the DID_TIME_OUT status set, so we shouldn't be overwriting that. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 10faca2686ba..0e2a2016af71 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2008,9 +2008,15 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status; break; case FC_CMD_ABORTED: - FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " - "due to FC_CMD_ABORTED\n"); - sc_cmd->result = (DID_ERROR << 16) | fsp->io_status; + if (host_byte(sc_cmd->result) == DID_TIME_OUT) + FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml " + "due to FC_CMD_ABORTED\n"); + else { + FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " + "due to FC_CMD_ABORTED\n"); + set_host_byte(sc_cmd, DID_ERROR); + } + sc_cmd->result |= fsp->io_status; break; case FC_CMD_RESET: FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml " -- cgit v1.2.3 From 9f9504a7cdee39e167f0421346ff17568a5f29a0 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:44 +0200 Subject: scsi: libfc: use error code for fc_rport_error() We only ever use the 'fp' argument for fc_rport_error() to encapsulate the error code, so we can as well do away with that and pass the error directly. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 101 +++++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 40 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 3d2baba4103e..d2d8607ff6a0 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -87,8 +87,8 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *, struct fc_frame *); static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *); static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *); static void fc_rport_timeout(struct work_struct *); -static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *); -static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *); +static void fc_rport_error(struct fc_rport_priv *, int); +static void fc_rport_error_retry(struct fc_rport_priv *, int); static void fc_rport_work(struct work_struct *); static const char *fc_rport_state_names[] = { @@ -604,20 +604,19 @@ static void fc_rport_timeout(struct work_struct *work) /** * fc_rport_error() - Error handler, called once retries have been exhausted * @rdata: The remote port the error is happened on - * @fp: The error code encapsulated in a frame pointer + * @err: The error code * * Locking Note: The rport lock is expected to be held before * calling this routine * * Reference counting: does not modify kref */ -static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) +static void fc_rport_error(struct fc_rport_priv *rdata, int err) { struct fc_lport *lport = rdata->local_port; - FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n", - IS_ERR(fp) ? -PTR_ERR(fp) : 0, - fc_rport_state(rdata), rdata->retries); + FC_RPORT_DBG(rdata, "Error %d in state %s, retries %d\n", + -err, fc_rport_state(rdata), rdata->retries); switch (rdata->rp_state) { case RPORT_ST_FLOGI: @@ -649,7 +648,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) /** * fc_rport_error_retry() - Handler for remote port state retries * @rdata: The remote port whose state is to be retried - * @fp: The error code encapsulated in a frame pointer + * @err: The error code * * If the error was an exchange timeout retry immediately, * otherwise wait for E_D_TOV. @@ -659,22 +658,21 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) * * Reference counting: increments kref when scheduling retry_work */ -static void fc_rport_error_retry(struct fc_rport_priv *rdata, - struct fc_frame *fp) +static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err) { unsigned long delay = msecs_to_jiffies(rdata->e_d_tov); struct fc_lport *lport = rdata->local_port; /* make sure this isn't an FC_EX_CLOSED error, never retry those */ - if (PTR_ERR(fp) == -FC_EX_CLOSED) + if (err == -FC_EX_CLOSED) goto out; if (rdata->retries < rdata->local_port->max_rport_retry_count) { - FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n", - PTR_ERR(fp), fc_rport_state(rdata)); + FC_RPORT_DBG(rdata, "Error %d in state %s, retrying\n", + err, fc_rport_state(rdata)); rdata->retries++; /* no additional delay on exchange timeouts */ - if (PTR_ERR(fp) == -FC_EX_TIMEOUT) + if (err == -FC_EX_TIMEOUT) delay = 0; kref_get(&rdata->kref); if (!schedule_delayed_work(&rdata->retry_work, delay)) @@ -683,7 +681,7 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, } out: - fc_rport_error(rdata, fp); + fc_rport_error(rdata, err); } /** @@ -743,8 +741,11 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_lport *lport = rdata->local_port; struct fc_els_flogi *flogi; unsigned int r_a_tov; + u8 opcode; + int err = 0; - FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp)); + FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", + IS_ERR(fp) ? "error" : fc_els_resp_type(fp)); if (fp == ERR_PTR(-FC_EX_CLOSED)) goto put; @@ -760,18 +761,32 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rdata, fp); + fc_rport_error(rdata, PTR_ERR(fp)); goto err; } + opcode = fc_frame_payload_op(fp); + if (opcode == ELS_LS_RJT) { + struct fc_els_ls_rjt *rjt; - if (fc_frame_payload_op(fp) != ELS_LS_ACC) + rjt = fc_frame_payload_get(fp, sizeof(*rjt)); + FC_RPORT_DBG(rdata, "FLOGI ELS rejected, reason %x expl %x\n", + rjt->er_reason, rjt->er_explan); + err = -FC_EX_ELS_RJT; + goto bad; + } else if (opcode != ELS_LS_ACC) { + FC_RPORT_DBG(rdata, "FLOGI ELS invalid opcode %x\n", opcode); + err = -FC_EX_ELS_RJT; goto bad; - if (fc_rport_login_complete(rdata, fp)) + } + if (fc_rport_login_complete(rdata, fp)) { + FC_RPORT_DBG(rdata, "FLOGI failed, no login\n"); + err = -FC_EX_INV_LOGIN; goto bad; + } flogi = fc_frame_payload_get(fp, sizeof(*flogi)); if (!flogi) { - FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); + err = -FC_EX_ALLOC_ERR; goto bad; } r_a_tov = ntohl(flogi->fl_csp.sp_r_a_tov); @@ -790,7 +805,8 @@ put: kref_put(&rdata->kref, lport->tt.rport_destroy); return; bad: - fc_rport_error_retry(rdata, fp); + FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); + fc_rport_error_retry(rdata, err); goto out; } @@ -818,13 +834,13 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) - return fc_rport_error_retry(rdata, fp); + return fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_FLOGI, fc_rport_flogi_resp, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } @@ -991,7 +1007,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, PTR_ERR(fp)); goto err; } @@ -1013,9 +1029,14 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, rdata->max_seq = csp_seq; rdata->maxframe_size = fc_plogi_get_maxframe(plp, lport->mfs); fc_rport_enter_prli(rdata); - } else - fc_rport_error_retry(rdata, fp); + } else { + struct fc_els_ls_rjt *rjt; + rjt = fc_frame_payload_get(fp, sizeof(*rjt)); + FC_RPORT_DBG(rdata, "PLOGI ELS rejected, reason %x expl %x\n", + rjt->er_reason, rjt->er_explan); + fc_rport_error_retry(rdata, -FC_EX_ELS_RJT); + } out: fc_frame_free(fp); err: @@ -1067,7 +1088,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) { FC_RPORT_DBG(rdata, "%s frame alloc failed\n", __func__); - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); return; } rdata->e_d_tov = lport->e_d_tov; @@ -1076,7 +1097,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI, fc_rport_plogi_resp, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } @@ -1123,7 +1144,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, PTR_ERR(fp)); goto err; } @@ -1142,9 +1163,9 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, rdata->spp_type = pp->spp.spp_type; if (resp_code != FC_SPP_RESP_ACK) { if (resp_code == FC_SPP_RESP_CONF) - fc_rport_error(rdata, fp); + fc_rport_error(rdata, -FC_EX_SEQ_ERR); else - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_SEQ_ERR); goto out; } if (pp->prli.prli_spp_len < sizeof(pp->spp)) @@ -1176,7 +1197,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, rjt = fc_frame_payload_get(fp, sizeof(*rjt)); FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n", rjt->er_reason, rjt->er_explan); - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, FC_EX_ELS_RJT); } out: @@ -1222,7 +1243,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(*pp)); if (!fp) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); return; } @@ -1241,7 +1262,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) kref_get(&rdata->kref); if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp, NULL, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } @@ -1280,7 +1301,7 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rdata, fp); + fc_rport_error(rdata, PTR_ERR(fp)); goto err; } @@ -1339,7 +1360,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv)); if (!fp) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); return; } @@ -1347,7 +1368,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV, fc_rport_rtv_resp, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } @@ -1430,7 +1451,7 @@ static void fc_rport_adisc_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rdata, fp); + fc_rport_error(rdata, PTR_ERR(fp)); goto err; } @@ -1480,14 +1501,14 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) fp = fc_frame_alloc(lport, sizeof(struct fc_els_adisc)); if (!fp) { - fc_rport_error_retry(rdata, fp); + fc_rport_error_retry(rdata, -FC_EX_ALLOC_ERR); return; } kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC, fc_rport_adisc_resp, rdata, 2 * lport->r_a_tov)) { - fc_rport_error_retry(rdata, NULL); + fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } } -- cgit v1.2.3 From 7c5a51b8f82fcfba1925fa64f08413c8258590d2 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:45 +0200 Subject: scsi: libfc: Implement RTV responder The libfc stack generates an RTV request, so we should be implementing an RTV responder, too. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index d2d8607ff6a0..426c39989952 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1268,7 +1268,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) } /** - * fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses + * fc_rport_rtv_resp() - Handler for Request Timeout Value (RTV) responses * @sp: The sequence the RTV was on * @fp: The RTV response frame * @rdata_arg: The remote port that sent the RTV response @@ -1373,6 +1373,41 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) } } +/** + * fc_rport_recv_rtv_req() - Handler for Read Timeout Value (RTV) requests + * @rdata: The remote port that sent the RTV request + * @in_fp: The RTV request frame + * + * Locking Note: Called with the lport and rport locks held. + */ +static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata, + struct fc_frame *in_fp) +{ + struct fc_lport *lport = rdata->local_port; + struct fc_frame *fp; + struct fc_els_rtv_acc *rtv; + struct fc_seq_els_data rjt_data; + + FC_RPORT_DBG(rdata, "Received RTV request\n"); + + fp = fc_frame_alloc(lport, sizeof(*rtv)); + if (!fp) { + rjt_data.reason = ELS_RJT_UNAB; + rjt_data.reason = ELS_EXPL_INSUF_RES; + lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); + goto drop; + } + rtv = fc_frame_payload_get(fp, sizeof(*rtv)); + rtv->rtv_cmd = ELS_LS_ACC; + rtv->rtv_r_a_tov = htonl(lport->r_a_tov); + rtv->rtv_e_d_tov = htonl(lport->e_d_tov); + rtv->rtv_toq = 0; + fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); + lport->tt.frame_send(lport, fp); +drop: + fc_frame_free(in_fp); +} + /** * fc_rport_logo_resp() - Handler for logout (LOGO) responses * @sp: The sequence the LOGO was on @@ -1678,6 +1713,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) case ELS_RLS: fc_rport_recv_rls_req(rdata, fp); break; + case ELS_RTV: + fc_rport_recv_rtv_req(rdata, fp); + break; default: fc_frame_free(fp); /* can't happen */ break; @@ -1729,6 +1767,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) case ELS_RRQ: case ELS_REC: case ELS_RLS: + case ELS_RTV: fc_rport_recv_els_req(lport, fp); break; default: -- cgit v1.2.3 From 386b97b43c0c9e0d878eec7ea1db16af22b036ae Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:46 +0200 Subject: scsi: libfc: Rework PRLI handling PRLI is only required if the port is acting as an initiator; ports which support target functionality only do not need to send PRLI. At the same time the PRLI state is only used if the port initiated a PRLI transfer; if we received a PRLI request we should _not_ change the state as this would cause our PRLI response to be dropped. And when we receive a PRLI response we need to check if an image pair has been established; if not the remote port cannot act as a target for us and we need to disable target functionality. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 56 +++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 18 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 426c39989952..2b8214f335db 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1126,7 +1126,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, u32 roles = FC_RPORT_ROLE_UNKNOWN; u32 fcp_parm = 0; u8 op; - u8 resp_code = 0; + enum fc_els_spp_resp resp_code; FC_RPORT_DBG(rdata, "Received a PRLI %s\n", fc_els_resp_type(fp)); @@ -1158,8 +1158,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, goto out; resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK); - FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n", - pp->spp.spp_flags); + FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x spp_type 0x%x\n", + pp->spp.spp_flags, pp->spp.spp_type); rdata->spp_type = pp->spp.spp_type; if (resp_code != FC_SPP_RESP_ACK) { if (resp_code == FC_SPP_RESP_CONF) @@ -1177,13 +1177,26 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, if (fcp_parm & FCP_SPPF_CONF_COMPL) rdata->flags |= FC_RP_FLAGS_CONF_REQ; - prov = fc_passive_prov[FC_TYPE_FCP]; + /* + * Call prli provider if we should act as a target + */ + prov = fc_passive_prov[rdata->spp_type]; if (prov) { memset(&temp_spp, 0, sizeof(temp_spp)); prov->prli(rdata, pp->prli.prli_spp_len, &pp->spp, &temp_spp); } - + /* + * Check if the image pair could be established + */ + if (rdata->spp_type != FC_TYPE_FCP || + resp_code != FC_SPP_RESP_ACK || + !(pp->spp.spp_flags & FC_SPP_EST_IMG_PAIR)) { + /* + * Nope; we can't use this port as a target. + */ + fcp_parm &= ~FCP_SPPF_TARG_FCN; + } rdata->supported_classes = FC_COS_CLASS3; if (fcp_parm & FCP_SPPF_INIT_FCN) roles |= FC_RPORT_ROLE_FCP_INITIATOR; @@ -1236,6 +1249,15 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) return; } + /* + * And if the local port does not support the initiator function + * there's no need to send a PRLI, either. + */ + if (!(lport->service_params & FCP_SPPF_INIT_FCN)) { + fc_rport_enter_ready(rdata); + return; + } + FC_RPORT_DBG(rdata, "Port entered PRLI state from %s state\n", fc_rport_state(rdata)); @@ -1926,7 +1948,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, unsigned int len; unsigned int plen; enum fc_els_spp_resp resp; - enum fc_els_spp_resp passive; struct fc_seq_els_data rjt_data; struct fc4_prov *prov; @@ -1976,15 +1997,21 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, resp = 0; if (rspp->spp_type < FC_FC4_PROV_SIZE) { + enum fc_els_spp_resp active = 0, passive = 0; + prov = fc_active_prov[rspp->spp_type]; if (prov) - resp = prov->prli(rdata, plen, rspp, spp); + active = prov->prli(rdata, plen, rspp, spp); prov = fc_passive_prov[rspp->spp_type]; - if (prov) { + if (prov) passive = prov->prli(rdata, plen, rspp, spp); - if (!resp || passive == FC_SPP_RESP_ACK) - resp = passive; - } + if (!active || passive == FC_SPP_RESP_ACK) + resp = passive; + else + resp = active; + FC_RPORT_DBG(rdata, "PRLI rspp type %x " + "active %x passive %x\n", + rspp->spp_type, active, passive); } if (!resp) { if (spp->spp_flags & FC_SPP_EST_IMG_PAIR) @@ -2005,13 +2032,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); lport->tt.frame_send(lport, fp); - switch (rdata->rp_state) { - case RPORT_ST_PRLI: - fc_rport_enter_ready(rdata); - break; - default: - break; - } goto drop; reject_len: -- cgit v1.2.3 From 8acf1b50cfa44c8260fb1fcf7464a4eee69aefcf Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:47 +0200 Subject: scsi: libfc: Return LS_RJT_BUSY for PRLI in status PLOGI Occasionally it might happen that we receive a PRLI while we're still waiting for our PLOGI response. In that case we should return 'busy' LS status instead of 'plogi required' LS status. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 2b8214f335db..a867874ff367 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1705,6 +1705,15 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) case RPORT_ST_READY: case RPORT_ST_ADISC: break; + case RPORT_ST_PLOGI: + if (fc_frame_payload_op(fp) == ELS_PRLI) { + FC_RPORT_DBG(rdata, "Reject ELS PRLI " + "while in state %s\n", + fc_rport_state(rdata)); + mutex_unlock(&rdata->rp_mutex); + kref_put(&rdata->kref, lport->tt.rport_destroy); + goto busy; + } default: FC_RPORT_DBG(rdata, "Reject ELS 0x%02x while in state %s\n", @@ -1752,6 +1761,14 @@ reject: els_data.explan = ELS_EXPL_PLOGI_REQD; lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); + return; + +busy: + els_data.reason = ELS_RJT_BUSY; + els_data.explan = ELS_EXPL_NONE; + lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_frame_free(fp); + return; } /** -- cgit v1.2.3 From 5d339d163a541ceb13074789ac2f8c35b11ebda9 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:48 +0200 Subject: scsi: libfc: Clarify ramp-down messages When the queue depth is reduced we should print out the reason for this; it might be due to a queue full condition. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 0e2a2016af71..f7700cccf793 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -403,8 +403,6 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport) if (!can_queue) can_queue = 1; lport->host->can_queue = can_queue; - shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n" - "Reducing can_queue to %d.\n", can_queue); unlock: spin_unlock_irqrestore(lport->host->host_lock, flags); @@ -431,6 +429,9 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport, put_cpu(); /* error case */ fc_fcp_can_queue_ramp_down(lport); + shost_printk(KERN_ERR, lport->host, + "libfc: Could not allocate frame, " + "reducing can_queue to %d.\n", lport->host->can_queue); return NULL; } @@ -1860,8 +1861,13 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd) rpriv = rport->dd_data; if (!fc_fcp_lport_queue_ready(lport)) { - if (lport->qfull) + if (lport->qfull) { fc_fcp_can_queue_ramp_down(lport); + shost_printk(KERN_ERR, lport->host, + "libfc: queue full, " + "reducing can_queue to %d.\n", + lport->host->can_queue); + } rc = SCSI_MLQUEUE_HOST_BUSY; goto out; } -- cgit v1.2.3 From b73aa56ee91cd88a4977033cfd2a18d6b25dddde Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:49 +0200 Subject: scsi: libfc: safeguard against invalid exchange index The cached exchange index might be invalid, in which case we should drop down to allocate a new one. And we should not try to access an invalid exchange when responding to a BA_ABTS. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 99cc5a941997..7b47ab1389ca 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -827,14 +827,18 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, /* peek cache of free slot */ if (pool->left != FC_XID_UNKNOWN) { - index = pool->left; - pool->left = FC_XID_UNKNOWN; - goto hit; + if (!WARN_ON(fc_exch_ptr_get(pool, pool->left))) { + index = pool->left; + pool->left = FC_XID_UNKNOWN; + goto hit; + } } if (pool->right != FC_XID_UNKNOWN) { - index = pool->right; - pool->right = FC_XID_UNKNOWN; - goto hit; + if (!WARN_ON(fc_exch_ptr_get(pool, pool->right))) { + index = pool->right; + pool->right = FC_XID_UNKNOWN; + goto hit; + } } index = pool->next_index; @@ -1782,7 +1786,10 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp) fc_frame_free(fp); break; case FC_RCTL_BA_ABTS: - fc_exch_recv_abts(ep, fp); + if (ep) + fc_exch_recv_abts(ep, fp); + else + fc_frame_free(fp); break; default: /* ignore junk */ fc_frame_free(fp); -- cgit v1.2.3 From 9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:50 +0200 Subject: scsi: libfc: quarantine timed out xids When a sequence times out we have no idea what happened to the frame. And we do not know if we will ever receive the frame. Hence we cannot re-use the xid as we would risk data corruption if the xid had been re-used and the timed out frame would be received after that. So we need to quarantine the xid until the lport is reset. Yes, I know this will (eventually) deplete the xid pool. But for now it's the safest method. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 33 ++++++++++++++++++++++----------- drivers/scsi/libfc/fc_fcp.c | 13 +++++++------ 2 files changed, 29 insertions(+), 17 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 7b47ab1389ca..ca7d947dc427 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -94,6 +94,7 @@ struct fc_exch_pool { struct fc_exch_mgr { struct fc_exch_pool __percpu *pool; mempool_t *ep_pool; + struct fc_lport *lport; enum fc_class class; struct kref kref; u16 min_xid; @@ -408,6 +409,8 @@ static int fc_exch_done_locked(struct fc_exch *ep) return rc; } +static struct fc_exch fc_quarantine_exch; + /** * fc_exch_ptr_get() - Return an exchange from an exchange pool * @pool: Exchange Pool to get an exchange from @@ -452,14 +455,17 @@ static void fc_exch_delete(struct fc_exch *ep) /* update cache of free slot */ index = (ep->xid - ep->em->min_xid) >> fc_cpu_order; - if (pool->left == FC_XID_UNKNOWN) - pool->left = index; - else if (pool->right == FC_XID_UNKNOWN) - pool->right = index; - else - pool->next_index = index; - - fc_exch_ptr_set(pool, index, NULL); + if (!(ep->state & FC_EX_QUARANTINE)) { + if (pool->left == FC_XID_UNKNOWN) + pool->left = index; + else if (pool->right == FC_XID_UNKNOWN) + pool->right = index; + else + pool->next_index = index; + fc_exch_ptr_set(pool, index, NULL); + } else { + fc_exch_ptr_set(pool, index, &fc_quarantine_exch); + } list_del(&ep->ex_list); spin_unlock_bh(&pool->lock); fc_exch_release(ep); /* drop hold for exch in mp */ @@ -921,14 +927,14 @@ static struct fc_exch *fc_exch_alloc(struct fc_lport *lport, */ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) { + struct fc_lport *lport = mp->lport; struct fc_exch_pool *pool; struct fc_exch *ep = NULL; u16 cpu = xid & fc_cpu_mask; if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) { - printk_ratelimited(KERN_ERR - "libfc: lookup request for XID = %d, " - "indicates invalid CPU %d\n", xid, cpu); + pr_err("host%u: lport %6.6x: xid %d invalid CPU %d\n:", + lport->host->host_no, lport->port_id, xid, cpu); return NULL; } @@ -936,6 +942,10 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) pool = per_cpu_ptr(mp->pool, cpu); spin_lock_bh(&pool->lock); ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order); + if (ep == &fc_quarantine_exch) { + FC_LPORT_DBG(lport, "xid %x quarantined\n", xid); + ep = NULL; + } if (ep) { WARN_ON(ep->xid != xid); fc_exch_hold(ep); @@ -2434,6 +2444,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport, return NULL; mp->class = class; + mp->lport = lport; /* adjust em exch xid range for offload */ mp->min_xid = min_xid; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index f7700cccf793..780d9f09a267 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1529,13 +1529,14 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fsp->rport->port_id, rjt->er_reason, rjt->er_explan); /* - * If no data transfer, the command frame got dropped - * so we just retry. If data was transferred, we - * lost the response but the target has no record, - * so we abort and retry. + * If response got lost or is stuck in the + * queue somewhere we have no idea if and when + * the response will be received. So quarantine + * the xid and retry the command. */ - if (rjt->er_explan == ELS_EXPL_OXID_RXID && - fsp->xfer_len == 0) { + if (rjt->er_explan == ELS_EXPL_OXID_RXID) { + struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr); + ep->state |= FC_EX_QUARANTINE; fsp->state |= FC_SRB_ABORTED; fc_fcp_retry_cmd(fsp, FC_TRANS_RESET); break; -- cgit v1.2.3 From d11b44eff113e2a848577ce58af6488f161b6f7d Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:51 +0200 Subject: scsi: libfc: don't fail sequence abort for completed exchanges If a sequence should be aborted the exchange might already be completed (eg if the response is still queued in the rx queue), so this shouldn't considered as an error. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 780d9f09a267..d43c925bace3 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -258,6 +258,17 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay) mod_timer(&fsp->timer, jiffies + delay); } +static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp) +{ + fsp->state |= FC_SRB_ABORTED; + fsp->state &= ~FC_SRB_ABORT_PENDING; + + if (fsp->wait_for_comp) + complete(&fsp->tm_done); + else + fc_fcp_complete_locked(fsp); +} + /** * fc_fcp_send_abort() - Send an abort for exchanges associated with a * fcp_pkt @@ -265,6 +276,8 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay) */ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) { + int rc; + if (!fsp->seq_ptr) return -EINVAL; @@ -272,7 +285,16 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) put_cpu(); fsp->state |= FC_SRB_ABORT_PENDING; - return fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0); + rc = fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0); + /* + * ->seq_exch_abort() might return -ENXIO if + * the sequence is already completed + */ + if (rc == -ENXIO) { + fc_fcp_abort_done(fsp); + rc = 0; + } + return rc; } /** @@ -729,15 +751,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) ba_done = 0; } - if (ba_done) { - fsp->state |= FC_SRB_ABORTED; - fsp->state &= ~FC_SRB_ABORT_PENDING; - - if (fsp->wait_for_comp) - complete(&fsp->tm_done); - else - fc_fcp_complete_locked(fsp); - } + if (ba_done) + fc_fcp_abort_done(fsp); } /** @@ -1245,6 +1260,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp) return FAILED; } + if (fsp->state & FC_SRB_ABORTED) { + FC_FCP_DBG(fsp, "target abort cmd completed\n"); + return SUCCESS; + } + init_completion(&fsp->tm_done); fsp->wait_for_comp = 1; -- cgit v1.2.3 From 53db8fa8a3b37d076f89bac67095e1381a2fb19a Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:52 +0200 Subject: scsi: libfc: Do not drop out-of-order frames When receiving packets from the network we cannot guarantee any frame ordering, so we should be receiving all valid frames and let the upper layers deal with it. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index ca7d947dc427..44feffa2ee25 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1597,9 +1597,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) if (fc_sof_is_init(sof)) { sp->ssb_stat |= SSB_ST_RESP; sp->id = fh->fh_seq_id; - } else if (sp->id != fh->fh_seq_id) { - atomic_inc(&mp->stats.seq_not_found); - goto rel; } f_ctl = ntoh24(fh->fh_f_ctl); -- cgit v1.2.3 From ad3120cfe0c5dcd5aaa87a0f7c42d4b09a94fa12 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:53 +0200 Subject: scsi: libfc: reset timeout on queue full When we're receiving a timeout we should be checking for queue full status; if there are still some packets pending we should be resetting the counter to ensure we're not missing out any packets which are still queued. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index d43c925bace3..fb2ebc76e0eb 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -254,8 +254,10 @@ static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt *fsp) */ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay) { - if (!(fsp->state & FC_SRB_COMPL)) + if (!(fsp->state & FC_SRB_COMPL)) { mod_timer(&fsp->timer, jiffies + delay); + fsp->timer_delay = delay; + } } static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp) @@ -932,6 +934,11 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * Wait a at least one jiffy to see if it is delivered. * If this expires without data, we may do SRR. */ + if (fsp->lp->qfull) { + FC_FCP_DBG(fsp, "tgt %6.6x queue busy retry\n", + fsp->rport->port_id); + return; + } FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun " "len %x, data len %x\n", fsp->rport->port_id, @@ -1434,8 +1441,15 @@ static void fc_fcp_timeout(unsigned long data) if (fsp->cdb_cmd.fc_tm_flags) goto unlock; - FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n", - rpriv->flags, fsp->state); + if (fsp->lp->qfull) { + FC_FCP_DBG(fsp, "fcp timeout, resetting timer delay %d\n", + fsp->timer_delay); + setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp); + fc_fcp_timer_set(fsp, fsp->timer_delay); + goto unlock; + } + FC_FCP_DBG(fsp, "fcp timeout, delay %d flags %x state %x\n", + fsp->timer_delay, rpriv->flags, fsp->state); fsp->state |= FC_SRB_FCP_PROCESSING_TMO; if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) -- cgit v1.2.3 From 87da3b832e54bcee7fac220bec00ca42b931bab0 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:54 +0200 Subject: scsi: libfc: wait for E_D_TOV when out-of-order sequence is received When detecting an out-of-order sequence we should be waiting for E_D_TOV before trying to abort the sequence. The response might still be stuck in the queue somewhere. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index fb2ebc76e0eb..c033946875a7 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -459,6 +459,22 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport, return NULL; } +/** + * get_fsp_rec_tov() - Helper function to get REC_TOV + * @fsp: the FCP packet + * + * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second + */ +static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) +{ + struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data; + unsigned int e_d_tov = FC_DEF_E_D_TOV; + + if (rpriv && rpriv->e_d_tov > e_d_tov) + e_d_tov = rpriv->e_d_tov; + return msecs_to_jiffies(e_d_tov) + HZ; +} + /** * fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target * @fsp: The FCP packet the data is on @@ -562,8 +578,10 @@ crc_err: * and completes the transfer, call the completion handler. */ if (unlikely(fsp->state & FC_SRB_RCV_STATUS) && - fsp->xfer_len == fsp->data_len - fsp->scsi_resid) + fsp->xfer_len == fsp->data_len - fsp->scsi_resid) { + FC_FCP_DBG( fsp, "complete out-of-order sequence\n" ); fc_fcp_complete_locked(fsp); + } return; err: fc_fcp_recovery(fsp, host_bcode); @@ -943,7 +961,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) "len %x, data len %x\n", fsp->rport->port_id, fsp->xfer_len, expected_len, fsp->data_len); - fc_fcp_timer_set(fsp, 2); + fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp)); return; } fsp->status_code = FC_DATA_OVRRUN; @@ -1151,22 +1169,6 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) return rc; } -/** - * get_fsp_rec_tov() - Helper function to get REC_TOV - * @fsp: the FCP packet - * - * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second - */ -static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) -{ - struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data; - unsigned int e_d_tov = FC_DEF_E_D_TOV; - - if (rpriv && rpriv->e_d_tov > e_d_tov) - e_d_tov = rpriv->e_d_tov; - return msecs_to_jiffies(e_d_tov) + HZ; -} - /** * fc_fcp_cmd_send() - Send a FCP command * @lport: The local port to send the command on -- cgit v1.2.3 From e0a25286d8acd97ac0b9db5b8b776755fc8b62fa Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 13 Oct 2016 15:10:55 +0200 Subject: scsi: libfc: Check xid when looking up REC exchanges We currently can only lookup the local xid, so we need to reject REC with empty rxid. Signed-off-by: Hannes Reinecke Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 44feffa2ee25..9921dbbaeaff 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -2005,8 +2005,7 @@ static void fc_exch_els_rec(struct fc_frame *rfp) enum fc_els_rjt_reason reason = ELS_RJT_LOGIC; enum fc_els_rjt_explan explan; u32 sid; - u16 rxid; - u16 oxid; + u16 xid, rxid, oxid; lport = fr_dev(rfp); rp = fc_frame_payload_get(rfp, sizeof(*rp)); @@ -2017,9 +2016,18 @@ static void fc_exch_els_rec(struct fc_frame *rfp) rxid = ntohs(rp->rec_rx_id); oxid = ntohs(rp->rec_ox_id); - ep = fc_exch_lookup(lport, - sid == fc_host_port_id(lport->host) ? oxid : rxid); explan = ELS_EXPL_OXID_RXID; + if (sid == fc_host_port_id(lport->host)) + xid = oxid; + else + xid = rxid; + if (xid == FC_XID_UNKNOWN) { + FC_LPORT_DBG(lport, + "REC request from %x: invalid rxid %x oxid %x\n", + sid, rxid, oxid); + goto reject; + } + ep = fc_exch_lookup(lport, xid); if (!ep) { FC_LPORT_DBG(lport, "REC request from %x: rxid %x oxid %x not found\n", -- cgit v1.2.3 From 7ab24dd16579514d261a669aa3b9e19220df5456 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:35 +0200 Subject: scsi: libfc: Replace ->seq_els_rsp_send callback with function call The 'seq_els_rsp_send' callback only ever had one implementation, so we might as well drop it and use the function directly. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_disc.c | 4 ++-- drivers/scsi/libfc/fc_exch.c | 8 +++----- drivers/scsi/libfc/fc_lport.c | 6 +++--- drivers/scsi/libfc/fc_rport.c | 26 +++++++++++++------------- 4 files changed, 21 insertions(+), 23 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index ad3965f9d03d..4e3115211631 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -154,7 +154,7 @@ static void fc_disc_recv_rscn_req(struct fc_disc *disc, struct fc_frame *fp) break; } } - lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); + fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL); /* * If not doing a complete rediscovery, do GPN_ID on @@ -182,7 +182,7 @@ reject: FC_DISC_DBG(disc, "Received a bad RSCN frame\n"); rjt_data.reason = ELS_RJT_LOGIC; rjt_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); fc_frame_free(fp); } diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 9921dbbaeaff..3f58aeb8937e 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1222,8 +1222,8 @@ static void fc_exch_set_addr(struct fc_exch *ep, * * The received frame is not freed. */ -static void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd, - struct fc_seq_els_data *els_data) +void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd, + struct fc_seq_els_data *els_data) { switch (els_cmd) { case ELS_LS_RJT: @@ -1242,6 +1242,7 @@ static void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd, FC_LPORT_DBG(fr_dev(fp), "Invalid ELS CMD:%x\n", els_cmd); } } +EXPORT_SYMBOL_GPL(fc_seq_els_rsp_send); /** * fc_seq_send_last() - Send a sequence that is the last in the exchange @@ -2635,9 +2636,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_send) lport->tt.seq_send = fc_seq_send; - if (!lport->tt.seq_els_rsp_send) - lport->tt.seq_els_rsp_send = fc_seq_els_rsp_send; - if (!lport->tt.exch_done) lport->tt.exch_done = fc_exch_done; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 81ad8ac5a33d..bf79c9bd2a14 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -412,7 +412,7 @@ static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp) FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", fc_lport_state(lport)); - lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); + fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL); fc_frame_free(fp); } @@ -481,7 +481,7 @@ static void fc_lport_recv_rnid_req(struct fc_lport *lport, if (!req) { rjt_data.reason = ELS_RJT_LOGIC; rjt_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); } else { fmt = req->rnid_fmt; len = sizeof(*rp); @@ -521,7 +521,7 @@ static void fc_lport_recv_rnid_req(struct fc_lport *lport, */ static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) { - lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); + fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL); fc_lport_enter_reset(lport); fc_frame_free(fp); } diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index a867874ff367..4ca0f40dc0d6 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -967,7 +967,7 @@ out: reject_put: kref_put(&rdata->kref, lport->tt.rport_destroy); reject: - lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); fc_frame_free(rx_fp); } @@ -1416,7 +1416,7 @@ static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata, if (!fp) { rjt_data.reason = ELS_RJT_UNAB; rjt_data.reason = ELS_EXPL_INSUF_RES; - lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); goto drop; } rtv = fc_frame_payload_get(fp, sizeof(*rtv)); @@ -1591,7 +1591,7 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, if (!adisc) { rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; - lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); goto drop; } @@ -1667,7 +1667,7 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, goto out; out_rjt: - lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); out: fc_frame_free(rx_fp); } @@ -1734,11 +1734,11 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) fc_rport_recv_adisc_req(rdata, fp); break; case ELS_RRQ: - lport->tt.seq_els_rsp_send(fp, ELS_RRQ, NULL); + fc_seq_els_rsp_send(fp, ELS_RRQ, NULL); fc_frame_free(fp); break; case ELS_REC: - lport->tt.seq_els_rsp_send(fp, ELS_REC, NULL); + fc_seq_els_rsp_send(fp, ELS_REC, NULL); fc_frame_free(fp); break; case ELS_RLS: @@ -1759,14 +1759,14 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) reject: els_data.reason = ELS_RJT_UNAB; els_data.explan = ELS_EXPL_PLOGI_REQD; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); return; busy: els_data.reason = ELS_RJT_BUSY; els_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); return; } @@ -1812,7 +1812,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) default: els_data.reason = ELS_RJT_UNSUP; els_data.explan = ELS_EXPL_NONE; - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); fc_frame_free(fp); break; } @@ -1939,7 +1939,7 @@ out: return; reject: - lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); fc_frame_free(fp); } @@ -2055,7 +2055,7 @@ reject_len: rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; reject: - lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); drop: fc_frame_free(rx_fp); } @@ -2126,7 +2126,7 @@ reject_len: rjt_data.reason = ELS_RJT_PROT; rjt_data.explan = ELS_EXPL_INV_LEN; reject: - lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); + fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); drop: fc_frame_free(rx_fp); } @@ -2146,7 +2146,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) struct fc_rport_priv *rdata; u32 sid; - lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); + fc_seq_els_rsp_send(fp, ELS_LS_ACC, NULL); sid = fc_frame_sid(fp); -- cgit v1.2.3 From 31c0a631a430b01e05ff1e35f287fb8dfa0ef519 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:36 +0200 Subject: scsi: libfc: Replace ->lport_reset callback with function call The ->lport_reset callback only ever had one implementation, which already is exported. So remove it and use the function directly. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_fcp.c | 2 +- drivers/scsi/libfc/fc_lport.c | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index c033946875a7..831de3eada9c 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2224,7 +2224,7 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) fc_block_scsi_eh(sc_cmd); - lport->tt.lport_reset(lport); + fc_lport_reset(lport); wait_tmo = jiffies + FC_HOST_RESET_TIMEOUT; while (!fc_fcp_lport_queue_ready(lport) && time_before(jiffies, wait_tmo)) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index bf79c9bd2a14..05f83a65cc1e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1868,9 +1868,6 @@ int fc_lport_init(struct fc_lport *lport) if (!lport->tt.lport_recv) lport->tt.lport_recv = fc_lport_recv_req; - if (!lport->tt.lport_reset) - lport->tt.lport_reset = fc_lport_reset; - fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; fc_host_node_name(lport->host) = lport->wwnn; fc_host_port_name(lport->host) = lport->wwpn; -- cgit v1.2.3 From c5cb444c31d1577d2dd207101ba9cf498e1c2d48 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:37 +0200 Subject: scsi: libfc: Replace ->lport_recv with function call The ->lport_recv callback only ever had one implementation, so call the function directly and remove the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 4 ++-- drivers/scsi/libfc/fc_lport.c | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 3f58aeb8937e..cc320a91b7b7 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1527,7 +1527,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, * The upper-level protocol may request one later, if needed. */ if (fh->fh_rx_id == htons(FC_XID_UNKNOWN)) - return lport->tt.lport_recv(lport, fp); + return fc_lport_recv(lport, fp); reject = fc_seq_lookup_recip(lport, mp, fp); if (reject == FC_RJT_NONE) { @@ -1548,7 +1548,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, * first. */ if (!fc_invoke_resp(ep, sp, fp)) - lport->tt.lport_recv(lport, fp); + fc_lport_recv(lport, fp); fc_exch_release(ep); /* release from lookup */ } else { FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n", diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 05f83a65cc1e..42dcb722172b 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -944,15 +944,14 @@ struct fc4_prov fc_lport_els_prov = { }; /** - * fc_lport_recv_req() - The generic lport request handler + * fc_lport_recv() - The generic lport request handler * @lport: The lport that received the request * @fp: The frame the request is in * * Locking Note: This function should not be called with the lport * lock held because it may grab the lock. */ -static void fc_lport_recv_req(struct fc_lport *lport, - struct fc_frame *fp) +void fc_lport_recv(struct fc_lport *lport, struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_seq *sp = fr_seq(fp); @@ -983,6 +982,7 @@ drop: if (sp) lport->tt.exch_done(sp); } +EXPORT_SYMBOL(fc_lport_recv); /** * fc_lport_reset() - Reset a local port @@ -1865,9 +1865,6 @@ EXPORT_SYMBOL(fc_lport_config); */ int fc_lport_init(struct fc_lport *lport) { - if (!lport->tt.lport_recv) - lport->tt.lport_recv = fc_lport_recv_req; - fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; fc_host_node_name(lport->host) = lport->wwnn; fc_host_port_name(lport->host) = lport->wwpn; -- cgit v1.2.3 From 3afd2d1521951cb05ef5279b71634cc55ace688b Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:38 +0200 Subject: scsi: libfc: Replace ->exch_seq_send callback with function call The ->exch_seq_send callback only ever had one implementation, so we can call the function directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_elsct.c | 2 +- drivers/scsi/libfc/fc_exch.c | 37 ++++++++++++++++++++++++++----------- drivers/scsi/libfc/fc_fcp.c | 11 +++++------ drivers/scsi/libfc/fc_lport.c | 8 ++++---- drivers/scsi/libfc/fc_rport.c | 4 ++-- 5 files changed, 38 insertions(+), 24 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index c2384d501470..6384a98048af 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -67,7 +67,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type, FC_FCTL_REQ, 0); - return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); + return fc_exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); } EXPORT_SYMBOL(fc_elsct_send); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index cc320a91b7b7..f5c3c1d09651 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -2127,6 +2127,24 @@ cleanup: * @arg: The argument to be passed to the response handler * @timer_msec: The timeout period for the exchange * + * The exchange response handler is set in this routine to resp() + * function pointer. It can be called in two scenarios: if a timeout + * occurs or if a response frame is received for the exchange. The + * fc_frame pointer in response handler will also indicate timeout + * as error using IS_ERR related macros. + * + * The exchange destructor handler is also set in this routine. + * The destructor handler is invoked by EM layer when exchange + * is about to free, this can be used by caller to free its + * resources along with exchange free. + * + * The arg is passed back to resp and destructor handler. + * + * The timeout value (in msec) for an exchange is set if non zero + * timer_msec argument is specified. The timer is canceled when + * it fires or when the exchange is done. The exchange timeout handler + * is registered by EM layer. + * * The frame pointer with some of the header's fields must be * filled before calling this routine, those fields are: * @@ -2137,14 +2155,13 @@ cleanup: * - frame control * - parameter or relative offset */ -static struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, - struct fc_frame *fp, - void (*resp)(struct fc_seq *, - struct fc_frame *fp, - void *arg), - void (*destructor)(struct fc_seq *, - void *), - void *arg, u32 timer_msec) +struct fc_seq *fc_exch_seq_send(struct fc_lport *lport, + struct fc_frame *fp, + void (*resp)(struct fc_seq *, + struct fc_frame *fp, + void *arg), + void (*destructor)(struct fc_seq *, void *), + void *arg, u32 timer_msec) { struct fc_exch *ep; struct fc_seq *sp = NULL; @@ -2197,6 +2214,7 @@ err: fc_exch_delete(ep); return NULL; } +EXPORT_SYMBOL(fc_exch_seq_send); /** * fc_exch_rrq() - Send an ELS RRQ (Reinstate Recovery Qualifier) command @@ -2630,9 +2648,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_set_resp) lport->tt.seq_set_resp = fc_seq_set_resp; - if (!lport->tt.exch_seq_send) - lport->tt.exch_seq_send = fc_exch_seq_send; - if (!lport->tt.seq_send) lport->tt.seq_send = fc_seq_send; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 831de3eada9c..5cf1d2e3b575 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -196,7 +196,7 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp) * @seq: The sequence that the FCP packet is on (required by destructor API) * @fsp: The FCP packet to be released * - * This routine is called by a destructor callback in the exch_seq_send() + * This routine is called by a destructor callback in the fc_exch_seq_send() * routine of the libfc Transport Template. The 'struct fc_seq' is a required * argument even though it is not used by this routine. * @@ -1206,8 +1206,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, rpriv->local_port->port_id, FC_TYPE_FCP, FC_FCTL_REQ, 0); - seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, - fsp, 0); + seq = fc_exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, fsp, 0); if (!seq) { rc = -1; goto unlock; @@ -1757,9 +1756,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) rpriv->local_port->port_id, FC_TYPE_FCP, FC_FCTL_REQ, 0); - seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, - fc_fcp_pkt_destroy, - fsp, get_fsp_rec_tov(fsp)); + seq = fc_exch_seq_send(lport, fp, fc_fcp_srr_resp, + fc_fcp_pkt_destroy, + fsp, get_fsp_rec_tov(fsp)); if (!seq) goto retry; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 42dcb722172b..1a4f17617260 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -2006,8 +2006,8 @@ static int fc_lport_els_request(struct fc_bsg_job *job, info->nents = job->reply_payload.sg_cnt; info->sg = job->reply_payload.sg_list; - if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp, - NULL, info, tov)) { + if (!fc_exch_seq_send(lport, fp, fc_lport_bsg_resp, + NULL, info, tov)) { kfree(info); return -ECOMM; } @@ -2067,8 +2067,8 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, info->nents = job->reply_payload.sg_cnt; info->sg = job->reply_payload.sg_list; - if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp, - NULL, info, tov)) { + if (!fc_exch_seq_send(lport, fp, fc_lport_bsg_resp, + NULL, info, tov)) { kfree(info); return -ECOMM; } diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4ca0f40dc0d6..d275df04f03a 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1282,8 +1282,8 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); kref_get(&rdata->kref); - if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp, - NULL, rdata, 2 * lport->r_a_tov)) { + if (!fc_exch_seq_send(lport, fp, fc_rport_prli_resp, + NULL, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); kref_put(&rdata->kref, lport->tt.rport_destroy); } -- cgit v1.2.3 From 944ef9689d8affc13d16c09ac2dba56c5b4c5ff7 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:39 +0200 Subject: scsi: libfc: Replace ->rport_destroy callback with function call The ->rport_destroy callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_disc.c | 6 ++-- drivers/scsi/libfc/fc_lport.c | 6 ++-- drivers/scsi/libfc/fc_rport.c | 68 +++++++++++++++++++------------------------ 3 files changed, 36 insertions(+), 44 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 4e3115211631..e5ffeab9f670 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -72,7 +72,7 @@ static void fc_disc_stop_rports(struct fc_disc *disc) list_for_each_entry_rcu(rdata, &disc->rports, peers) { if (kref_get_unless_zero(&rdata->kref)) { lport->tt.rport_logoff(rdata); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } rcu_read_unlock(); @@ -303,7 +303,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) else lport->tt.rport_logoff(rdata); } - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } rcu_read_unlock(); mutex_unlock(&disc->disc_mutex); @@ -649,7 +649,7 @@ redisc: mutex_unlock(&disc->disc_mutex); } out: - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 1a4f17617260..ad45808c4833 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -247,7 +247,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, { if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); - kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); + kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); } mutex_lock(&lport->disc.disc_mutex); lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); @@ -1017,7 +1017,7 @@ static void fc_lport_reset_locked(struct fc_lport *lport) if (lport->ptp_rdata) { lport->tt.rport_logoff(lport->ptp_rdata); - kref_put(&lport->ptp_rdata->kref, lport->tt.rport_destroy); + kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); lport->ptp_rdata = NULL; } @@ -2129,7 +2129,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) if (!rdata) break; tov = rdata->e_d_tov; - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } rc = fc_lport_ct_request(job, lport, did, tov); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index d275df04f03a..47ab9625246b 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -176,13 +176,14 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, * fc_rport_destroy() - Free a remote port after last reference is released * @kref: The remote port's kref */ -static void fc_rport_destroy(struct kref *kref) +void fc_rport_destroy(struct kref *kref) { struct fc_rport_priv *rdata; rdata = container_of(kref, struct fc_rport_priv, kref); kfree_rcu(rdata, rcu); } +EXPORT_SYMBOL(fc_rport_destroy); /** * fc_rport_state() - Return a string identifying the remote port's state @@ -294,7 +295,7 @@ static void fc_rport_work(struct work_struct *work) if (!rport) { FC_RPORT_DBG(rdata, "Failed to add the rport\n"); lport->tt.rport_logoff(rdata); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; } mutex_lock(&rdata->rp_mutex); @@ -320,7 +321,7 @@ static void fc_rport_work(struct work_struct *work) FC_RPORT_DBG(rdata, "lld callback ev %d\n", event); rdata->lld_event_callback(lport, rdata, event); } - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); break; case RPORT_EV_FAILED: @@ -347,7 +348,7 @@ static void fc_rport_work(struct work_struct *work) rdata->lld_event_callback(lport, rdata, event); } if (cancel_delayed_work_sync(&rdata->retry_work)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); /* * Reset any outstanding exchanges before freeing rport. @@ -369,7 +370,7 @@ static void fc_rport_work(struct work_struct *work) if (port_id == FC_FID_DIR_SERV) { rdata->event = RPORT_EV_NONE; mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } else if ((rdata->flags & FC_RP_STARTED) && rdata->major_retries < lport->max_rport_retry_count) { @@ -384,7 +385,7 @@ static void fc_rport_work(struct work_struct *work) list_del_rcu(&rdata->peers); mutex_unlock(&lport->disc.disc_mutex); mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } else { /* @@ -403,7 +404,7 @@ static void fc_rport_work(struct work_struct *work) mutex_unlock(&rdata->rp_mutex); break; } - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -470,8 +471,6 @@ static int fc_rport_login(struct fc_rport_priv *rdata) static void fc_rport_enter_delete(struct fc_rport_priv *rdata, enum fc_rport_event event) { - struct fc_lport *lport = rdata->local_port; - if (rdata->rp_state == RPORT_ST_DELETE) return; @@ -482,7 +481,7 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, kref_get(&rdata->kref); if (rdata->event == RPORT_EV_NONE && !queue_work(rport_event_queue, &rdata->event_work)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); rdata->event = event; } @@ -541,8 +540,6 @@ out: */ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) { - struct fc_lport *lport = rdata->local_port; - fc_rport_state_enter(rdata, RPORT_ST_READY); FC_RPORT_DBG(rdata, "Port is Ready\n"); @@ -550,7 +547,7 @@ static void fc_rport_enter_ready(struct fc_rport_priv *rdata) kref_get(&rdata->kref); if (rdata->event == RPORT_EV_NONE && !queue_work(rport_event_queue, &rdata->event_work)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); rdata->event = RPORT_EV_READY; } @@ -569,7 +566,6 @@ static void fc_rport_timeout(struct work_struct *work) { struct fc_rport_priv *rdata = container_of(work, struct fc_rport_priv, retry_work.work); - struct fc_lport *lport = rdata->local_port; mutex_lock(&rdata->rp_mutex); FC_RPORT_DBG(rdata, "Port timeout, state %s\n", fc_rport_state(rdata)); @@ -598,7 +594,7 @@ static void fc_rport_timeout(struct work_struct *work) } mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -661,7 +657,6 @@ static void fc_rport_error(struct fc_rport_priv *rdata, int err) static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err) { unsigned long delay = msecs_to_jiffies(rdata->e_d_tov); - struct fc_lport *lport = rdata->local_port; /* make sure this isn't an FC_EX_CLOSED error, never retry those */ if (err == -FC_EX_CLOSED) @@ -676,7 +671,7 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err) delay = 0; kref_get(&rdata->kref); if (!schedule_delayed_work(&rdata->retry_work, delay)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; } @@ -802,7 +797,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; bad: FC_RPORT_DBG(rdata, "Bad FLOGI response\n"); @@ -841,7 +836,7 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) fc_rport_flogi_resp, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -960,12 +955,12 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, } out: mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); fc_frame_free(rx_fp); return; reject_put: - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); reject: fc_seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); fc_frame_free(rx_fp); @@ -1042,7 +1037,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } static bool @@ -1098,7 +1093,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) fc_rport_plogi_resp, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -1218,7 +1213,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1285,7 +1280,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) if (!fc_exch_seq_send(lport, fp, fc_rport_prli_resp, NULL, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -1358,7 +1353,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1391,7 +1386,7 @@ static void fc_rport_enter_rtv(struct fc_rport_priv *rdata) fc_rport_rtv_resp, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -1446,7 +1441,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, "Received a LOGO %s\n", fc_els_resp_type(fp)); if (!IS_ERR(fp)) fc_frame_free(fp); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1472,7 +1467,7 @@ static void fc_rport_enter_logo(struct fc_rport_priv *rdata) kref_get(&rdata->kref); if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO, fc_rport_logo_resp, rdata, 0)) - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1534,7 +1529,7 @@ out: err: mutex_unlock(&rdata->rp_mutex); put: - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } /** @@ -1566,7 +1561,7 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) fc_rport_adisc_resp, rdata, 2 * lport->r_a_tov)) { fc_rport_error_retry(rdata, -FC_EX_XMIT_ERR); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } } @@ -1711,7 +1706,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) "while in state %s\n", fc_rport_state(rdata)); mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); goto busy; } default: @@ -1719,7 +1714,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) "Reject ELS 0x%02x while in state %s\n", fc_frame_payload_op(fp), fc_rport_state(rdata)); mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, lport->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); goto reject; } @@ -1753,7 +1748,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) } mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); return; reject: @@ -2158,7 +2153,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) fc_rport_enter_delete(rdata, RPORT_EV_STOP); mutex_unlock(&rdata->rp_mutex); - kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); + kref_put(&rdata->kref, fc_rport_destroy); } else FC_RPORT_ID_DBG(lport, sid, "Received LOGO from non-logged-in port\n"); @@ -2197,9 +2192,6 @@ int fc_rport_init(struct fc_lport *lport) if (!lport->tt.rport_flush_queue) lport->tt.rport_flush_queue = fc_rport_flush_queue; - if (!lport->tt.rport_destroy) - lport->tt.rport_destroy = fc_rport_destroy; - return 0; } EXPORT_SYMBOL(fc_rport_init); -- cgit v1.2.3 From e87b77779381ca148006da1d5f541df52ff6a445 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:40 +0200 Subject: scsi: libfc: Replace ->rport_lookup callback with function call The ->rport_lookup callback only ever had a single implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index ad45808c4833..2da6c7c6544d 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -2125,7 +2125,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) break; tov = rdata->e_d_tov; } else { - rdata = lport->tt.rport_lookup(lport, did); + rdata = fc_rport_lookup(lport, did); if (!rdata) break; tov = rdata->e_d_tov; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 47ab9625246b..5f674fc8412f 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -111,8 +111,8 @@ static const char *fc_rport_state_names[] = { * The reference count of the fc_rport_priv structure is * increased by one. */ -static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, - u32 port_id) +struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, + u32 port_id) { struct fc_rport_priv *rdata = NULL, *tmp_rdata; @@ -126,6 +126,7 @@ static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport, rcu_read_unlock(); return rdata; } +EXPORT_SYMBOL(fc_rport_lookup); /** * fc_rport_create() - Create a new remote port @@ -141,7 +142,7 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, { struct fc_rport_priv *rdata; - rdata = lport->tt.rport_lookup(lport, port_id); + rdata = fc_rport_lookup(lport, port_id); if (rdata) return rdata; @@ -875,7 +876,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, goto reject; } - rdata = lport->tt.rport_lookup(lport, sid); + rdata = fc_rport_lookup(lport, sid); if (!rdata) { rjt_data.reason = ELS_RJT_FIP; rjt_data.explan = ELS_EXPL_NOT_NEIGHBOR; @@ -1684,7 +1685,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) struct fc_rport_priv *rdata; struct fc_seq_els_data els_data; - rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); + rdata = fc_rport_lookup(lport, fc_frame_sid(fp)); if (!rdata) { FC_RPORT_ID_DBG(lport, fc_frame_sid(fp), "Received ELS 0x%02x from non-logged-in port\n", @@ -2145,7 +2146,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) sid = fc_frame_sid(fp); - rdata = lport->tt.rport_lookup(lport, sid); + rdata = fc_rport_lookup(lport, sid); if (rdata) { mutex_lock(&rdata->rp_mutex); FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", @@ -2174,9 +2175,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_lookup) - lport->tt.rport_lookup = fc_rport_lookup; - if (!lport->tt.rport_create) lport->tt.rport_create = fc_rport_create; -- cgit v1.2.3 From 2580064b5ec6dc9efa475298b276ab21f5cc287d Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:42 +0200 Subject: scsi: libfc: Replace ->rport_create callback with function call The ->rport_create callback only ever had a single implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_disc.c | 7 +++---- drivers/scsi/libfc/fc_lport.c | 6 +++--- drivers/scsi/libfc/fc_rport.c | 9 +++------ 3 files changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index e5ffeab9f670..305dd8541963 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -454,7 +454,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) if (ids.port_id != lport->port_id && ids.port_name != lport->wwpn) { - rdata = lport->tt.rport_create(lport, ids.port_id); + rdata = fc_rport_create(lport, ids.port_id); if (rdata) { rdata->ids.port_name = ids.port_name; rdata->disc_id = disc->disc_id; @@ -624,8 +624,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_unlock(&rdata->rp_mutex); lport->tt.rport_logoff(rdata); mutex_lock(&lport->disc.disc_mutex); - new_rdata = lport->tt.rport_create(lport, - rdata->ids.port_id); + new_rdata = fc_rport_create(lport, rdata->ids.port_id); mutex_unlock(&lport->disc.disc_mutex); if (new_rdata) { new_rdata->disc_id = disc->disc_id; @@ -690,7 +689,7 @@ static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp) { struct fc_rport_priv *rdata; - rdata = lport->tt.rport_create(lport, dp->port_id); + rdata = fc_rport_create(lport, dp->port_id); if (!rdata) return -ENOMEM; rdata->disc_id = 0; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2da6c7c6544d..a16936a833f8 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -250,7 +250,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); } mutex_lock(&lport->disc.disc_mutex); - lport->ptp_rdata = lport->tt.rport_create(lport, remote_fid); + lport->ptp_rdata = fc_rport_create(lport, remote_fid); kref_get(&lport->ptp_rdata->kref); lport->ptp_rdata->ids.port_name = remote_wwpn; lport->ptp_rdata->ids.node_name = remote_wwnn; @@ -1431,7 +1431,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_DNS); mutex_lock(&lport->disc.disc_mutex); - rdata = lport->tt.rport_create(lport, FC_FID_DIR_SERV); + rdata = fc_rport_create(lport, FC_FID_DIR_SERV); mutex_unlock(&lport->disc.disc_mutex); if (!rdata) goto err; @@ -1548,7 +1548,7 @@ static void fc_lport_enter_fdmi(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_FDMI); mutex_lock(&lport->disc.disc_mutex); - rdata = lport->tt.rport_create(lport, FC_FID_MGMT_SERV); + rdata = fc_rport_create(lport, FC_FID_MGMT_SERV); mutex_unlock(&lport->disc.disc_mutex); if (!rdata) goto err; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 5f674fc8412f..b05fa9997db5 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -137,8 +137,7 @@ EXPORT_SYMBOL(fc_rport_lookup); * * Locking note: must be called with the disc_mutex held. */ -static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, - u32 port_id) +struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, u32 port_id) { struct fc_rport_priv *rdata; @@ -172,6 +171,7 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, } return rdata; } +EXPORT_SYMBOL(fc_rport_create); /** * fc_rport_destroy() - Free a remote port after last reference is released @@ -1847,7 +1847,7 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, disc = &lport->disc; mutex_lock(&disc->disc_mutex); - rdata = lport->tt.rport_create(lport, sid); + rdata = fc_rport_create(lport, sid); if (!rdata) { mutex_unlock(&disc->disc_mutex); rjt_data.reason = ELS_RJT_UNAB; @@ -2175,9 +2175,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_create) - lport->tt.rport_create = fc_rport_create; - if (!lport->tt.rport_login) lport->tt.rport_login = fc_rport_login; -- cgit v1.2.3 From 05d7d3b0bd07e3990ab7a39ee93be28dbf7091d4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:43 +0200 Subject: scsi: libfc: Replace ->rport_login callback with function call The ->rport_login callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_disc.c | 6 +++--- drivers/scsi/libfc/fc_lport.c | 6 +++--- drivers/scsi/libfc/fc_rport.c | 14 ++++++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 305dd8541963..8d0aa19b1f5b 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -299,7 +299,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) continue; if (rdata->disc_id) { if (rdata->disc_id == disc->disc_id) - lport->tt.rport_login(rdata); + fc_rport_login(rdata); else lport->tt.rport_logoff(rdata); } @@ -628,13 +628,13 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_unlock(&lport->disc.disc_mutex); if (new_rdata) { new_rdata->disc_id = disc->disc_id; - lport->tt.rport_login(new_rdata); + fc_rport_login(new_rdata); } goto out; } rdata->disc_id = disc->disc_id; mutex_unlock(&rdata->rp_mutex); - lport->tt.rport_login(rdata); + fc_rport_login(rdata); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n", cp->ct_reason, cp->ct_explan); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index a16936a833f8..e20c1519be15 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -256,7 +256,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, lport->ptp_rdata->ids.node_name = remote_wwnn; mutex_unlock(&lport->disc.disc_mutex); - lport->tt.rport_login(lport->ptp_rdata); + fc_rport_login(lport->ptp_rdata); fc_lport_enter_ready(lport); } @@ -1437,7 +1437,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport) goto err; rdata->ops = &fc_lport_rport_ops; - lport->tt.rport_login(rdata); + fc_rport_login(rdata); return; err: @@ -1554,7 +1554,7 @@ static void fc_lport_enter_fdmi(struct fc_lport *lport) goto err; rdata->ops = &fc_lport_rport_ops; - lport->tt.rport_login(rdata); + fc_rport_login(rdata); return; err: diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index b05fa9997db5..c045bc459910 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -412,6 +412,14 @@ static void fc_rport_work(struct work_struct *work) * fc_rport_login() - Start the remote port login state machine * @rdata: The remote port to be logged in to * + * Initiates the RP state machine. It is called from the LP module. + * This function will issue the following commands to the N_Port + * identified by the FC ID provided. + * + * - PLOGI + * - PRLI + * - RTV + * * Locking Note: Called without the rport lock held. This * function will hold the rport lock, call an _enter_* * function and then unlock the rport. @@ -420,7 +428,7 @@ static void fc_rport_work(struct work_struct *work) * If it appears we are already logged in, ADISC is used to verify * the setup. */ -static int fc_rport_login(struct fc_rport_priv *rdata) +int fc_rport_login(struct fc_rport_priv *rdata) { mutex_lock(&rdata->rp_mutex); @@ -452,6 +460,7 @@ static int fc_rport_login(struct fc_rport_priv *rdata) return 0; } +EXPORT_SYMBOL(fc_rport_login); /** * fc_rport_enter_delete() - Schedule a remote port to be deleted @@ -2175,9 +2184,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_login) - lport->tt.rport_login = fc_rport_login; - if (!lport->tt.rport_logoff) lport->tt.rport_logoff = fc_rport_logoff; -- cgit v1.2.3 From c96c792aee33ab1a06c4d595959cd92eddbdbf3e Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:44 +0200 Subject: scsi: libfc: Replace ->rport_logoff callback with function call The ->rport_logoff callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Reviewed-by: Chad Dupuis Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_disc.c | 8 ++++---- drivers/scsi/libfc/fc_lport.c | 10 +++++----- drivers/scsi/libfc/fc_rport.c | 8 +++----- 3 files changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 8d0aa19b1f5b..7efa5a66e92a 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -71,7 +71,7 @@ static void fc_disc_stop_rports(struct fc_disc *disc) rcu_read_lock(); list_for_each_entry_rcu(rdata, &disc->rports, peers) { if (kref_get_unless_zero(&rdata->kref)) { - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); kref_put(&rdata->kref, fc_rport_destroy); } } @@ -301,7 +301,7 @@ static void fc_disc_done(struct fc_disc *disc, enum fc_disc_event event) if (rdata->disc_id == disc->disc_id) fc_rport_login(rdata); else - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } kref_put(&rdata->kref, fc_rport_destroy); } @@ -622,7 +622,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, "Port-id %6.6x wwpn %16.16llx\n", rdata->ids.port_id, port_name); mutex_unlock(&rdata->rp_mutex); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); mutex_lock(&lport->disc.disc_mutex); new_rdata = fc_rport_create(lport, rdata->ids.port_id); mutex_unlock(&lport->disc.disc_mutex); @@ -638,7 +638,7 @@ static void fc_disc_gpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { FC_DISC_DBG(disc, "GPN_ID rejected reason %x exp %x\n", cp->ct_reason, cp->ct_explan); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } else { FC_DISC_DBG(disc, "GPN_ID unexpected response code %x\n", ntohs(cp->ct_cmd)); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index e20c1519be15..a391cb160f4b 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -200,7 +200,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, "in the DNS or FDMI state, it's in the " "%d state", rdata->ids.port_id, lport->state); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); } break; case RPORT_EV_LOGO: @@ -246,7 +246,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, u64 remote_wwnn) { if (lport->ptp_rdata) { - lport->tt.rport_logoff(lport->ptp_rdata); + fc_rport_logoff(lport->ptp_rdata); kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); } mutex_lock(&lport->disc.disc_mutex); @@ -623,7 +623,7 @@ int fc_fabric_logoff(struct fc_lport *lport) lport->tt.disc_stop_final(lport); mutex_lock(&lport->lp_mutex); if (lport->dns_rdata) - lport->tt.rport_logoff(lport->dns_rdata); + fc_rport_logoff(lport->dns_rdata); mutex_unlock(&lport->lp_mutex); lport->tt.rport_flush_queue(); mutex_lock(&lport->lp_mutex); @@ -1011,12 +1011,12 @@ EXPORT_SYMBOL(fc_lport_reset); static void fc_lport_reset_locked(struct fc_lport *lport) { if (lport->dns_rdata) { - lport->tt.rport_logoff(lport->dns_rdata); + fc_rport_logoff(lport->dns_rdata); lport->dns_rdata = NULL; } if (lport->ptp_rdata) { - lport->tt.rport_logoff(lport->ptp_rdata); + fc_rport_logoff(lport->ptp_rdata); kref_put(&lport->ptp_rdata->kref, fc_rport_destroy); lport->ptp_rdata = NULL; } diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index c045bc459910..22c8c928ee2b 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -295,7 +295,7 @@ static void fc_rport_work(struct work_struct *work) } if (!rport) { FC_RPORT_DBG(rdata, "Failed to add the rport\n"); - lport->tt.rport_logoff(rdata); + fc_rport_logoff(rdata); kref_put(&rdata->kref, fc_rport_destroy); return; } @@ -504,7 +504,7 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, * function will hold the rport lock, call an _enter_* * function and then unlock the rport. */ -static int fc_rport_logoff(struct fc_rport_priv *rdata) +int fc_rport_logoff(struct fc_rport_priv *rdata) { struct fc_lport *lport = rdata->local_port; u32 port_id = rdata->ids.port_id; @@ -538,6 +538,7 @@ out: mutex_unlock(&rdata->rp_mutex); return 0; } +EXPORT_SYMBOL(fc_rport_logoff); /** * fc_rport_enter_ready() - Transition to the RPORT_ST_READY state @@ -2184,9 +2185,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_logoff) - lport->tt.rport_logoff = fc_rport_logoff; - if (!lport->tt.rport_recv_req) lport->tt.rport_recv_req = fc_rport_recv_req; -- cgit v1.2.3 From e76ee65fa649740fde0da44a0e1dc458407c685c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:45 +0200 Subject: scsi: libfc: Replace ->rport_recv_req callback with function call The ->rport_recv_req callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index a391cb160f4b..937a442cc70e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -902,7 +902,7 @@ static void fc_lport_recv_els_req(struct fc_lport *lport, /* * Check opcode. */ - recv = lport->tt.rport_recv_req; + recv = fc_rport_recv_req; switch (fc_frame_payload_op(fp)) { case ELS_FLOGI: if (!lport->point_to_multipoint) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 22c8c928ee2b..feae7abf05c3 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1786,7 +1786,7 @@ busy: * * Reference counting: does not modify kref */ -static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) +void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) { struct fc_seq_els_data els_data; @@ -1823,6 +1823,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) break; } } +EXPORT_SYMBOL(fc_rport_recv_req); /** * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests @@ -2185,9 +2186,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_recv_req) - lport->tt.rport_recv_req = fc_rport_recv_req; - if (!lport->tt.rport_flush_queue) lport->tt.rport_flush_queue = fc_rport_flush_queue; -- cgit v1.2.3 From 5922a957457c9146fc601ce3c36a076dde249593 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:46 +0200 Subject: scsi: libfc: Replace ->rport_flush_queue callback with function call The ->rport_flush_queue callback only ever had a single implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_disc.c | 2 +- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 7efa5a66e92a..6103231104da 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -719,7 +719,7 @@ static void fc_disc_stop(struct fc_lport *lport) static void fc_disc_stop_final(struct fc_lport *lport) { fc_disc_stop(lport); - lport->tt.rport_flush_queue(); + fc_rport_flush_queue(); } /** diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 937a442cc70e..7315675d3e33 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -625,7 +625,7 @@ int fc_fabric_logoff(struct fc_lport *lport) if (lport->dns_rdata) fc_rport_logoff(lport->dns_rdata); mutex_unlock(&lport->lp_mutex); - lport->tt.rport_flush_queue(); + fc_rport_flush_queue(); mutex_lock(&lport->lp_mutex); fc_lport_enter_logo(lport); mutex_unlock(&lport->lp_mutex); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index feae7abf05c3..6e5022627777 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -2175,10 +2175,11 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) /** * fc_rport_flush_queue() - Flush the rport_event_queue */ -static void fc_rport_flush_queue(void) +void fc_rport_flush_queue(void) { flush_workqueue(rport_event_queue); } +EXPORT_SYMBOL(fc_rport_flush_queue); /** * fc_rport_init() - Initialize the remote port layer for a local port @@ -2186,9 +2187,6 @@ static void fc_rport_flush_queue(void) */ int fc_rport_init(struct fc_lport *lport) { - if (!lport->tt.rport_flush_queue) - lport->tt.rport_flush_queue = fc_rport_flush_queue; - return 0; } EXPORT_SYMBOL(fc_rport_init); -- cgit v1.2.3 From a8220ded095695f2f11f0c35e1d2578bb0ec0e8f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:47 +0200 Subject: scsi: libfc: Remove fc_rport_init() Function is empty now and can be removed. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Reviewed-by: Chad Dupuis Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6e5022627777..110a707d8e82 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -2181,16 +2181,6 @@ void fc_rport_flush_queue(void) } EXPORT_SYMBOL(fc_rport_flush_queue); -/** - * fc_rport_init() - Initialize the remote port layer for a local port - * @lport: The local port to initialize the remote port layer for - */ -int fc_rport_init(struct fc_lport *lport) -{ - return 0; -} -EXPORT_SYMBOL(fc_rport_init); - /** * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator. * @rdata: remote port private -- cgit v1.2.3 From 0cac937da525ae3aa9f4b82c6ca129d16bb321fe Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:48 +0200 Subject: scsi: libfc: Replace ->seq_send callback with function call The ->seq_send callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 7 ++----- drivers/scsi/libfc/fc_fcp.c | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index f5c3c1d09651..ee34cc6aded7 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -533,8 +533,7 @@ out: * Note: The frame will be freed either by a direct call to fc_frame_free(fp) * or indirectly by calling libfc_function_template.frame_send(). */ -static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, - struct fc_frame *fp) +int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, struct fc_frame *fp) { struct fc_exch *ep; int error; @@ -544,6 +543,7 @@ static int fc_seq_send(struct fc_lport *lport, struct fc_seq *sp, spin_unlock_bh(&ep->ex_lock); return error; } +EXPORT_SYMBOL(fc_seq_send); /** * fc_seq_alloc() - Allocate a sequence for a given exchange @@ -2648,9 +2648,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_set_resp) lport->tt.seq_set_resp = fc_seq_set_resp; - if (!lport->tt.seq_send) - lport->tt.seq_send = fc_seq_send; - if (!lport->tt.exch_done) lport->tt.exch_done = fc_exch_done; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 5cf1d2e3b575..daad70ff8c8f 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -731,7 +731,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, /* * send fragment using for a sequence. */ - error = lport->tt.seq_send(lport, seq, fp); + error = fc_seq_send(lport, seq, fp); if (error) { WARN_ON(1); /* send error should be rare */ return error; @@ -1033,7 +1033,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) fc_fill_fc_hdr(conf_frame, FC_RCTL_DD_SOL_CTL, ep->did, ep->sid, FC_TYPE_FCP, f_ctl, 0); - lport->tt.seq_send(lport, csp, conf_frame); + fc_seq_send(lport, csp, conf_frame); } } lport->tt.exch_done(seq); -- cgit v1.2.3 From 0ebaed17febadeda0f4da21da2c0f295f46348a4 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:49 +0200 Subject: scsi: libfc: Replace ->seq_exch_abort callback with function call The ->seq_exch_abort callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 13 ++++++++----- drivers/scsi/libfc/fc_fcp.c | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index ee34cc6aded7..fffb9a3162e2 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -629,6 +629,13 @@ static void fc_seq_set_resp(struct fc_seq *sp, * @ep: The exchange to be aborted * @timer_msec: The period of time to wait before aborting * + * Abort an exchange and sequence. Generally called because of a + * exchange timeout or an abort from the upper layer. + * + * A timer_msec can be specified for abort timeout, if non-zero + * timer_msec value is specified then exchange resp handler + * will be called with timeout error if no response to abort. + * * Locking notes: Called with exch lock held * * Return value: 0 on success else error code @@ -692,8 +699,7 @@ static int fc_exch_abort_locked(struct fc_exch *ep, * * Return value: 0 on success else error code */ -static int fc_seq_exch_abort(const struct fc_seq *req_sp, - unsigned int timer_msec) +int fc_seq_exch_abort(const struct fc_seq *req_sp, unsigned int timer_msec) { struct fc_exch *ep; int error; @@ -2654,9 +2660,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; - if (!lport->tt.seq_exch_abort) - lport->tt.seq_exch_abort = fc_seq_exch_abort; - if (!lport->tt.seq_assign) lport->tt.seq_assign = fc_seq_assign; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index daad70ff8c8f..2bb3f9f74ad2 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -287,9 +287,9 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) put_cpu(); fsp->state |= FC_SRB_ABORT_PENDING; - rc = fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0); + rc = fc_seq_exch_abort(fsp->seq_ptr, 0); /* - * ->seq_exch_abort() might return -ENXIO if + * fc_seq_exch_abort() might return -ENXIO if * the sequence is already completed */ if (rc == -ENXIO) { -- cgit v1.2.3 From 768c72cc34a26ed1c41c9af89886f91af08ded8c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:50 +0200 Subject: scsi: libfc: Replace ->exch_done callback with function call The ->exch_done callback only ever had one implementation, so we can as well call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 6 ++---- drivers/scsi/libfc/fc_fcp.c | 20 +++++++++----------- drivers/scsi/libfc/fc_lport.c | 2 +- 3 files changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index fffb9a3162e2..b98ad3f743cb 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -969,7 +969,7 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) * * Note: May sleep if invoked from outside a response handler. */ -static void fc_exch_done(struct fc_seq *sp) +void fc_exch_done(struct fc_seq *sp) { struct fc_exch *ep = fc_seq_exch(sp); int rc; @@ -982,6 +982,7 @@ static void fc_exch_done(struct fc_seq *sp) if (!rc) fc_exch_delete(ep); } +EXPORT_SYMBOL(fc_exch_done); /** * fc_exch_resp() - Allocate a new exchange for a response frame @@ -2654,9 +2655,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.seq_set_resp) lport->tt.seq_set_resp = fc_seq_set_resp; - if (!lport->tt.exch_done) - lport->tt.exch_done = fc_exch_done; - if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 2bb3f9f74ad2..4fadd6249700 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -311,7 +311,7 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp) static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp, int status_code) { if (fsp->seq_ptr) { - fsp->lp->tt.exch_done(fsp->seq_ptr); + fc_exch_done(fsp->seq_ptr); fsp->seq_ptr = NULL; } @@ -1036,7 +1036,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) fc_seq_send(lport, csp, conf_frame); } } - lport->tt.exch_done(seq); + fc_exch_done(seq); } /* * Some resets driven by SCSI are not I/Os and do not have @@ -1054,10 +1054,8 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) */ static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error) { - struct fc_lport *lport = fsp->lp; - if (fsp->seq_ptr) { - lport->tt.exch_done(fsp->seq_ptr); + fc_exch_done(fsp->seq_ptr); fsp->seq_ptr = NULL; } fsp->status_code = error; @@ -1349,7 +1347,7 @@ static int fc_lun_reset(struct fc_lport *lport, struct fc_fcp_pkt *fsp, spin_lock_bh(&fsp->scsi_pkt_lock); if (fsp->seq_ptr) { - lport->tt.exch_done(fsp->seq_ptr); + fc_exch_done(fsp->seq_ptr); fsp->seq_ptr = NULL; } fsp->wait_for_comp = 0; @@ -1403,7 +1401,7 @@ static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg) if (fh->fh_type != FC_TYPE_BLS) fc_fcp_resp(fsp, fp); fsp->seq_ptr = NULL; - fsp->lp->tt.exch_done(seq); + fc_exch_done(seq); out_unlock: fc_fcp_unlock_pkt(fsp); out: @@ -1793,9 +1791,9 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fh = fc_frame_header_get(fp); /* - * BUG? fc_fcp_srr_error calls exch_done which would release + * BUG? fc_fcp_srr_error calls fc_exch_done which would release * the ep. But if fc_fcp_srr_error had got -FC_EX_TIMEOUT, - * then fc_exch_timeout would be sending an abort. The exch_done + * then fc_exch_timeout would be sending an abort. The fc_exch_done * call by fc_fcp_srr_error would prevent fc_exch.c from seeing * an abort response though. */ @@ -1816,7 +1814,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) } fc_fcp_unlock_pkt(fsp); out: - fsp->lp->tt.exch_done(seq); + fc_exch_done(seq); fc_frame_free(fp); } @@ -1846,7 +1844,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) } fc_fcp_unlock_pkt(fsp); out: - fsp->lp->tt.exch_done(fsp->recov_seq); + fc_exch_done(fsp->recov_seq); } /** diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 7315675d3e33..2d3133f62463 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -980,7 +980,7 @@ drop: FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type); fc_frame_free(fp); if (sp) - lport->tt.exch_done(sp); + fc_exch_done(sp); } EXPORT_SYMBOL(fc_lport_recv); -- cgit v1.2.3 From c6865b30be7ed894839687b26f2cde9b99b97270 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:51 +0200 Subject: scsi: libfc: Replace ->seq_start_next callback with function call The ->seq_start_next callback only ever had one implementation, so call the function directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 6 ++---- drivers/scsi/libfc/fc_fcp.c | 4 ++-- drivers/scsi/libfc/fc_libfc.c | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index b98ad3f743cb..8a99f846441a 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -585,7 +585,7 @@ static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp) * for a given sequence/exchange pair * @sp: The sequence/exchange to get a new exchange for */ -static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) +struct fc_seq *fc_seq_start_next(struct fc_seq *sp) { struct fc_exch *ep = fc_seq_exch(sp); @@ -595,6 +595,7 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp) return sp; } +EXPORT_SYMBOL(fc_seq_start_next); /* * Set the response handler for the exchange associated with a sequence. @@ -2649,9 +2650,6 @@ EXPORT_SYMBOL(fc_exch_recv); */ int fc_exch_init(struct fc_lport *lport) { - if (!lport->tt.seq_start_next) - lport->tt.seq_start_next = fc_seq_start_next; - if (!lport->tt.seq_set_resp) lport->tt.seq_set_resp = fc_seq_set_resp; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 4fadd6249700..0e67621477a8 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -653,7 +653,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, remaining = seq_blen; fh_parm_offset = frame_offset = offset; tlen = 0; - seq = lport->tt.seq_start_next(seq); + seq = fc_seq_start_next(seq); f_ctl = FC_FC_REL_OFF; WARN_ON(!seq); @@ -1024,7 +1024,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) struct fc_frame *conf_frame; struct fc_seq *csp; - csp = lport->tt.seq_start_next(seq); + csp = fc_seq_start_next(seq); conf_frame = fc_fcp_frame_alloc(fsp->lp, 0); if (conf_frame) { f_ctl = FC_FC_SEQ_INIT; diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c index c11a638f32e6..d623d084b7ec 100644 --- a/drivers/scsi/libfc/fc_libfc.c +++ b/drivers/scsi/libfc/fc_libfc.c @@ -226,7 +226,7 @@ void fc_fill_reply_hdr(struct fc_frame *fp, const struct fc_frame *in_fp, sp = fr_seq(in_fp); if (sp) - fr_seq(fp) = fr_dev(in_fp)->tt.seq_start_next(sp); + fr_seq(fp) = fc_seq_start_next(sp); fc_fill_hdr(fp, in_fp, r_ctl, FC_FCTL_RESP, 0, parm_offset); } EXPORT_SYMBOL(fc_fill_reply_hdr); -- cgit v1.2.3 From f1d61e6e682cd241c145e6268be3a9f30af934eb Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:52 +0200 Subject: scsi: libfc: Replace ->seq_set_resp callback with direct function call The ->seq_set_resp callback only ever had one implementation, so call it directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8a99f846441a..ceeccd7b3ba7 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -602,10 +602,9 @@ EXPORT_SYMBOL(fc_seq_start_next); * * Note: May sleep if invoked from outside a response handler. */ -static void fc_seq_set_resp(struct fc_seq *sp, - void (*resp)(struct fc_seq *, struct fc_frame *, - void *), - void *arg) +void fc_seq_set_resp(struct fc_seq *sp, + void (*resp)(struct fc_seq *, struct fc_frame *, void *), + void *arg) { struct fc_exch *ep = fc_seq_exch(sp); DEFINE_WAIT(wait); @@ -624,6 +623,7 @@ static void fc_seq_set_resp(struct fc_seq *sp, ep->arg = arg; spin_unlock_bh(&ep->ex_lock); } +EXPORT_SYMBOL(fc_seq_set_resp); /** * fc_exch_abort_locked() - Abort an exchange @@ -2650,9 +2650,6 @@ EXPORT_SYMBOL(fc_exch_recv); */ int fc_exch_init(struct fc_lport *lport) { - if (!lport->tt.seq_set_resp) - lport->tt.seq_set_resp = fc_seq_set_resp; - if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; -- cgit v1.2.3 From 96d564e24ac2b69fbfa2b81d48069ffeede549d7 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:53 +0200 Subject: scsi: libfc: Replace ->seq_assign callback with function call The ->seq_assign callback only ever had one implementation, so call the function directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index ceeccd7b3ba7..efb6a4b7a62a 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1477,7 +1477,7 @@ reject: * A reference will be held on the exchange/sequence for the caller, which * must call fc_seq_release(). */ -static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) +struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) { struct fc_exch_mgr_anchor *ema; @@ -1491,6 +1491,7 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) break; return fr_seq(fp); } +EXPORT_SYMBOL(fc_seq_assign); /** * fc_seq_release() - Release the hold @@ -2653,9 +2654,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; - if (!lport->tt.seq_assign) - lport->tt.seq_assign = fc_seq_assign; - if (!lport->tt.seq_release) lport->tt.seq_release = fc_seq_release; -- cgit v1.2.3 From 9625cc483b8c41d500ec78f0f2e61d71db1431f5 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 18 Oct 2016 10:01:54 +0200 Subject: scsi: libfc: Replace ->seq_release callback with function call The ->seq_release callback only ever had one implementation, so call the function directly and drop the callback. Signed-off-by: Hannes Reinecke Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index efb6a4b7a62a..442a6c1d5efc 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1497,10 +1497,11 @@ EXPORT_SYMBOL(fc_seq_assign); * fc_seq_release() - Release the hold * @sp: The sequence. */ -static void fc_seq_release(struct fc_seq *sp) +void fc_seq_release(struct fc_seq *sp) { fc_exch_release(fc_seq_exch(sp)); } +EXPORT_SYMBOL(fc_seq_release); /** * fc_exch_recv_req() - Handler for an incoming request @@ -2654,9 +2655,6 @@ int fc_exch_init(struct fc_lport *lport) if (!lport->tt.exch_mgr_reset) lport->tt.exch_mgr_reset = fc_exch_mgr_reset; - if (!lport->tt.seq_release) - lport->tt.seq_release = fc_seq_release; - return 0; } EXPORT_SYMBOL(fc_exch_init); -- cgit v1.2.3 From d5c3eb26d9ad78a2705ec675dd2399e985c5ee52 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 21 Oct 2016 14:10:53 -0700 Subject: scsi: libfc: Don't have fc_exch_find log errors on a new exchange With the error message I added in "libfc: sanity check cpu number extracted from xid" I didn't account for the fact that fc_exch_find is called with FC_XID_UNKNOWN at the start of a new exchange if we are the responder. It doesn't come up with the initiator much, but that's basically every exchange for a target. By checking the xid for FC_XID_UNKNOWN first, we not only prevent the erroneous error message, but skip the unnecessary lookup attempt as well. [mkp: applied by hand due to conflict with Hannes' libfc patch series] Signed-off-by: Chris Leech Reviewed-by: Ewan D. Milne Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 442a6c1d5efc..42bcf7f3a0f9 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -939,6 +939,9 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid) struct fc_exch *ep = NULL; u16 cpu = xid & fc_cpu_mask; + if (xid == FC_XID_UNKNOWN) + return NULL; + if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) { pr_err("host%u: lport %6.6x: xid %d invalid CPU %d\n:", lport->host->host_no, lport->port_id, xid, cpu); -- cgit v1.2.3 From 01e0e15c8b3b32e006e5cccac10c8b377ac3d803 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:12 +0100 Subject: scsi: don't use fc_bsg_job::request and fc_bsg_job::reply directly Don't use fc_bsg_job::request and fc_bsg_job::reply directly, but use helper variables bsg_request and bsg_reply. This will be helpful when transitioning to bsg-lib. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2d3133f62463..2de6093b3c04 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1902,13 +1902,14 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, { struct fc_bsg_info *info = info_arg; struct fc_bsg_job *job = info->job; + struct fc_bsg_reply *bsg_reply = job->reply; struct fc_lport *lport = info->lport; struct fc_frame_header *fh; size_t len; void *buf; if (IS_ERR(fp)) { - job->reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? + bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? -ECONNABORTED : -ETIMEDOUT; job->reply_len = sizeof(uint32_t); job->state_flags |= FC_RQST_STATE_DONE; @@ -1929,23 +1930,23 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, (unsigned short)fc_frame_payload_op(fp); /* Save the reply status of the job */ - job->reply->reply_data.ctels_reply.status = + bsg_reply->reply_data.ctels_reply.status = (cmd == info->rsp_code) ? FC_CTELS_STATUS_OK : FC_CTELS_STATUS_REJECT; } - job->reply->reply_payload_rcv_len += + bsg_reply->reply_payload_rcv_len += fc_copy_buffer_to_sglist(buf, len, info->sg, &info->nents, &info->offset, NULL); if (fr_eof(fp) == FC_EOF_T && (ntoh24(fh->fh_f_ctl) & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) == (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) { - if (job->reply->reply_payload_rcv_len > + if (bsg_reply->reply_payload_rcv_len > job->reply_payload.payload_len) - job->reply->reply_payload_rcv_len = + bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; - job->reply->result = 0; + bsg_reply->result = 0; job->state_flags |= FC_RQST_STATE_DONE; job->job_done(job); kfree(info); @@ -2082,6 +2083,8 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, */ int fc_lport_bsg_request(struct fc_bsg_job *job) { + struct fc_bsg_request *bsg_request = job->request; + struct fc_bsg_reply *bsg_reply = job->reply; struct request *rsp = job->req->next_rq; struct Scsi_Host *shost = job->shost; struct fc_lport *lport = shost_priv(shost); @@ -2090,13 +2093,13 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) int rc = -EINVAL; u32 did, tov; - job->reply->reply_payload_rcv_len = 0; + bsg_reply->reply_payload_rcv_len = 0; if (rsp) rsp->resid_len = job->reply_payload.payload_len; mutex_lock(&lport->lp_mutex); - switch (job->request->msgcode) { + switch (bsg_request->msgcode) { case FC_BSG_RPT_ELS: rport = job->rport; if (!rport) @@ -2118,7 +2121,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) break; case FC_BSG_HST_CT: - did = ntoh24(job->request->rqst_data.h_ct.port_id); + did = ntoh24(bsg_request->rqst_data.h_ct.port_id); if (did == FC_FID_DIR_SERV) { rdata = lport->dns_rdata; if (!rdata) @@ -2136,7 +2139,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) break; case FC_BSG_HST_ELS_NOLOGIN: - did = ntoh24(job->request->rqst_data.h_els.port_id); + did = ntoh24(bsg_request->rqst_data.h_els.port_id); rc = fc_lport_els_request(job, lport, did, lport->e_d_tov); break; } -- cgit v1.2.3 From 1abaede71560fa98b97d8e6b172a14e6383f633d Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:13 +0100 Subject: scsi: fc: Export fc_bsg_jobdone and use it in FC drivers Export fc_bsg_jobdone so drivers can use it directly instead of doing the round-trip via struct fc_bsg_job::job_done() and use it in the LLDDs. That way we can also unify the interfaces of fc_bsg_jobdone and bsg_job_done. As we've converted all LLDDs over to use fc_bsg_jobdone() directly, we can remove the function pointer from struct fc_bsg_job as well. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 2de6093b3c04..8ea6e9322ad1 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1913,7 +1913,8 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, -ECONNABORTED : -ETIMEDOUT; job->reply_len = sizeof(uint32_t); job->state_flags |= FC_RQST_STATE_DONE; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); kfree(info); return; } @@ -1948,7 +1949,8 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, job->reply_payload.payload_len; bsg_reply->result = 0; job->state_flags |= FC_RQST_STATE_DONE; - job->job_done(job); + fc_bsg_jobdone(job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); kfree(info); } fc_frame_free(fp); -- cgit v1.2.3 From cd21c605b2cf1cf4e698eb4f043f6a7f72b55691 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:14 +0100 Subject: scsi: fc: provide fc_bsg_to_shost() helper Provide fc_bsg_to_shost() helper that will become handy when we're moving from struct fc_bsg_job to a plain struct bsg_job. Also use this little helper in the LLDDs. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 8ea6e9322ad1..3e3afe6e0cde 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -2088,7 +2088,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; struct request *rsp = job->req->next_rq; - struct Scsi_Host *shost = job->shost; + struct Scsi_Host *shost = fc_bsg_to_shost(job); struct fc_lport *lport = shost_priv(shost); struct fc_rport *rport; struct fc_rport_priv *rdata; -- cgit v1.2.3 From 1d69b1222abcba58e567bc99b0b76b7857dc5031 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:15 +0100 Subject: scsi: fc: provide fc_bsg_to_rport() helper Provide fc_bsg_to_rport() helper that will become handy when we're moving from struct fc_bsg_job to a plain struct bsg_job. Also move all LLDDs to use the new helper. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 3e3afe6e0cde..5e24ca3118c3 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -2103,7 +2103,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) switch (bsg_request->msgcode) { case FC_BSG_RPT_ELS: - rport = job->rport; + rport = fc_bsg_to_rport(job); if (!rport) break; @@ -2113,7 +2113,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job) break; case FC_BSG_RPT_CT: - rport = job->rport; + rport = fc_bsg_to_rport(job); if (!rport) break; -- cgit v1.2.3 From 7ac65007c285e377a31107fe2e13afacf47400f2 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:16 +0100 Subject: scsi: libfc: don't set FC_RQST_STATE_DONE before calling fc_bsg_jobdone() Don't set FC_RQST_STATE_DONE before calling fc_bsg_jobdone() as fc_bsg_jobdone() calls blk_complete_requeust() which raises a soft-IRQ that ends up in fc_bsg_sofirq_done() and fc_bsg_softirq_done() sets the FC_RQST_STATE_DONE flag. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 5e24ca3118c3..cc98ebc9d0af 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1912,7 +1912,6 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? -ECONNABORTED : -ETIMEDOUT; job->reply_len = sizeof(uint32_t); - job->state_flags |= FC_RQST_STATE_DONE; fc_bsg_jobdone(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(info); @@ -1948,7 +1947,6 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; bsg_reply->result = 0; - job->state_flags |= FC_RQST_STATE_DONE; fc_bsg_jobdone(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(info); -- cgit v1.2.3 From 75cc8cfc6e13d42d50c2bf4307d0a68c2a70f709 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:19 +0100 Subject: scsi: change FC drivers to use 'struct bsg_job' Change FC drivers to use 'struct bsg_job' from bsg-lib.h instead of 'struct fc_bsg_job' from scsi_transport_fc.h and remove 'struct fc_bsg_job'. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index cc98ebc9d0af..c428ce389a5b 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -149,7 +149,7 @@ static const char *fc_lport_state_names[] = { * @offset: The offset into the response data */ struct fc_bsg_info { - struct fc_bsg_job *job; + struct bsg_job *job; struct fc_lport *lport; u16 rsp_code; struct scatterlist *sg; @@ -1901,7 +1901,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, void *info_arg) { struct fc_bsg_info *info = info_arg; - struct fc_bsg_job *job = info->job; + struct bsg_job *job = info->job; struct fc_bsg_reply *bsg_reply = job->reply; struct fc_lport *lport = info->lport; struct fc_frame_header *fh; @@ -1964,7 +1964,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, * Locking Note: The lport lock is expected to be held before calling * this routine. */ -static int fc_lport_els_request(struct fc_bsg_job *job, +static int fc_lport_els_request(struct bsg_job *job, struct fc_lport *lport, u32 did, u32 tov) { @@ -2025,7 +2025,7 @@ static int fc_lport_els_request(struct fc_bsg_job *job, * Locking Note: The lport lock is expected to be held before calling * this routine. */ -static int fc_lport_ct_request(struct fc_bsg_job *job, +static int fc_lport_ct_request(struct bsg_job *job, struct fc_lport *lport, u32 did, u32 tov) { struct fc_bsg_info *info; @@ -2081,7 +2081,7 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, * FC Passthrough requests * @job: The BSG passthrough job */ -int fc_lport_bsg_request(struct fc_bsg_job *job) +int fc_lport_bsg_request(struct bsg_job *job) { struct fc_bsg_request *bsg_request = job->request; struct fc_bsg_reply *bsg_reply = job->reply; -- cgit v1.2.3 From 06548160dfecd1983ffd9d6795242a5cda095da5 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Thu, 17 Nov 2016 10:31:22 +0100 Subject: scsi: fc: use bsg_job_done fc_bsg_jobdone() and bsg_job_done() are 1:1 copies now so use the bsg-lib one instead of the FC private implementation. Signed-off-by: Johannes Thumshirn Reviewed-by: Hannes Reinecke Acked-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_lport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index c428ce389a5b..2be7015498fd 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1912,7 +1912,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ? -ECONNABORTED : -ETIMEDOUT; job->reply_len = sizeof(uint32_t); - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(info); return; @@ -1947,7 +1947,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp, bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len; bsg_reply->result = 0; - fc_bsg_jobdone(job, bsg_reply->result, + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(info); } -- cgit v1.2.3 From 27c3d76821a5f563cd3d760bfa7c8deb43f8d874 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 24 Nov 2016 13:52:38 +0300 Subject: scsi: libfc: Remove an unneeded condition We verified that resp_code is FC_SPP_RESP_ACK earlier so we don't need to check again here. Signed-off-by: Dan Carpenter Acked-by: Johannes Thumshirn Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_rport.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi/libfc') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 110a707d8e82..c991f3b822f8 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1196,7 +1196,6 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, * Check if the image pair could be established */ if (rdata->spp_type != FC_TYPE_FCP || - resp_code != FC_SPP_RESP_ACK || !(pp->spp.spp_flags & FC_SPP_EST_IMG_PAIR)) { /* * Nope; we can't use this port as a target. -- cgit v1.2.3