]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.drivers/libfc_rport.diff
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.drivers / libfc_rport.diff
CommitLineData
4d1e5b62
AF
1From: Chris Leech <christopher.leech@intel.com>
2Subject: libfc: rport retry on LS_RJT from certain ELS
3Patch-mainline: 6147a1194ba86af4266f36c9522a7b0040af98fe
4References: bnc #468054
5
6This allows any rport ELS to retry on LS_RJT.
7
8The rport error handling would only retry on resource allocation failures
9and exchange timeouts. I have a target that will occasionally reject PLOGI
10when we do a quick LOGO/PLOGI. When a critical ELS was rejected, libfc would
11fail silently leaving the rport in a dead state.
12
13The retry count and delay are managed by fc_rport_error_retry. If the retry
14count is exceeded fc_rport_error will be called. When retrying is not the
15correct course of action, fc_rport_error can be called directly.
16
17Signed-off-by: Chris Leech <christopher.leech@intel.com>
18Acked-by: Bernhard Walle <bwalle@suse.de>
19---
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(-)
24
25--- a/drivers/scsi/libfc/fc_exch.c
26+++ b/drivers/scsi/libfc/fc_exch.c
27@@ -32,8 +32,6 @@
28 #include <scsi/libfc.h>
29 #include <scsi/fc_encode.h>
30
31-#define FC_DEF_R_A_TOV (10 * 1000) /* resource allocation timeout */
32-
33 /*
34 * fc_exch_debug can be set in debugger or at compile time to get more logs.
35 */
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 *);
44
45 static const char *fc_rport_state_names[] = {
46@@ -405,55 +406,71 @@ static void fc_rport_timeout(struct work
47 }
48
49 /**
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
54 *
55- * If the error was caused by a resource allocation failure
56- * then wait for half a second and retry, otherwise retry
57- * immediately.
58- *
59 * Locking Note: The rport lock is expected to be held before
60 * calling this routine
61 */
62 static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
63 {
64 struct fc_rport_libfc_priv *rdata = rport->dd_data;
65- unsigned long delay = 0;
66
67 FC_DEBUG_RPORT("Error %ld in state %s, retries %d\n",
68 PTR_ERR(fp), fc_rport_state(rport), rdata->retries);
69
70- if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
71- /*
72- * Memory allocation failure, or the exchange timed out.
73- * Retry after delay
74- */
75- if (rdata->retries < rdata->local_port->max_retry_count) {
76- rdata->retries++;
77- if (!fp)
78- delay = msecs_to_jiffies(500);
79- get_device(&rport->dev);
80- schedule_delayed_work(&rdata->retry_work, delay);
81- } else {
82- switch (rdata->rp_state) {
83- case RPORT_ST_PLOGI:
84- case RPORT_ST_PRLI:
85- case RPORT_ST_LOGO:
86- rdata->event = RPORT_EV_FAILED;
87- queue_work(rport_event_queue,
88- &rdata->event_work);
89- break;
90- case RPORT_ST_RTV:
91- fc_rport_enter_ready(rport);
92- break;
93- case RPORT_ST_NONE:
94- case RPORT_ST_READY:
95- case RPORT_ST_INIT:
96- break;
97- }
98- }
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);
106+ break;
107+ case RPORT_ST_RTV:
108+ fc_rport_enter_ready(rport);
109+ break;
110+ case RPORT_ST_NONE:
111+ case RPORT_ST_READY:
112+ case RPORT_ST_INIT:
113+ break;
114+ }
115+}
116+
117+/**
118+ * fc_rport_error_retry - Error handler when retries are desired
119+ * @rport: The fc_rport object
120+ * @fp: The frame pointer
121+ *
122+ * If the error was an exchange timeout retry immediately,
123+ * otherwise wait for E_D_TOV.
124+ *
125+ * Locking Note: The rport lock is expected to be held before
126+ * calling this routine
127+ */
128+static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp)
129+{
130+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
131+ unsigned long delay = FC_DEF_E_D_TOV;
132+
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);
136+
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));
140+ rdata->retries++;
141+ /* no additional delay on exchange timeouts */
142+ if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
143+ delay = 0;
144+ get_device(&rport->dev);
145+ schedule_delayed_work(&rdata->retry_work, delay);
146+ return;
147 }
148+
149+ return fc_rport_error(rport, fp);
150 }
151
152 /**
153@@ -490,7 +507,7 @@ static void fc_rport_plogi_resp(struct f
154 }
155
156 if (IS_ERR(fp)) {
157- fc_rport_error(rport, fp);
158+ fc_rport_error_retry(rport, fp);
159 goto err;
160 }
161
162@@ -522,7 +539,7 @@ static void fc_rport_plogi_resp(struct f
163 else
164 fc_rport_enter_prli(rport);
165 } else
166- fc_rport_error(rport, fp);
167+ fc_rport_error_retry(rport, fp);
168
169 out:
170 fc_frame_free(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));
174 if (!fp) {
175- fc_rport_error(rport, fp);
176+ fc_rport_error_retry(rport, fp);
177 return;
178 }
179 rdata->e_d_tov = lport->e_d_tov;
180
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);
185 else
186 get_device(&rport->dev);
187 }
188@@ -599,7 +616,7 @@ static void fc_rport_prli_resp(struct fc
189 }
190
191 if (IS_ERR(fp)) {
192- fc_rport_error(rport, fp);
193+ fc_rport_error_retry(rport, fp);
194 goto err;
195 }
196
197@@ -657,7 +674,7 @@ static void fc_rport_logo_resp(struct fc
198 rport->port_id);
199
200 if (IS_ERR(fp)) {
201- fc_rport_error(rport, fp);
202+ fc_rport_error_retry(rport, fp);
203 goto err;
204 }
205
206@@ -707,13 +724,13 @@ static void fc_rport_enter_prli(struct f
207
208 fp = fc_frame_alloc(lport, sizeof(*pp));
209 if (!fp) {
210- fc_rport_error(rport, fp);
211+ fc_rport_error_retry(rport, fp);
212 return;
213 }
214
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);
219 else
220 get_device(&rport->dev);
221 }
222@@ -804,13 +821,13 @@ static void fc_rport_enter_rtv(struct fc
223
224 fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv));
225 if (!fp) {
226- fc_rport_error(rport, fp);
227+ fc_rport_error_retry(rport, fp);
228 return;
229 }
230
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);
235 else
236 get_device(&rport->dev);
237 }
238@@ -835,13 +852,13 @@ static void fc_rport_enter_logo(struct f
239
240 fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo));
241 if (!fp) {
242- fc_rport_error(rport, fp);
243+ fc_rport_error_retry(rport, fp);
244 return;
245 }
246
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);
251 else
252 get_device(&rport->dev);
253 }
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 */
258 };
259
260+/* default timeout values */
261+
262+#define FC_DEF_E_D_TOV 2000UL
263+#define FC_DEF_R_A_TOV 10000UL
264+
265 #endif /* _FC_FS_H_ */