1 From: Chris Leech <christopher.leech@intel.com>
2 Subject: libfc: rport retry on LS_RJT from certain ELS
3 Patch-mainline: 6147a1194ba86af4266f36c9522a7b0040af98fe
4 References: bnc #468054
6 This allows any rport ELS to retry on LS_RJT.
8 The rport error handling would only retry on resource allocation failures
9 and exchange timeouts. I have a target that will occasionally reject PLOGI
10 when we do a quick LOGO/PLOGI. When a critical ELS was rejected, libfc would
11 fail silently leaving the rport in a dead state.
13 The retry count and delay are managed by fc_rport_error_retry. If the retry
14 count is exceeded fc_rport_error will be called. When retrying is not the
15 correct course of action, fc_rport_error can be called directly.
17 Signed-off-by: Chris Leech <christopher.leech@intel.com>
18 Acked-by: Bernhard Walle <bwalle@suse.de>
20 drivers/scsi/libfc/fc_exch.c | 2
21 drivers/scsi/libfc/fc_rport.c | 111 ++++++++++++++++++++++++------------------
22 include/scsi/fc/fc_fs.h | 5 +
23 3 files changed, 69 insertions(+), 49 deletions(-)
25 --- a/drivers/scsi/libfc/fc_exch.c
26 +++ b/drivers/scsi/libfc/fc_exch.c
28 #include <scsi/libfc.h>
29 #include <scsi/fc_encode.h>
31 -#define FC_DEF_R_A_TOV (10 * 1000) /* resource allocation timeout */
34 * fc_exch_debug can be set in debugger or at compile time to get more logs.
36 --- a/drivers/scsi/libfc/fc_rport.c
37 +++ b/drivers/scsi/libfc/fc_rport.c
38 @@ -81,6 +81,7 @@ static void fc_rport_recv_logo_req(struc
39 struct fc_seq *, struct fc_frame *);
40 static void fc_rport_timeout(struct work_struct *);
41 static void fc_rport_error(struct fc_rport *, struct fc_frame *);
42 +static void fc_rport_error_retry(struct fc_rport *, struct fc_frame *);
43 static void fc_rport_work(struct work_struct *);
45 static const char *fc_rport_state_names[] = {
46 @@ -405,55 +406,71 @@ static void fc_rport_timeout(struct work
50 - * fc_rport_error - Handler for any errors
51 + * fc_rport_error - Error handler, called once retries have been exhausted
52 * @rport: The fc_rport object
53 * @fp: The frame pointer
55 - * If the error was caused by a resource allocation failure
56 - * then wait for half a second and retry, otherwise retry
59 * Locking Note: The rport lock is expected to be held before
60 * calling this routine
62 static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
64 struct fc_rport_libfc_priv *rdata = rport->dd_data;
65 - unsigned long delay = 0;
67 FC_DEBUG_RPORT("Error %ld in state %s, retries %d\n",
68 PTR_ERR(fp), fc_rport_state(rport), rdata->retries);
70 - if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
72 - * Memory allocation failure, or the exchange timed out.
75 - if (rdata->retries < rdata->local_port->max_retry_count) {
78 - delay = msecs_to_jiffies(500);
79 - get_device(&rport->dev);
80 - schedule_delayed_work(&rdata->retry_work, delay);
82 - switch (rdata->rp_state) {
83 - case RPORT_ST_PLOGI:
86 - rdata->event = RPORT_EV_FAILED;
87 - queue_work(rport_event_queue,
88 - &rdata->event_work);
91 - fc_rport_enter_ready(rport);
94 - case RPORT_ST_READY:
99 + switch (rdata->rp_state) {
100 + case RPORT_ST_PLOGI:
101 + case RPORT_ST_PRLI:
102 + case RPORT_ST_LOGO:
103 + rdata->event = RPORT_EV_FAILED;
104 + queue_work(rport_event_queue,
105 + &rdata->event_work);
108 + fc_rport_enter_ready(rport);
110 + case RPORT_ST_NONE:
111 + case RPORT_ST_READY:
112 + case RPORT_ST_INIT:
118 + * fc_rport_error_retry - Error handler when retries are desired
119 + * @rport: The fc_rport object
120 + * @fp: The frame pointer
122 + * If the error was an exchange timeout retry immediately,
123 + * otherwise wait for E_D_TOV.
125 + * Locking Note: The rport lock is expected to be held before
126 + * calling this routine
128 +static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp)
130 + struct fc_rport_libfc_priv *rdata = rport->dd_data;
131 + unsigned long delay = FC_DEF_E_D_TOV;
133 + /* make sure this isn't an FC_EX_CLOSED error, never retry those */
134 + if (PTR_ERR(fp) == -FC_EX_CLOSED)
135 + return fc_rport_error(rport, fp);
137 + if (rdata->retries < rdata->local_port->max_retry_count) {
138 + FC_DEBUG_RPORT("Error %ld in state %s, retrying\n",
139 + PTR_ERR(fp), fc_rport_state(rport));
141 + /* no additional delay on exchange timeouts */
142 + if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
144 + get_device(&rport->dev);
145 + schedule_delayed_work(&rdata->retry_work, delay);
149 + return fc_rport_error(rport, fp);
153 @@ -490,7 +507,7 @@ static void fc_rport_plogi_resp(struct f
157 - fc_rport_error(rport, fp);
158 + fc_rport_error_retry(rport, fp);
162 @@ -522,7 +539,7 @@ static void fc_rport_plogi_resp(struct f
164 fc_rport_enter_prli(rport);
166 - fc_rport_error(rport, fp);
167 + fc_rport_error_retry(rport, fp);
171 @@ -552,14 +569,14 @@ static void fc_rport_enter_plogi(struct
172 rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
173 fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
175 - fc_rport_error(rport, fp);
176 + fc_rport_error_retry(rport, fp);
179 rdata->e_d_tov = lport->e_d_tov;
181 if (!lport->tt.elsct_send(lport, rport, fp, ELS_PLOGI,
182 fc_rport_plogi_resp, rport, lport->e_d_tov))
183 - fc_rport_error(rport, fp);
184 + fc_rport_error_retry(rport, fp);
186 get_device(&rport->dev);
188 @@ -599,7 +616,7 @@ static void fc_rport_prli_resp(struct fc
192 - fc_rport_error(rport, fp);
193 + fc_rport_error_retry(rport, fp);
197 @@ -657,7 +674,7 @@ static void fc_rport_logo_resp(struct fc
201 - fc_rport_error(rport, fp);
202 + fc_rport_error_retry(rport, fp);
206 @@ -707,13 +724,13 @@ static void fc_rport_enter_prli(struct f
208 fp = fc_frame_alloc(lport, sizeof(*pp));
210 - fc_rport_error(rport, fp);
211 + fc_rport_error_retry(rport, fp);
215 if (!lport->tt.elsct_send(lport, rport, fp, ELS_PRLI,
216 fc_rport_prli_resp, rport, lport->e_d_tov))
217 - fc_rport_error(rport, fp);
218 + fc_rport_error_retry(rport, fp);
220 get_device(&rport->dev);
222 @@ -804,13 +821,13 @@ static void fc_rport_enter_rtv(struct fc
224 fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv));
226 - fc_rport_error(rport, fp);
227 + fc_rport_error_retry(rport, fp);
231 if (!lport->tt.elsct_send(lport, rport, fp, ELS_RTV,
232 fc_rport_rtv_resp, rport, lport->e_d_tov))
233 - fc_rport_error(rport, fp);
234 + fc_rport_error_retry(rport, fp);
236 get_device(&rport->dev);
238 @@ -835,13 +852,13 @@ static void fc_rport_enter_logo(struct f
240 fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo));
242 - fc_rport_error(rport, fp);
243 + fc_rport_error_retry(rport, fp);
247 if (!lport->tt.elsct_send(lport, rport, fp, ELS_LOGO,
248 fc_rport_logo_resp, rport, lport->e_d_tov))
249 - fc_rport_error(rport, fp);
250 + fc_rport_error_retry(rport, fp);
252 get_device(&rport->dev);
254 --- a/include/scsi/fc/fc_fs.h
255 +++ b/include/scsi/fc/fc_fs.h
256 @@ -337,4 +337,9 @@ enum fc_pf_rjt_reason {
257 FC_RJT_VENDOR = 0xff, /* vendor specific reject */
260 +/* default timeout values */
262 +#define FC_DEF_E_D_TOV 2000UL
263 +#define FC_DEF_R_A_TOV 10000UL
265 #endif /* _FC_FS_H_ */