]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.arch/s390-07-02-zfcp-unchained-fsf.diff
Add a patch to fix Intel E100 wake-on-lan problems.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / s390-07-02-zfcp-unchained-fsf.diff
1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: zfcp: Add support for unchained FSF requests
3 References: bnc#464466
4
5 Symptom: On a z900 zfcp loops in error recovery.
6 Problem: The z900 requires support for unchained FSF requests for
7 CT and ELS requests. The chained format triggers the ERP
8 from the qdio error handler.
9 Solution: Check the hardware feature flag and send unchained CT
10 and ELS requests if chaining is not support. Adapt the
11 size of the GPN_FT request as necessary and add debug data
12 and a warning, in case the CT request hits a limit.
13
14 Acked-by: John Jolly <jjolly@suse.de>
15 ---
16 Documentation/kmsg/s390/zfcp | 16 ++++++++++++
17 drivers/s390/scsi/zfcp_dbf.c | 2 +
18 drivers/s390/scsi/zfcp_dbf.h | 1
19 drivers/s390/scsi/zfcp_def.h | 9 -------
20 drivers/s390/scsi/zfcp_fc.c | 55 ++++++++++++++++++++++++-------------------
21 drivers/s390/scsi/zfcp_fsf.c | 32 +++++++++++++++++++------
22 drivers/s390/scsi/zfcp_fsf.h | 2 +
23 7 files changed, 77 insertions(+), 40 deletions(-)
24
25 --- a/drivers/s390/scsi/zfcp_fc.c 2008-12-19 13:36:23.000000000 +0100
26 +++ b/drivers/s390/scsi/zfcp_fc.c 2008-12-19 13:36:27.000000000 +0100
27 @@ -25,9 +25,12 @@ struct gpn_ft_resp_acc {
28 u64 wwpn;
29 } __attribute__ ((packed));
30
31 -#define ZFCP_GPN_FT_ENTRIES ((PAGE_SIZE - sizeof(struct ct_hdr)) \
32 - / sizeof(struct gpn_ft_resp_acc))
33 +#define ZFCP_CT_SIZE_ONE_PAGE (PAGE_SIZE - sizeof(struct ct_hdr))
34 +#define ZFCP_GPN_FT_ENTRIES (ZFCP_CT_SIZE_ONE_PAGE \
35 + / sizeof(struct gpn_ft_resp_acc))
36 #define ZFCP_GPN_FT_BUFFERS 4
37 +#define ZFCP_GPN_FT_MAX_SIZE (ZFCP_GPN_FT_BUFFERS * PAGE_SIZE \
38 + - sizeof(struct ct_hdr))
39 #define ZFCP_GPN_FT_MAX_ENTRIES ZFCP_GPN_FT_BUFFERS * (ZFCP_GPN_FT_ENTRIES + 1)
40
41 struct ct_iu_gpn_ft_resp {
42 @@ -283,8 +286,6 @@ int static zfcp_fc_ns_gid_pn_request(str
43 gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
44 gid_pn->ct.req = &gid_pn->req;
45 gid_pn->ct.resp = &gid_pn->resp;
46 - gid_pn->ct.req_count = 1;
47 - gid_pn->ct.resp_count = 1;
48 sg_init_one(&gid_pn->req, &gid_pn->ct_iu_req,
49 sizeof(struct ct_iu_gid_pn_req));
50 sg_init_one(&gid_pn->resp, &gid_pn->ct_iu_resp,
51 @@ -296,7 +297,7 @@ int static zfcp_fc_ns_gid_pn_request(str
52 gid_pn->ct_iu_req.header.gs_subtype = ZFCP_CT_NAME_SERVER;
53 gid_pn->ct_iu_req.header.options = ZFCP_CT_SYNCHRONOUS;
54 gid_pn->ct_iu_req.header.cmd_rsp_code = ZFCP_CT_GID_PN;
55 - gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE;
56 + gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_SIZE_ONE_PAGE / 4;
57 gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn;
58
59 init_completion(&compl_rec.done);
60 @@ -406,8 +407,6 @@ static int zfcp_fc_adisc(struct zfcp_por
61 sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc,
62 sizeof(struct zfcp_ls_adisc));
63
64 - adisc->els.req_count = 1;
65 - adisc->els.resp_count = 1;
66 adisc->els.adapter = adapter;
67 adisc->els.port = port;
68 adisc->els.d_id = port->d_id;
69 @@ -447,17 +446,17 @@ void zfcp_test_link(struct zfcp_port *po
70 zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
71 }
72
73 -static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft)
74 +static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num)
75 {
76 struct scatterlist *sg = &gpn_ft->sg_req;
77
78 kfree(sg_virt(sg)); /* free request buffer */
79 - zfcp_sg_free_table(gpn_ft->sg_resp, ZFCP_GPN_FT_BUFFERS);
80 + zfcp_sg_free_table(gpn_ft->sg_resp, buf_num);
81
82 kfree(gpn_ft);
83 }
84
85 -static struct zfcp_gpn_ft *zfcp_alloc_sg_env(void)
86 +static struct zfcp_gpn_ft *zfcp_alloc_sg_env(int buf_num)
87 {
88 struct zfcp_gpn_ft *gpn_ft;
89 struct ct_iu_gpn_ft_req *req;
90 @@ -474,8 +473,8 @@ static struct zfcp_gpn_ft *zfcp_alloc_sg
91 }
92 sg_init_one(&gpn_ft->sg_req, req, sizeof(*req));
93
94 - if (zfcp_sg_setup_table(gpn_ft->sg_resp, ZFCP_GPN_FT_BUFFERS)) {
95 - zfcp_free_sg_env(gpn_ft);
96 + if (zfcp_sg_setup_table(gpn_ft->sg_resp, buf_num)) {
97 + zfcp_free_sg_env(gpn_ft, buf_num);
98 gpn_ft = NULL;
99 }
100 out:
101 @@ -484,7 +483,8 @@ out:
102
103
104 static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
105 - struct zfcp_adapter *adapter)
106 + struct zfcp_adapter *adapter,
107 + int max_bytes)
108 {
109 struct zfcp_send_ct *ct = &gpn_ft->ct;
110 struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
111 @@ -497,8 +497,7 @@ static int zfcp_scan_issue_gpn_ft(struct
112 req->header.gs_subtype = ZFCP_CT_NAME_SERVER;
113 req->header.options = ZFCP_CT_SYNCHRONOUS;
114 req->header.cmd_rsp_code = ZFCP_CT_GPN_FT;
115 - req->header.max_res_size = (sizeof(struct gpn_ft_resp_acc) *
116 - (ZFCP_GPN_FT_MAX_ENTRIES - 1)) >> 2;
117 + req->header.max_res_size = max_bytes / 4;
118 req->flags = 0;
119 req->domain_id_scope = 0;
120 req->area_id_scope = 0;
121 @@ -511,8 +510,6 @@ static int zfcp_scan_issue_gpn_ft(struct
122 ct->timeout = 10;
123 ct->req = &gpn_ft->sg_req;
124 ct->resp = gpn_ft->sg_resp;
125 - ct->req_count = 1;
126 - ct->resp_count = ZFCP_GPN_FT_BUFFERS;
127
128 init_completion(&compl_rec.done);
129 compl_rec.handler = NULL;
130 @@ -539,7 +536,7 @@ static void zfcp_validate_port(struct zf
131 zfcp_port_dequeue(port);
132 }
133
134 -static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
135 +static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
136 {
137 struct zfcp_send_ct *ct = &gpn_ft->ct;
138 struct scatterlist *sg = gpn_ft->sg_resp;
139 @@ -559,13 +556,17 @@ static int zfcp_scan_eval_gpn_ft(struct
140 return -EIO;
141 }
142
143 - if (hdr->max_res_size)
144 + if (hdr->max_res_size) {
145 + dev_warn(&adapter->ccw_device->dev,
146 + "The name server reported %d words residual data\n",
147 + hdr->max_res_size);
148 return -E2BIG;
149 + }
150
151 down(&zfcp_data.config_sema);
152
153 /* first entry is the header */
154 - for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES && !last; x++) {
155 + for (x = 1; x < max_entries && !last; x++) {
156 if (x % (ZFCP_GPN_FT_ENTRIES + 1))
157 acc++;
158 else
159 @@ -611,6 +612,12 @@ int zfcp_scan_ports(struct zfcp_adapter
160 {
161 int ret, i;
162 struct zfcp_gpn_ft *gpn_ft;
163 + int chain, max_entries, buf_num, max_bytes;
164 +
165 + chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS;
166 + buf_num = chain ? ZFCP_GPN_FT_BUFFERS : 1;
167 + max_entries = chain ? ZFCP_GPN_FT_MAX_ENTRIES : ZFCP_GPN_FT_ENTRIES;
168 + max_bytes = chain ? ZFCP_GPN_FT_MAX_SIZE : ZFCP_CT_SIZE_ONE_PAGE;
169
170 zfcp_erp_wait(adapter); /* wait until adapter is finished with ERP */
171 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
172 @@ -620,23 +627,23 @@ int zfcp_scan_ports(struct zfcp_adapter
173 if (ret)
174 return ret;
175
176 - gpn_ft = zfcp_alloc_sg_env();
177 + gpn_ft = zfcp_alloc_sg_env(buf_num);
178 if (!gpn_ft) {
179 ret = -ENOMEM;
180 goto out;
181 }
182
183 for (i = 0; i < 3; i++) {
184 - ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter);
185 + ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter, max_bytes);
186 if (!ret) {
187 - ret = zfcp_scan_eval_gpn_ft(gpn_ft);
188 + ret = zfcp_scan_eval_gpn_ft(gpn_ft, max_entries);
189 if (ret == -EAGAIN)
190 ssleep(1);
191 else
192 break;
193 }
194 }
195 - zfcp_free_sg_env(gpn_ft);
196 + zfcp_free_sg_env(gpn_ft, buf_num);
197 out:
198 zfcp_wka_port_put(&adapter->nsp);
199 return ret;
200 --- a/drivers/s390/scsi/zfcp_fsf.h 2008-12-19 13:36:23.000000000 +0100
201 +++ b/drivers/s390/scsi/zfcp_fsf.h 2008-12-19 13:36:27.000000000 +0100
202 @@ -164,6 +164,7 @@
203 #define FSF_FEATURE_LUN_SHARING 0x00000004
204 #define FSF_FEATURE_NOTIFICATION_LOST 0x00000008
205 #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
206 +#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
207 #define FSF_FEATURE_UPDATE_ALERT 0x00000100
208 #define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
209
210 @@ -322,6 +323,7 @@ struct fsf_nport_serv_param {
211 u8 vendor_version_level[16];
212 } __attribute__ ((packed));
213
214 +#define FSF_PLOGI_MIN_LEN 112
215 struct fsf_plogi {
216 u32 code;
217 struct fsf_nport_serv_param serv_param;
218 --- a/drivers/s390/scsi/zfcp_fsf.c 2008-12-19 13:36:23.000000000 +0100
219 +++ b/drivers/s390/scsi/zfcp_fsf.c 2008-12-19 13:36:27.000000000 +0100
220 @@ -1012,12 +1012,29 @@ skip_fsfstatus:
221 send_ct->handler(send_ct->handler_data);
222 }
223
224 -static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req,
225 - struct scatterlist *sg_req,
226 - struct scatterlist *sg_resp, int max_sbals)
227 +static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
228 + struct scatterlist *sg_req,
229 + struct scatterlist *sg_resp,
230 + int max_sbals)
231 {
232 + struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(req);
233 + u32 feat = req->adapter->adapter_features;
234 int bytes;
235
236 + if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
237 + if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE ||
238 + !sg_is_last(sg_req) || !sg_is_last(sg_resp))
239 + return -EOPNOTSUPP;
240 +
241 + sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
242 + sbale[2].addr = sg_virt(sg_req);
243 + sbale[2].length = sg_req->length;
244 + sbale[3].addr = sg_virt(sg_resp);
245 + sbale[3].length = sg_resp->length;
246 + sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
247 + return 0;
248 + }
249 +
250 bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
251 sg_req, max_sbals);
252 if (bytes <= 0)
253 @@ -1059,8 +1076,8 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct
254 goto out;
255 }
256
257 - ret = zfcp_fsf_setup_sbals(req, ct->req, ct->resp,
258 - FSF_MAX_SBALS_PER_REQ);
259 + ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp,
260 + FSF_MAX_SBALS_PER_REQ);
261 if (ret)
262 goto failed_send;
263
264 @@ -1170,7 +1187,7 @@ int zfcp_fsf_send_els(struct zfcp_send_e
265 goto out;
266 }
267
268 - ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, 2);
269 + ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
270
271 if (ret)
272 goto failed_send;
273 @@ -1433,7 +1450,8 @@ static void zfcp_fsf_open_port_handler(s
274 * Alternately, an ADISC/PDISC ELS should suffice, as well.
275 */
276 plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
277 - if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) {
278 + if (req->qtcb->bottom.support.els1_length >=
279 + FSF_PLOGI_MIN_LEN) {
280 if (plogi->serv_param.wwpn != port->wwpn)
281 atomic_clear_mask(ZFCP_STATUS_PORT_DID_DID,
282 &port->status);
283 --- a/Documentation/kmsg/s390/zfcp 2008-12-19 13:36:23.000000000 +0100
284 +++ b/Documentation/kmsg/s390/zfcp 2008-12-19 13:36:27.000000000 +0100
285 @@ -813,3 +813,19 @@
286 * problem persists, gather Linux debug data, collect the FCP adapter
287 * hardware logs, and report the problem to your support organization.
288 */
289 +
290 +/*?
291 + * Text: "%s: The name server reported %d words residual data\n"
292 + * Severity: Warning
293 + * Parameter:
294 + * @1: bus ID of the zfcp device
295 + * @2: number of words in residual data
296 + * Description:
297 + * The fibre channel name server sent too much information about remote ports.
298 + * The zfcp device driver did not receive sufficient information to attach all
299 + * available remote ports in the SAN.
300 + * User action:
301 + * Verify that you are running the latest firmware level on the FCP
302 + * adapter. Check your SAN setup and consider reducing the number of ports
303 + * visible to the FCP adapter by using more restrictive zoning in the SAN.
304 + */
305 --- a/drivers/s390/scsi/zfcp_dbf.c 2008-12-19 13:36:23.000000000 +0100
306 +++ b/drivers/s390/scsi/zfcp_dbf.c 2008-12-19 13:36:27.000000000 +0100
307 @@ -935,6 +935,7 @@ void zfcp_san_dbf_event_ct_response(stru
308 rct->reason_code = hdr->reason_code;
309 rct->expl = hdr->reason_code_expl;
310 rct->vendor_unique = hdr->vendor_unique;
311 + rct->max_res_size = hdr->max_res_size;
312 rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr),
313 ZFCP_DBF_SAN_MAX_PAYLOAD);
314 debug_event(adapter->san_dbf, level, r, sizeof(*r));
315 @@ -1042,6 +1043,7 @@ static int zfcp_san_dbf_view_format(debu
316 zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code);
317 zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl);
318 zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique);
319 + zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size);
320 } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 ||
321 strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 ||
322 strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) {
323 --- a/drivers/s390/scsi/zfcp_dbf.h 2008-12-19 13:36:23.000000000 +0100
324 +++ b/drivers/s390/scsi/zfcp_dbf.h 2008-12-19 13:36:27.000000000 +0100
325 @@ -171,6 +171,7 @@ struct zfcp_san_dbf_record_ct_response {
326 u8 reason_code;
327 u8 expl;
328 u8 vendor_unique;
329 + u16 max_res_size;
330 u32 len;
331 } __attribute__ ((packed));
332
333 --- a/drivers/s390/scsi/zfcp_def.h 2008-12-19 13:36:23.000000000 +0100
334 +++ b/drivers/s390/scsi/zfcp_def.h 2008-12-19 13:36:27.000000000 +0100
335 @@ -210,7 +210,6 @@ struct zfcp_ls_adisc {
336 #define ZFCP_CT_UNABLE_TO_PERFORM_CMD 0x09
337 #define ZFCP_CT_GID_PN 0x0121
338 #define ZFCP_CT_GPN_FT 0x0172
339 -#define ZFCP_CT_MAX_SIZE 0x1020
340 #define ZFCP_CT_ACCEPT 0x8002
341 #define ZFCP_CT_REJECT 0x8001
342
343 @@ -339,8 +338,6 @@ struct ct_iu_gid_pn_resp {
344 * @wka_port: port where the request is sent to
345 * @req: scatter-gather list for request
346 * @resp: scatter-gather list for response
347 - * @req_count: number of elements in request scatter-gather list
348 - * @resp_count: number of elements in response scatter-gather list
349 * @handler: handler function (called for response to the request)
350 * @handler_data: data passed to handler function
351 * @timeout: FSF timeout for this request
352 @@ -351,8 +348,6 @@ struct zfcp_send_ct {
353 struct zfcp_wka_port *wka_port;
354 struct scatterlist *req;
355 struct scatterlist *resp;
356 - unsigned int req_count;
357 - unsigned int resp_count;
358 void (*handler)(unsigned long);
359 unsigned long handler_data;
360 int timeout;
361 @@ -377,8 +372,6 @@ struct zfcp_gid_pn_data {
362 * @d_id: destiniation id of port where request is sent to
363 * @req: scatter-gather list for request
364 * @resp: scatter-gather list for response
365 - * @req_count: number of elements in request scatter-gather list
366 - * @resp_count: number of elements in response scatter-gather list
367 * @handler: handler function (called for response to the request)
368 * @handler_data: data passed to handler function
369 * @completion: completion for synchronization purposes
370 @@ -391,8 +384,6 @@ struct zfcp_send_els {
371 u32 d_id;
372 struct scatterlist *req;
373 struct scatterlist *resp;
374 - unsigned int req_count;
375 - unsigned int resp_count;
376 void (*handler)(unsigned long);
377 unsigned long handler_data;
378 struct completion *completion;