]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.drivers/libfc_rport.diff
Move xen patchset to new version's subdir.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / libfc_rport.diff
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
5
6 This allows any rport ELS to retry on LS_RJT.
7
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.
12
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.
16
17 Signed-off-by: Chris Leech <christopher.leech@intel.com>
18 Acked-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_ */