Commit | Line | Data |
---|---|---|
8a36e453 | 1 | /* |
553448f6 | 2 | * zfcp device driver |
8a36e453 | 3 | * |
553448f6 | 4 | * Debug traces for zfcp. |
8a36e453 | 5 | * |
beb0b6c9 | 6 | * Copyright IBM Corp. 2002, 2016 |
8a36e453 MS |
7 | */ |
8 | ||
ecf39d42 CS |
9 | #define KMSG_COMPONENT "zfcp" |
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
11 | ||
3a4c5d59 | 12 | #include <linux/module.h> |
8a36e453 | 13 | #include <linux/ctype.h> |
5a0e3ad6 | 14 | #include <linux/slab.h> |
364c8558 | 15 | #include <asm/debug.h> |
d46f384a | 16 | #include "zfcp_dbf.h" |
8a36e453 | 17 | #include "zfcp_ext.h" |
bd0072ec | 18 | #include "zfcp_fc.h" |
8a36e453 MS |
19 | |
20 | static u32 dbfsize = 4; | |
21 | ||
22 | module_param(dbfsize, uint, 0400); | |
23 | MODULE_PARM_DESC(dbfsize, | |
24 | "number of pages for each debug feature area (default 4)"); | |
25 | ||
a54ca0f6 | 26 | static inline unsigned int zfcp_dbf_plen(unsigned int offset) |
c15450e3 | 27 | { |
a54ca0f6 SS |
28 | return sizeof(struct zfcp_dbf_pay) + offset - ZFCP_DBF_PAY_MAX_REC; |
29 | } | |
30 | ||
31 | static inline | |
32 | void zfcp_dbf_pl_write(struct zfcp_dbf *dbf, void *data, u16 length, char *area, | |
33 | u64 req_id) | |
34 | { | |
35 | struct zfcp_dbf_pay *pl = &dbf->pay_buf; | |
36 | u16 offset = 0, rec_length; | |
37 | ||
38 | spin_lock(&dbf->pay_lock); | |
39 | memset(pl, 0, sizeof(*pl)); | |
40 | pl->fsf_req_id = req_id; | |
41 | memcpy(pl->area, area, ZFCP_DBF_TAG_LEN); | |
42 | ||
43 | while (offset < length) { | |
44 | rec_length = min((u16) ZFCP_DBF_PAY_MAX_REC, | |
45 | (u16) (length - offset)); | |
46 | memcpy(pl->data, data + offset, rec_length); | |
47 | debug_event(dbf->pay, 1, pl, zfcp_dbf_plen(rec_length)); | |
48 | ||
49 | offset += rec_length; | |
50 | pl->counter++; | |
c15450e3 | 51 | } |
a54ca0f6 SS |
52 | |
53 | spin_unlock(&dbf->pay_lock); | |
c15450e3 MP |
54 | } |
55 | ||
a54ca0f6 SS |
56 | /** |
57 | * zfcp_dbf_hba_fsf_res - trace event for fsf responses | |
58 | * @tag: tag indicating which kind of unsolicited status has been received | |
59 | * @req: request for which a response was received | |
60 | */ | |
909987d4 | 61 | void zfcp_dbf_hba_fsf_res(char *tag, int level, struct zfcp_fsf_req *req) |
8a36e453 | 62 | { |
a54ca0f6 SS |
63 | struct zfcp_dbf *dbf = req->adapter->dbf; |
64 | struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix; | |
65 | struct fsf_qtcb_header *q_head = &req->qtcb->header; | |
66 | struct zfcp_dbf_hba *rec = &dbf->hba_buf; | |
8a36e453 MS |
67 | unsigned long flags; |
68 | ||
5771710b | 69 | spin_lock_irqsave(&dbf->hba_lock, flags); |
6bc473dd | 70 | memset(rec, 0, sizeof(*rec)); |
8a36e453 | 71 | |
a54ca0f6 SS |
72 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
73 | rec->id = ZFCP_DBF_HBA_RES; | |
74 | rec->fsf_req_id = req->req_id; | |
75 | rec->fsf_req_status = req->status; | |
76 | rec->fsf_cmd = req->fsf_command; | |
77 | rec->fsf_seq_no = req->seq_no; | |
78 | rec->u.res.req_issued = req->issued; | |
79 | rec->u.res.prot_status = q_pref->prot_status; | |
80 | rec->u.res.fsf_status = q_head->fsf_status; | |
8467dd46 SM |
81 | rec->u.res.port_handle = q_head->port_handle; |
82 | rec->u.res.lun_handle = q_head->lun_handle; | |
a54ca0f6 SS |
83 | |
84 | memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual, | |
85 | FSF_PROT_STATUS_QUAL_SIZE); | |
86 | memcpy(rec->u.res.fsf_status_qual, &q_head->fsf_status_qual, | |
87 | FSF_STATUS_QUALIFIER_SIZE); | |
88 | ||
89 | if (req->fsf_command != FSF_QTCB_FCP_CMND) { | |
90 | rec->pl_len = q_head->log_length; | |
91 | zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start, | |
92 | rec->pl_len, "fsf_res", req->req_id); | |
8a36e453 MS |
93 | } |
94 | ||
909987d4 | 95 | debug_event(dbf->hba, level, rec, sizeof(*rec)); |
5771710b | 96 | spin_unlock_irqrestore(&dbf->hba_lock, flags); |
8a36e453 MS |
97 | } |
98 | ||
bfab1637 | 99 | /** |
a54ca0f6 SS |
100 | * zfcp_dbf_hba_fsf_uss - trace event for an unsolicited status buffer |
101 | * @tag: tag indicating which kind of unsolicited status has been received | |
102 | * @req: request providing the unsolicited status | |
bfab1637 | 103 | */ |
a54ca0f6 | 104 | void zfcp_dbf_hba_fsf_uss(char *tag, struct zfcp_fsf_req *req) |
8a36e453 | 105 | { |
a54ca0f6 SS |
106 | struct zfcp_dbf *dbf = req->adapter->dbf; |
107 | struct fsf_status_read_buffer *srb = req->data; | |
108 | struct zfcp_dbf_hba *rec = &dbf->hba_buf; | |
8a36e453 MS |
109 | unsigned long flags; |
110 | ||
5771710b | 111 | spin_lock_irqsave(&dbf->hba_lock, flags); |
a54ca0f6 SS |
112 | memset(rec, 0, sizeof(*rec)); |
113 | ||
114 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); | |
115 | rec->id = ZFCP_DBF_HBA_USS; | |
116 | rec->fsf_req_id = req->req_id; | |
117 | rec->fsf_req_status = req->status; | |
118 | rec->fsf_cmd = req->fsf_command; | |
119 | ||
120 | if (!srb) | |
121 | goto log; | |
122 | ||
123 | rec->u.uss.status_type = srb->status_type; | |
124 | rec->u.uss.status_subtype = srb->status_subtype; | |
125 | rec->u.uss.d_id = ntoh24(srb->d_id); | |
126 | rec->u.uss.lun = srb->fcp_lun; | |
127 | memcpy(&rec->u.uss.queue_designator, &srb->queue_designator, | |
128 | sizeof(rec->u.uss.queue_designator)); | |
129 | ||
130 | /* status read buffer payload length */ | |
131 | rec->pl_len = (!srb->length) ? 0 : srb->length - | |
132 | offsetof(struct fsf_status_read_buffer, payload); | |
133 | ||
134 | if (rec->pl_len) | |
135 | zfcp_dbf_pl_write(dbf, srb->payload.data, rec->pl_len, | |
136 | "fsf_uss", req->req_id); | |
137 | log: | |
138 | debug_event(dbf->hba, 2, rec, sizeof(*rec)); | |
5771710b | 139 | spin_unlock_irqrestore(&dbf->hba_lock, flags); |
8a36e453 MS |
140 | } |
141 | ||
57069386 | 142 | /** |
a54ca0f6 SS |
143 | * zfcp_dbf_hba_bit_err - trace event for bit error conditions |
144 | * @tag: tag indicating which kind of unsolicited status has been received | |
145 | * @req: request which caused the bit_error condition | |
57069386 | 146 | */ |
a54ca0f6 | 147 | void zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req) |
57069386 | 148 | { |
a54ca0f6 SS |
149 | struct zfcp_dbf *dbf = req->adapter->dbf; |
150 | struct zfcp_dbf_hba *rec = &dbf->hba_buf; | |
57069386 | 151 | struct fsf_status_read_buffer *sr_buf = req->data; |
57069386 SS |
152 | unsigned long flags; |
153 | ||
5771710b | 154 | spin_lock_irqsave(&dbf->hba_lock, flags); |
a54ca0f6 | 155 | memset(rec, 0, sizeof(*rec)); |
8a36e453 | 156 | |
a54ca0f6 SS |
157 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
158 | rec->id = ZFCP_DBF_HBA_BIT; | |
159 | rec->fsf_req_id = req->req_id; | |
160 | rec->fsf_req_status = req->status; | |
161 | rec->fsf_cmd = req->fsf_command; | |
162 | memcpy(&rec->u.be, &sr_buf->payload.bit_error, | |
163 | sizeof(struct fsf_bit_error_payload)); | |
164 | ||
165 | debug_event(dbf->hba, 1, rec, sizeof(*rec)); | |
166 | spin_unlock_irqrestore(&dbf->hba_lock, flags); | |
8a36e453 MS |
167 | } |
168 | ||
86a9668a SS |
169 | /** |
170 | * zfcp_dbf_hba_def_err - trace event for deferred error messages | |
171 | * @adapter: pointer to struct zfcp_adapter | |
172 | * @req_id: request id which caused the deferred error message | |
173 | * @scount: number of sbals incl. the signaling sbal | |
174 | * @pl: array of all involved sbals | |
175 | */ | |
176 | void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, | |
177 | void **pl) | |
178 | { | |
179 | struct zfcp_dbf *dbf = adapter->dbf; | |
180 | struct zfcp_dbf_pay *payload = &dbf->pay_buf; | |
181 | unsigned long flags; | |
182 | u16 length; | |
183 | ||
184 | if (!pl) | |
185 | return; | |
186 | ||
187 | spin_lock_irqsave(&dbf->pay_lock, flags); | |
188 | memset(payload, 0, sizeof(*payload)); | |
189 | ||
190 | memcpy(payload->area, "def_err", 7); | |
191 | payload->fsf_req_id = req_id; | |
192 | payload->counter = 0; | |
193 | length = min((u16)sizeof(struct qdio_buffer), | |
194 | (u16)ZFCP_DBF_PAY_MAX_REC); | |
195 | ||
01e60527 | 196 | while (payload->counter < scount && (char *)pl[payload->counter]) { |
86a9668a SS |
197 | memcpy(payload->data, (char *)pl[payload->counter], length); |
198 | debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length)); | |
199 | payload->counter++; | |
200 | } | |
201 | ||
202 | spin_unlock_irqrestore(&dbf->pay_lock, flags); | |
203 | } | |
204 | ||
cb452149 SM |
205 | /** |
206 | * zfcp_dbf_hba_basic - trace event for basic adapter events | |
207 | * @adapter: pointer to struct zfcp_adapter | |
208 | */ | |
209 | void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter) | |
210 | { | |
211 | struct zfcp_dbf *dbf = adapter->dbf; | |
212 | struct zfcp_dbf_hba *rec = &dbf->hba_buf; | |
213 | unsigned long flags; | |
214 | ||
215 | spin_lock_irqsave(&dbf->hba_lock, flags); | |
216 | memset(rec, 0, sizeof(*rec)); | |
217 | ||
218 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); | |
219 | rec->id = ZFCP_DBF_HBA_BASIC; | |
220 | ||
221 | debug_event(dbf->hba, 1, rec, sizeof(*rec)); | |
222 | spin_unlock_irqrestore(&dbf->hba_lock, flags); | |
223 | } | |
224 | ||
ae0904f6 SS |
225 | static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, |
226 | struct zfcp_adapter *adapter, | |
227 | struct zfcp_port *port, | |
228 | struct scsi_device *sdev) | |
d79a83db | 229 | { |
ae0904f6 SS |
230 | rec->adapter_status = atomic_read(&adapter->status); |
231 | if (port) { | |
232 | rec->port_status = atomic_read(&port->status); | |
233 | rec->wwpn = port->wwpn; | |
234 | rec->d_id = port->d_id; | |
235 | } | |
236 | if (sdev) { | |
237 | rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status); | |
238 | rec->lun = zfcp_scsi_dev_lun(sdev); | |
05307725 SM |
239 | } else |
240 | rec->lun = ZFCP_DBF_INVALID_LUN; | |
d79a83db MP |
241 | } |
242 | ||
348447e8 | 243 | /** |
ae0904f6 SS |
244 | * zfcp_dbf_rec_trig - trace event related to triggered recovery |
245 | * @tag: identifier for event | |
246 | * @adapter: adapter on which the erp_action should run | |
247 | * @port: remote port involved in the erp_action | |
248 | * @sdev: scsi device involved in the erp_action | |
249 | * @want: wanted erp_action | |
250 | * @need: required erp_action | |
251 | * | |
252 | * The adapter->erp_lock has to be held. | |
348447e8 | 253 | */ |
ae0904f6 SS |
254 | void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, |
255 | struct zfcp_port *port, struct scsi_device *sdev, | |
256 | u8 want, u8 need) | |
348447e8 | 257 | { |
ae0904f6 SS |
258 | struct zfcp_dbf *dbf = adapter->dbf; |
259 | struct zfcp_dbf_rec *rec = &dbf->rec_buf; | |
348447e8 | 260 | struct list_head *entry; |
698ec016 MP |
261 | unsigned long flags; |
262 | ||
5771710b | 263 | spin_lock_irqsave(&dbf->rec_lock, flags); |
ae0904f6 | 264 | memset(rec, 0, sizeof(*rec)); |
5771710b | 265 | |
ae0904f6 SS |
266 | rec->id = ZFCP_DBF_REC_TRIG; |
267 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); | |
268 | zfcp_dbf_set_common(rec, adapter, port, sdev); | |
698ec016 | 269 | |
ae0904f6 SS |
270 | list_for_each(entry, &adapter->erp_ready_head) |
271 | rec->u.trig.ready++; | |
698ec016 | 272 | |
ae0904f6 SS |
273 | list_for_each(entry, &adapter->erp_running_head) |
274 | rec->u.trig.running++; | |
698ec016 | 275 | |
ae0904f6 SS |
276 | rec->u.trig.want = want; |
277 | rec->u.trig.need = need; | |
698ec016 | 278 | |
ae0904f6 SS |
279 | debug_event(dbf->rec, 1, rec, sizeof(*rec)); |
280 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | |
698ec016 MP |
281 | } |
282 | ||
ae0904f6 | 283 | |
9467a9b3 | 284 | /** |
1c2287b9 SM |
285 | * zfcp_dbf_rec_run_lvl - trace event related to running recovery |
286 | * @level: trace level to be used for event | |
ae0904f6 SS |
287 | * @tag: identifier for event |
288 | * @erp: erp_action running | |
9467a9b3 | 289 | */ |
1c2287b9 | 290 | void zfcp_dbf_rec_run_lvl(int level, char *tag, struct zfcp_erp_action *erp) |
9467a9b3 | 291 | { |
ae0904f6 SS |
292 | struct zfcp_dbf *dbf = erp->adapter->dbf; |
293 | struct zfcp_dbf_rec *rec = &dbf->rec_buf; | |
9467a9b3 MP |
294 | unsigned long flags; |
295 | ||
5771710b | 296 | spin_lock_irqsave(&dbf->rec_lock, flags); |
ae0904f6 | 297 | memset(rec, 0, sizeof(*rec)); |
9467a9b3 | 298 | |
ae0904f6 SS |
299 | rec->id = ZFCP_DBF_REC_RUN; |
300 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); | |
301 | zfcp_dbf_set_common(rec, erp->adapter, erp->port, erp->sdev); | |
6f4f365e | 302 | |
ae0904f6 SS |
303 | rec->u.run.fsf_req_id = erp->fsf_req_id; |
304 | rec->u.run.rec_status = erp->status; | |
305 | rec->u.run.rec_step = erp->step; | |
306 | rec->u.run.rec_action = erp->action; | |
307 | ||
308 | if (erp->sdev) | |
309 | rec->u.run.rec_count = | |
310 | atomic_read(&sdev_to_zfcp(erp->sdev)->erp_counter); | |
311 | else if (erp->port) | |
312 | rec->u.run.rec_count = atomic_read(&erp->port->erp_counter); | |
313 | else | |
314 | rec->u.run.rec_count = atomic_read(&erp->adapter->erp_counter); | |
315 | ||
1c2287b9 | 316 | debug_event(dbf->rec, level, rec, sizeof(*rec)); |
5771710b | 317 | spin_unlock_irqrestore(&dbf->rec_lock, flags); |
6f4f365e MP |
318 | } |
319 | ||
1c2287b9 SM |
320 | /** |
321 | * zfcp_dbf_rec_run - trace event related to running recovery | |
322 | * @tag: identifier for event | |
323 | * @erp: erp_action running | |
324 | */ | |
325 | void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp) | |
326 | { | |
327 | zfcp_dbf_rec_run_lvl(1, tag, erp); | |
328 | } | |
329 | ||
69169095 SM |
330 | /** |
331 | * zfcp_dbf_rec_run_wka - trace wka port event with info like running recovery | |
332 | * @tag: identifier for event | |
333 | * @wka_port: well known address port | |
334 | * @req_id: request ID to correlate with potential HBA trace record | |
335 | */ | |
336 | void zfcp_dbf_rec_run_wka(char *tag, struct zfcp_fc_wka_port *wka_port, | |
337 | u64 req_id) | |
338 | { | |
339 | struct zfcp_dbf *dbf = wka_port->adapter->dbf; | |
340 | struct zfcp_dbf_rec *rec = &dbf->rec_buf; | |
341 | unsigned long flags; | |
342 | ||
343 | spin_lock_irqsave(&dbf->rec_lock, flags); | |
344 | memset(rec, 0, sizeof(*rec)); | |
345 | ||
346 | rec->id = ZFCP_DBF_REC_RUN; | |
347 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); | |
348 | rec->port_status = wka_port->status; | |
349 | rec->d_id = wka_port->d_id; | |
350 | rec->lun = ZFCP_DBF_INVALID_LUN; | |
351 | ||
352 | rec->u.run.fsf_req_id = req_id; | |
353 | rec->u.run.rec_status = ~0; | |
354 | rec->u.run.rec_step = ~0; | |
355 | rec->u.run.rec_action = ~0; | |
356 | rec->u.run.rec_count = ~0; | |
357 | ||
358 | debug_event(dbf->rec, 1, rec, sizeof(*rec)); | |
359 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | |
360 | } | |
361 | ||
2c55b750 | 362 | static inline |
beb0b6c9 SM |
363 | void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, |
364 | char *paytag, struct scatterlist *sg, u8 id, u16 len, | |
365 | u64 req_id, u32 d_id, u16 cap_len) | |
8a36e453 | 366 | { |
2c55b750 SS |
367 | struct zfcp_dbf_san *rec = &dbf->san_buf; |
368 | u16 rec_len; | |
6bc473dd | 369 | unsigned long flags; |
beb0b6c9 SM |
370 | struct zfcp_dbf_pay *payload = &dbf->pay_buf; |
371 | u16 pay_sum = 0; | |
8a36e453 | 372 | |
5771710b | 373 | spin_lock_irqsave(&dbf->san_lock, flags); |
2c55b750 | 374 | memset(rec, 0, sizeof(*rec)); |
8a36e453 | 375 | |
2c55b750 SS |
376 | rec->id = id; |
377 | rec->fsf_req_id = req_id; | |
378 | rec->d_id = d_id; | |
2c55b750 | 379 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
beb0b6c9 SM |
380 | rec->pl_len = len; /* full length even if we cap pay below */ |
381 | if (!sg) | |
382 | goto out; | |
383 | rec_len = min_t(unsigned int, sg->length, ZFCP_DBF_SAN_MAX_PAYLOAD); | |
384 | memcpy(rec->payload, sg_virt(sg), rec_len); /* part of 1st sg entry */ | |
385 | if (len <= rec_len) | |
386 | goto out; /* skip pay record if full content in rec->payload */ | |
387 | ||
388 | /* if (len > rec_len): | |
389 | * dump data up to cap_len ignoring small duplicate in rec->payload | |
390 | */ | |
7ddb2584 | 391 | spin_lock(&dbf->pay_lock); |
beb0b6c9 SM |
392 | memset(payload, 0, sizeof(*payload)); |
393 | memcpy(payload->area, paytag, ZFCP_DBF_TAG_LEN); | |
394 | payload->fsf_req_id = req_id; | |
395 | payload->counter = 0; | |
396 | for (; sg && pay_sum < cap_len; sg = sg_next(sg)) { | |
397 | u16 pay_len, offset = 0; | |
398 | ||
399 | while (offset < sg->length && pay_sum < cap_len) { | |
400 | pay_len = min((u16)ZFCP_DBF_PAY_MAX_REC, | |
401 | (u16)(sg->length - offset)); | |
402 | /* cap_len <= pay_sum < cap_len+ZFCP_DBF_PAY_MAX_REC */ | |
403 | memcpy(payload->data, sg_virt(sg) + offset, pay_len); | |
404 | debug_event(dbf->pay, 1, payload, | |
405 | zfcp_dbf_plen(pay_len)); | |
406 | payload->counter++; | |
407 | offset += pay_len; | |
408 | pay_sum += pay_len; | |
409 | } | |
410 | } | |
411 | spin_unlock(&dbf->pay_lock); | |
8a36e453 | 412 | |
beb0b6c9 | 413 | out: |
2c55b750 | 414 | debug_event(dbf->san, 1, rec, sizeof(*rec)); |
5771710b | 415 | spin_unlock_irqrestore(&dbf->san_lock, flags); |
8a36e453 MS |
416 | } |
417 | ||
bfab1637 | 418 | /** |
2c55b750 SS |
419 | * zfcp_dbf_san_req - trace event for issued SAN request |
420 | * @tag: indentifier for event | |
421 | * @fsf_req: request containing issued CT data | |
422 | * d_id: destination ID | |
bfab1637 | 423 | */ |
2c55b750 | 424 | void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id) |
8a36e453 | 425 | { |
2c55b750 SS |
426 | struct zfcp_dbf *dbf = fsf->adapter->dbf; |
427 | struct zfcp_fsf_ct_els *ct_els = fsf->data; | |
428 | u16 length; | |
8a36e453 | 429 | |
beb0b6c9 SM |
430 | length = (u16)zfcp_qdio_real_bytes(ct_els->req); |
431 | zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ, | |
432 | length, fsf->req_id, d_id, length); | |
433 | } | |
434 | ||
435 | static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag, | |
436 | struct zfcp_fsf_req *fsf, | |
437 | u16 len) | |
438 | { | |
439 | struct zfcp_fsf_ct_els *ct_els = fsf->data; | |
440 | struct fc_ct_hdr *reqh = sg_virt(ct_els->req); | |
441 | struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1); | |
442 | struct scatterlist *resp_entry = ct_els->resp; | |
443 | struct fc_gpn_ft_resp *acc; | |
444 | int max_entries, x, last = 0; | |
445 | ||
446 | if (!(memcmp(tag, "fsscth2", 7) == 0 | |
447 | && ct_els->d_id == FC_FID_DIR_SERV | |
448 | && reqh->ct_rev == FC_CT_REV | |
449 | && reqh->ct_in_id[0] == 0 | |
450 | && reqh->ct_in_id[1] == 0 | |
451 | && reqh->ct_in_id[2] == 0 | |
452 | && reqh->ct_fs_type == FC_FST_DIR | |
453 | && reqh->ct_fs_subtype == FC_NS_SUBTYPE | |
454 | && reqh->ct_options == 0 | |
455 | && reqh->_ct_resvd1 == 0 | |
456 | && reqh->ct_cmd == FC_NS_GPN_FT | |
457 | /* reqh->ct_mr_size can vary so do not match but read below */ | |
458 | && reqh->_ct_resvd2 == 0 | |
459 | && reqh->ct_reason == 0 | |
460 | && reqh->ct_explan == 0 | |
461 | && reqh->ct_vendor == 0 | |
462 | && reqn->fn_resvd == 0 | |
463 | && reqn->fn_domain_id_scope == 0 | |
464 | && reqn->fn_area_id_scope == 0 | |
465 | && reqn->fn_fc4_type == FC_TYPE_FCP)) | |
466 | return len; /* not GPN_FT response so do not cap */ | |
467 | ||
468 | acc = sg_virt(resp_entry); | |
469 | max_entries = (reqh->ct_mr_size * 4 / sizeof(struct fc_gpn_ft_resp)) | |
470 | + 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one | |
471 | * to account for header as 1st pseudo "entry" */; | |
472 | ||
473 | /* the basic CT_IU preamble is the same size as one entry in the GPN_FT | |
474 | * response, allowing us to skip special handling for it - just skip it | |
475 | */ | |
476 | for (x = 1; x < max_entries && !last; x++) { | |
477 | if (x % (ZFCP_FC_GPN_FT_ENT_PAGE + 1)) | |
478 | acc++; | |
479 | else | |
480 | acc = sg_virt(++resp_entry); | |
481 | ||
482 | last = acc->fp_flags & FC_NS_FID_LAST; | |
483 | } | |
484 | len = min(len, (u16)(x * sizeof(struct fc_gpn_ft_resp))); | |
485 | return len; /* cap after last entry */ | |
8a36e453 MS |
486 | } |
487 | ||
bfab1637 | 488 | /** |
2c55b750 SS |
489 | * zfcp_dbf_san_res - trace event for received SAN request |
490 | * @tag: indentifier for event | |
491 | * @fsf_req: request containing issued CT data | |
bfab1637 | 492 | */ |
2c55b750 | 493 | void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf) |
8a36e453 | 494 | { |
2c55b750 SS |
495 | struct zfcp_dbf *dbf = fsf->adapter->dbf; |
496 | struct zfcp_fsf_ct_els *ct_els = fsf->data; | |
497 | u16 length; | |
8a36e453 | 498 | |
beb0b6c9 SM |
499 | length = (u16)zfcp_qdio_real_bytes(ct_els->resp); |
500 | zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES, | |
501 | length, fsf->req_id, ct_els->d_id, | |
502 | zfcp_dbf_san_res_cap_len_if_gpn_ft(tag, fsf, length)); | |
8a36e453 MS |
503 | } |
504 | ||
bfab1637 | 505 | /** |
2c55b750 SS |
506 | * zfcp_dbf_san_in_els - trace event for incoming ELS |
507 | * @tag: indentifier for event | |
508 | * @fsf_req: request containing issued CT data | |
bfab1637 | 509 | */ |
2c55b750 | 510 | void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) |
8a36e453 | 511 | { |
2c55b750 SS |
512 | struct zfcp_dbf *dbf = fsf->adapter->dbf; |
513 | struct fsf_status_read_buffer *srb = | |
514 | (struct fsf_status_read_buffer *) fsf->data; | |
515 | u16 length; | |
beb0b6c9 | 516 | struct scatterlist sg; |
2c55b750 SS |
517 | |
518 | length = (u16)(srb->length - | |
519 | offsetof(struct fsf_status_read_buffer, payload)); | |
beb0b6c9 SM |
520 | sg_init_one(&sg, srb->payload.data, length); |
521 | zfcp_dbf_san(tag, dbf, "san_els", &sg, ZFCP_DBF_SAN_ELS, length, | |
522 | fsf->req_id, ntoh24(srb->d_id), length); | |
8a36e453 MS |
523 | } |
524 | ||
250a1352 SS |
525 | /** |
526 | * zfcp_dbf_scsi - trace event for scsi commands | |
527 | * @tag: identifier for event | |
528 | * @sc: pointer to struct scsi_cmnd | |
529 | * @fsf: pointer to struct zfcp_fsf_req | |
530 | */ | |
909987d4 SM |
531 | void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, |
532 | struct zfcp_fsf_req *fsf) | |
8a36e453 | 533 | { |
250a1352 SS |
534 | struct zfcp_adapter *adapter = |
535 | (struct zfcp_adapter *) sc->device->host->hostdata[0]; | |
536 | struct zfcp_dbf *dbf = adapter->dbf; | |
537 | struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; | |
4318e08c | 538 | struct fcp_resp_with_ext *fcp_rsp; |
250a1352 SS |
539 | struct fcp_resp_rsp_info *fcp_rsp_info; |
540 | unsigned long flags; | |
8a36e453 | 541 | |
5771710b | 542 | spin_lock_irqsave(&dbf->scsi_lock, flags); |
250a1352 | 543 | memset(rec, 0, sizeof(*rec)); |
8a36e453 | 544 | |
250a1352 SS |
545 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
546 | rec->id = ZFCP_DBF_SCSI_CMND; | |
547 | rec->scsi_result = sc->result; | |
548 | rec->scsi_retries = sc->retries; | |
549 | rec->scsi_allowed = sc->allowed; | |
550 | rec->scsi_id = sc->device->id; | |
551 | rec->scsi_lun = sc->device->lun; | |
552 | rec->host_scribble = (unsigned long)sc->host_scribble; | |
553 | ||
554 | memcpy(rec->scsi_opcode, sc->cmnd, | |
555 | min((int)sc->cmd_len, ZFCP_DBF_SCSI_OPCODE)); | |
556 | ||
557 | if (fsf) { | |
558 | rec->fsf_req_id = fsf->req_id; | |
bb5cf573 | 559 | rec->pl_len = FCP_RESP_WITH_EXT; |
250a1352 SS |
560 | fcp_rsp = (struct fcp_resp_with_ext *) |
561 | &(fsf->qtcb->bottom.io.fcp_rsp); | |
bb5cf573 | 562 | /* mandatory parts of FCP_RSP IU in this SCSI record */ |
250a1352 SS |
563 | memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT); |
564 | if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) { | |
565 | fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; | |
566 | rec->fcp_rsp_info = fcp_rsp_info->rsp_code; | |
bb5cf573 | 567 | rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_rsp_len); |
250a1352 SS |
568 | } |
569 | if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) { | |
bb5cf573 | 570 | rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_sns_len); |
250a1352 | 571 | } |
bb5cf573 SM |
572 | /* complete FCP_RSP IU in associated PAYload record |
573 | * but only if there are optional parts | |
574 | */ | |
575 | if (fcp_rsp->resp.fr_flags != 0) | |
576 | zfcp_dbf_pl_write( | |
577 | dbf, fcp_rsp, | |
578 | /* at least one full PAY record | |
579 | * but not beyond hardware response field | |
580 | */ | |
581 | min_t(u16, max_t(u16, rec->pl_len, | |
582 | ZFCP_DBF_PAY_MAX_REC), | |
583 | FSF_FCP_RSP_SIZE), | |
584 | "fcp_riu", fsf->req_id); | |
8a36e453 | 585 | } |
8a36e453 | 586 | |
909987d4 | 587 | debug_event(dbf->scsi, level, rec, sizeof(*rec)); |
250a1352 SS |
588 | spin_unlock_irqrestore(&dbf->scsi_lock, flags); |
589 | } | |
8a36e453 | 590 | |
ea4a3a6a | 591 | static debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size) |
d46f384a CS |
592 | { |
593 | struct debug_info *d; | |
594 | ||
ea4a3a6a | 595 | d = debug_register(name, size, 1, rec_size); |
d46f384a CS |
596 | if (!d) |
597 | return NULL; | |
598 | ||
599 | debug_register_view(d, &debug_hex_ascii_view); | |
ea4a3a6a | 600 | debug_set_level(d, 3); |
d46f384a CS |
601 | |
602 | return d; | |
603 | } | |
604 | ||
ea4a3a6a SS |
605 | static void zfcp_dbf_unregister(struct zfcp_dbf *dbf) |
606 | { | |
607 | if (!dbf) | |
608 | return; | |
609 | ||
610 | debug_unregister(dbf->scsi); | |
611 | debug_unregister(dbf->san); | |
612 | debug_unregister(dbf->hba); | |
613 | debug_unregister(dbf->pay); | |
614 | debug_unregister(dbf->rec); | |
615 | kfree(dbf); | |
616 | } | |
617 | ||
8a36e453 MS |
618 | /** |
619 | * zfcp_adapter_debug_register - registers debug feature for an adapter | |
620 | * @adapter: pointer to adapter for which debug features should be registered | |
621 | * return: -ENOMEM on error, 0 otherwise | |
622 | */ | |
5771710b | 623 | int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) |
8a36e453 | 624 | { |
ea4a3a6a | 625 | char name[DEBUG_MAX_NAME_LEN]; |
d46f384a CS |
626 | struct zfcp_dbf *dbf; |
627 | ||
d23948ea | 628 | dbf = kzalloc(sizeof(struct zfcp_dbf), GFP_KERNEL); |
d46f384a CS |
629 | if (!dbf) |
630 | return -ENOMEM; | |
631 | ||
a54ca0f6 | 632 | spin_lock_init(&dbf->pay_lock); |
5771710b SS |
633 | spin_lock_init(&dbf->hba_lock); |
634 | spin_lock_init(&dbf->san_lock); | |
635 | spin_lock_init(&dbf->scsi_lock); | |
636 | spin_lock_init(&dbf->rec_lock); | |
8a36e453 | 637 | |
d79a83db | 638 | /* debug feature area which records recovery activity */ |
ea4a3a6a SS |
639 | sprintf(name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev)); |
640 | dbf->rec = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_rec)); | |
5771710b SS |
641 | if (!dbf->rec) |
642 | goto err_out; | |
d79a83db | 643 | |
8a36e453 | 644 | /* debug feature area which records HBA (FSF and QDIO) conditions */ |
ea4a3a6a SS |
645 | sprintf(name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev)); |
646 | dbf->hba = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_hba)); | |
5771710b SS |
647 | if (!dbf->hba) |
648 | goto err_out; | |
8a36e453 | 649 | |
a54ca0f6 | 650 | /* debug feature area which records payload info */ |
ea4a3a6a SS |
651 | sprintf(name, "zfcp_%s_pay", dev_name(&adapter->ccw_device->dev)); |
652 | dbf->pay = zfcp_dbf_reg(name, dbfsize * 2, sizeof(struct zfcp_dbf_pay)); | |
a54ca0f6 SS |
653 | if (!dbf->pay) |
654 | goto err_out; | |
655 | ||
8a36e453 | 656 | /* debug feature area which records SAN command failures and recovery */ |
ea4a3a6a SS |
657 | sprintf(name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); |
658 | dbf->san = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_san)); | |
5771710b SS |
659 | if (!dbf->san) |
660 | goto err_out; | |
8a36e453 MS |
661 | |
662 | /* debug feature area which records SCSI command failures and recovery */ | |
ea4a3a6a SS |
663 | sprintf(name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev)); |
664 | dbf->scsi = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_scsi)); | |
5771710b SS |
665 | if (!dbf->scsi) |
666 | goto err_out; | |
8a36e453 | 667 | |
d46f384a | 668 | adapter->dbf = dbf; |
8a36e453 | 669 | |
ea4a3a6a | 670 | return 0; |
5771710b | 671 | err_out: |
ea4a3a6a | 672 | zfcp_dbf_unregister(dbf); |
8a36e453 MS |
673 | return -ENOMEM; |
674 | } | |
675 | ||
676 | /** | |
677 | * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter | |
ea4a3a6a | 678 | * @adapter: pointer to adapter for which debug features should be unregistered |
8a36e453 | 679 | */ |
ea4a3a6a | 680 | void zfcp_dbf_adapter_unregister(struct zfcp_adapter *adapter) |
8a36e453 | 681 | { |
ea4a3a6a SS |
682 | struct zfcp_dbf *dbf = adapter->dbf; |
683 | ||
684 | adapter->dbf = NULL; | |
685 | zfcp_dbf_unregister(dbf); | |
8a36e453 | 686 | } |
5771710b | 687 |