1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * zfcp device driver |
4 | * |
5 | * Fibre Channel related functions for the zfcp device driver. |
6 | * |
7 | * Copyright IBM Corp. 2008, 2017 |
8 | */ |
9 | |
10 | #define KMSG_COMPONENT "zfcp" |
11 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
12 | |
13 | #include <linux/types.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/utsname.h> |
16 | #include <linux/random.h> |
17 | #include <linux/bsg-lib.h> |
18 | #include <scsi/fc/fc_els.h> |
19 | #include <scsi/libfc.h> |
20 | #include "zfcp_ext.h" |
21 | #include "zfcp_fc.h" |
22 | |
23 | struct kmem_cache *zfcp_fc_req_cache; |
24 | |
25 | static u32 zfcp_fc_rscn_range_mask[] = { |
26 | [ELS_ADDR_FMT_PORT] = 0xFFFFFF, |
27 | [ELS_ADDR_FMT_AREA] = 0xFFFF00, |
28 | [ELS_ADDR_FMT_DOM] = 0xFF0000, |
29 | [ELS_ADDR_FMT_FAB] = 0x000000, |
30 | }; |
31 | |
32 | static bool no_auto_port_rescan; |
33 | module_param(no_auto_port_rescan, bool, 0600); |
34 | MODULE_PARM_DESC(no_auto_port_rescan, |
35 | "no automatic port_rescan (default off)" ); |
36 | |
37 | static unsigned int port_scan_backoff = 500; |
38 | module_param(port_scan_backoff, uint, 0600); |
39 | MODULE_PARM_DESC(port_scan_backoff, |
40 | "upper limit of port scan random backoff in msecs (default 500)" ); |
41 | |
42 | static unsigned int port_scan_ratelimit = 60000; |
43 | module_param(port_scan_ratelimit, uint, 0600); |
44 | MODULE_PARM_DESC(port_scan_ratelimit, |
45 | "minimum interval between port scans in msecs (default 60000)" ); |
46 | |
47 | unsigned int zfcp_fc_port_scan_backoff(void) |
48 | { |
49 | if (!port_scan_backoff) |
50 | return 0; |
51 | return get_random_u32_below(ceil: port_scan_backoff); |
52 | } |
53 | |
54 | static void zfcp_fc_port_scan_time(struct zfcp_adapter *adapter) |
55 | { |
56 | unsigned long interval = msecs_to_jiffies(m: port_scan_ratelimit); |
57 | unsigned long backoff = msecs_to_jiffies(m: zfcp_fc_port_scan_backoff()); |
58 | |
59 | adapter->next_port_scan = jiffies + interval + backoff; |
60 | } |
61 | |
62 | static void zfcp_fc_port_scan(struct zfcp_adapter *adapter) |
63 | { |
64 | unsigned long now = jiffies; |
65 | unsigned long next = adapter->next_port_scan; |
66 | unsigned long delay = 0, max; |
67 | |
68 | /* delay only needed within waiting period */ |
69 | if (time_before(now, next)) { |
70 | delay = next - now; |
71 | /* paranoia: never ever delay scans longer than specified */ |
72 | max = msecs_to_jiffies(m: port_scan_ratelimit + port_scan_backoff); |
73 | delay = min(delay, max); |
74 | } |
75 | |
76 | queue_delayed_work(wq: adapter->work_queue, dwork: &adapter->scan_work, delay); |
77 | } |
78 | |
79 | void zfcp_fc_conditional_port_scan(struct zfcp_adapter *adapter) |
80 | { |
81 | if (no_auto_port_rescan) |
82 | return; |
83 | |
84 | zfcp_fc_port_scan(adapter); |
85 | } |
86 | |
87 | void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter) |
88 | { |
89 | if (!no_auto_port_rescan) |
90 | return; |
91 | |
92 | zfcp_fc_port_scan(adapter); |
93 | } |
94 | |
95 | /** |
96 | * zfcp_fc_post_event - post event to userspace via fc_transport |
97 | * @work: work struct with enqueued events |
98 | */ |
99 | void zfcp_fc_post_event(struct work_struct *work) |
100 | { |
101 | struct zfcp_fc_event *event = NULL, *tmp = NULL; |
102 | LIST_HEAD(tmp_lh); |
103 | struct zfcp_fc_events *events = container_of(work, |
104 | struct zfcp_fc_events, work); |
105 | struct zfcp_adapter *adapter = container_of(events, struct zfcp_adapter, |
106 | events); |
107 | |
108 | spin_lock_bh(lock: &events->list_lock); |
109 | list_splice_init(list: &events->list, head: &tmp_lh); |
110 | spin_unlock_bh(lock: &events->list_lock); |
111 | |
112 | list_for_each_entry_safe(event, tmp, &tmp_lh, list) { |
113 | fc_host_post_event(shost: adapter->scsi_host, event_number: fc_get_event_number(), |
114 | event_code: event->code, event_data: event->data); |
115 | list_del(entry: &event->list); |
116 | kfree(objp: event); |
117 | } |
118 | } |
119 | |
120 | /** |
121 | * zfcp_fc_enqueue_event - safely enqueue FC HBA API event from irq context |
122 | * @adapter: The adapter where to enqueue the event |
123 | * @event_code: The event code (as defined in fc_host_event_code in |
124 | * scsi_transport_fc.h) |
125 | * @event_data: The event data (e.g. n_port page in case of els) |
126 | */ |
127 | void zfcp_fc_enqueue_event(struct zfcp_adapter *adapter, |
128 | enum fc_host_event_code event_code, u32 event_data) |
129 | { |
130 | struct zfcp_fc_event *event; |
131 | |
132 | event = kmalloc(size: sizeof(struct zfcp_fc_event), GFP_ATOMIC); |
133 | if (!event) |
134 | return; |
135 | |
136 | event->code = event_code; |
137 | event->data = event_data; |
138 | |
139 | spin_lock(lock: &adapter->events.list_lock); |
140 | list_add_tail(new: &event->list, head: &adapter->events.list); |
141 | spin_unlock(lock: &adapter->events.list_lock); |
142 | |
143 | queue_work(wq: adapter->work_queue, work: &adapter->events.work); |
144 | } |
145 | |
146 | static int zfcp_fc_wka_port_get(struct zfcp_fc_wka_port *wka_port) |
147 | { |
148 | int ret = -EIO; |
149 | |
150 | if (mutex_lock_interruptible(&wka_port->mutex)) |
151 | return -ERESTARTSYS; |
152 | |
153 | if (wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE || |
154 | wka_port->status == ZFCP_FC_WKA_PORT_CLOSING) { |
155 | wka_port->status = ZFCP_FC_WKA_PORT_OPENING; |
156 | if (zfcp_fsf_open_wka_port(wka_port)) { |
157 | /* could not even send request, nothing to wait for */ |
158 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
159 | goto out; |
160 | } |
161 | } |
162 | |
163 | wait_event(wka_port->opened, |
164 | wka_port->status == ZFCP_FC_WKA_PORT_ONLINE || |
165 | wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE); |
166 | |
167 | if (wka_port->status == ZFCP_FC_WKA_PORT_ONLINE) { |
168 | atomic_inc(v: &wka_port->refcount); |
169 | ret = 0; |
170 | goto out; |
171 | } |
172 | out: |
173 | mutex_unlock(lock: &wka_port->mutex); |
174 | return ret; |
175 | } |
176 | |
177 | static void zfcp_fc_wka_port_offline(struct work_struct *work) |
178 | { |
179 | struct delayed_work *dw = to_delayed_work(work); |
180 | struct zfcp_fc_wka_port *wka_port = |
181 | container_of(dw, struct zfcp_fc_wka_port, work); |
182 | |
183 | mutex_lock(&wka_port->mutex); |
184 | if ((atomic_read(v: &wka_port->refcount) != 0) || |
185 | (wka_port->status != ZFCP_FC_WKA_PORT_ONLINE)) |
186 | goto out; |
187 | |
188 | wka_port->status = ZFCP_FC_WKA_PORT_CLOSING; |
189 | if (zfcp_fsf_close_wka_port(wka_port)) { |
190 | /* could not even send request, nothing to wait for */ |
191 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
192 | goto out; |
193 | } |
194 | wait_event(wka_port->closed, |
195 | wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE); |
196 | out: |
197 | mutex_unlock(lock: &wka_port->mutex); |
198 | } |
199 | |
200 | static void zfcp_fc_wka_port_put(struct zfcp_fc_wka_port *wka_port) |
201 | { |
202 | if (atomic_dec_return(v: &wka_port->refcount) != 0) |
203 | return; |
204 | /* wait 10 milliseconds, other reqs might pop in */ |
205 | queue_delayed_work(wq: wka_port->adapter->work_queue, dwork: &wka_port->work, |
206 | delay: msecs_to_jiffies(m: 10)); |
207 | } |
208 | |
209 | static void zfcp_fc_wka_port_init(struct zfcp_fc_wka_port *wka_port, u32 d_id, |
210 | struct zfcp_adapter *adapter) |
211 | { |
212 | init_waitqueue_head(&wka_port->opened); |
213 | init_waitqueue_head(&wka_port->closed); |
214 | |
215 | wka_port->adapter = adapter; |
216 | wka_port->d_id = d_id; |
217 | |
218 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
219 | atomic_set(v: &wka_port->refcount, i: 0); |
220 | mutex_init(&wka_port->mutex); |
221 | INIT_DELAYED_WORK(&wka_port->work, zfcp_fc_wka_port_offline); |
222 | } |
223 | |
224 | static void zfcp_fc_wka_port_force_offline(struct zfcp_fc_wka_port *wka) |
225 | { |
226 | cancel_delayed_work_sync(dwork: &wka->work); |
227 | mutex_lock(&wka->mutex); |
228 | wka->status = ZFCP_FC_WKA_PORT_OFFLINE; |
229 | mutex_unlock(lock: &wka->mutex); |
230 | } |
231 | |
232 | void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *gs) |
233 | { |
234 | if (!gs) |
235 | return; |
236 | zfcp_fc_wka_port_force_offline(wka: &gs->ms); |
237 | zfcp_fc_wka_port_force_offline(wka: &gs->ts); |
238 | zfcp_fc_wka_port_force_offline(wka: &gs->ds); |
239 | zfcp_fc_wka_port_force_offline(wka: &gs->as); |
240 | } |
241 | |
242 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, |
243 | struct fc_els_rscn_page *page) |
244 | { |
245 | unsigned long flags; |
246 | struct zfcp_adapter *adapter = fsf_req->adapter; |
247 | struct zfcp_port *port; |
248 | |
249 | read_lock_irqsave(&adapter->port_list_lock, flags); |
250 | list_for_each_entry(port, &adapter->port_list, list) { |
251 | if ((port->d_id & range) == (ntoh24(p: page->rscn_fid) & range)) |
252 | zfcp_fc_test_link(port); |
253 | } |
254 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
255 | } |
256 | |
257 | static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) |
258 | { |
259 | struct fsf_status_read_buffer *status_buffer = (void *)fsf_req->data; |
260 | struct zfcp_adapter *adapter = fsf_req->adapter; |
261 | struct fc_els_rscn *head; |
262 | struct fc_els_rscn_page *page; |
263 | u16 i; |
264 | u16 no_entries; |
265 | unsigned int afmt; |
266 | |
267 | head = (struct fc_els_rscn *) status_buffer->payload.data; |
268 | page = (struct fc_els_rscn_page *) head; |
269 | |
270 | /* see FC-FS */ |
271 | no_entries = be16_to_cpu(head->rscn_plen) / |
272 | sizeof(struct fc_els_rscn_page); |
273 | |
274 | if (no_entries > 1) { |
275 | /* handle failed ports */ |
276 | unsigned long flags; |
277 | struct zfcp_port *port; |
278 | |
279 | read_lock_irqsave(&adapter->port_list_lock, flags); |
280 | list_for_each_entry(port, &adapter->port_list, list) { |
281 | if (port->d_id) |
282 | continue; |
283 | zfcp_erp_port_reopen(port, |
284 | ZFCP_STATUS_COMMON_ERP_FAILED, |
285 | dbftag: "fcrscn1" ); |
286 | } |
287 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
288 | } |
289 | |
290 | for (i = 1; i < no_entries; i++) { |
291 | /* skip head and start with 1st element */ |
292 | page++; |
293 | afmt = page->rscn_page_flags & ELS_RSCN_ADDR_FMT_MASK; |
294 | _zfcp_fc_incoming_rscn(fsf_req, range: zfcp_fc_rscn_range_mask[afmt], |
295 | page); |
296 | zfcp_fc_enqueue_event(adapter: fsf_req->adapter, event_code: FCH_EVT_RSCN, |
297 | event_data: *(u32 *)page); |
298 | } |
299 | zfcp_fc_conditional_port_scan(adapter: fsf_req->adapter); |
300 | } |
301 | |
302 | static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) |
303 | { |
304 | unsigned long flags; |
305 | struct zfcp_adapter *adapter = req->adapter; |
306 | struct zfcp_port *port; |
307 | |
308 | read_lock_irqsave(&adapter->port_list_lock, flags); |
309 | list_for_each_entry(port, &adapter->port_list, list) |
310 | if (port->wwpn == wwpn) { |
311 | zfcp_erp_port_forced_reopen(port, 0, "fciwwp1" ); |
312 | break; |
313 | } |
314 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
315 | } |
316 | |
317 | static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) |
318 | { |
319 | struct fsf_status_read_buffer *status_buffer; |
320 | struct fc_els_flogi *plogi; |
321 | |
322 | status_buffer = (struct fsf_status_read_buffer *) req->data; |
323 | plogi = (struct fc_els_flogi *) status_buffer->payload.data; |
324 | zfcp_fc_incoming_wwpn(req, be64_to_cpu(plogi->fl_wwpn)); |
325 | } |
326 | |
327 | static void zfcp_fc_incoming_logo(struct zfcp_fsf_req *req) |
328 | { |
329 | struct fsf_status_read_buffer *status_buffer = |
330 | (struct fsf_status_read_buffer *)req->data; |
331 | struct fc_els_logo *logo = |
332 | (struct fc_els_logo *) status_buffer->payload.data; |
333 | |
334 | zfcp_fc_incoming_wwpn(req, be64_to_cpu(logo->fl_n_port_wwn)); |
335 | } |
336 | |
337 | /** |
338 | * zfcp_fc_incoming_els - handle incoming ELS |
339 | * @fsf_req: request which contains incoming ELS |
340 | */ |
341 | void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) |
342 | { |
343 | struct fsf_status_read_buffer *status_buffer = |
344 | (struct fsf_status_read_buffer *) fsf_req->data; |
345 | unsigned int els_type = status_buffer->payload.data[0]; |
346 | |
347 | zfcp_dbf_san_in_els("fciels1" , fsf_req); |
348 | if (els_type == ELS_PLOGI) |
349 | zfcp_fc_incoming_plogi(req: fsf_req); |
350 | else if (els_type == ELS_LOGO) |
351 | zfcp_fc_incoming_logo(req: fsf_req); |
352 | else if (els_type == ELS_RSCN) |
353 | zfcp_fc_incoming_rscn(fsf_req); |
354 | } |
355 | |
356 | static void zfcp_fc_ns_gid_pn_eval(struct zfcp_fc_req *fc_req) |
357 | { |
358 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; |
359 | struct zfcp_fc_gid_pn_rsp *gid_pn_rsp = &fc_req->u.gid_pn.rsp; |
360 | |
361 | if (ct_els->status) |
362 | return; |
363 | if (gid_pn_rsp->ct_hdr.ct_cmd != cpu_to_be16(FC_FS_ACC)) |
364 | return; |
365 | |
366 | /* looks like a valid d_id */ |
367 | ct_els->port->d_id = ntoh24(p: gid_pn_rsp->gid_pn.fp_fid); |
368 | } |
369 | |
370 | static void zfcp_fc_complete(void *data) |
371 | { |
372 | complete(data); |
373 | } |
374 | |
375 | static void zfcp_fc_ct_ns_init(struct fc_ct_hdr *ct_hdr, u16 cmd, u16 mr_size) |
376 | { |
377 | ct_hdr->ct_rev = FC_CT_REV; |
378 | ct_hdr->ct_fs_type = FC_FST_DIR; |
379 | ct_hdr->ct_fs_subtype = FC_NS_SUBTYPE; |
380 | ct_hdr->ct_cmd = cpu_to_be16(cmd); |
381 | ct_hdr->ct_mr_size = cpu_to_be16(mr_size / 4); |
382 | } |
383 | |
384 | static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, |
385 | struct zfcp_fc_req *fc_req) |
386 | { |
387 | struct zfcp_adapter *adapter = port->adapter; |
388 | DECLARE_COMPLETION_ONSTACK(completion); |
389 | struct zfcp_fc_gid_pn_req *gid_pn_req = &fc_req->u.gid_pn.req; |
390 | struct zfcp_fc_gid_pn_rsp *gid_pn_rsp = &fc_req->u.gid_pn.rsp; |
391 | int ret; |
392 | |
393 | /* setup parameters for send generic command */ |
394 | fc_req->ct_els.port = port; |
395 | fc_req->ct_els.handler = zfcp_fc_complete; |
396 | fc_req->ct_els.handler_data = &completion; |
397 | fc_req->ct_els.req = &fc_req->sg_req; |
398 | fc_req->ct_els.resp = &fc_req->sg_rsp; |
399 | sg_init_one(&fc_req->sg_req, gid_pn_req, sizeof(*gid_pn_req)); |
400 | sg_init_one(&fc_req->sg_rsp, gid_pn_rsp, sizeof(*gid_pn_rsp)); |
401 | |
402 | zfcp_fc_ct_ns_init(ct_hdr: &gid_pn_req->ct_hdr, |
403 | cmd: FC_NS_GID_PN, ZFCP_FC_CT_SIZE_PAGE); |
404 | gid_pn_req->gid_pn.fn_wwpn = cpu_to_be64(port->wwpn); |
405 | |
406 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, &fc_req->ct_els, |
407 | adapter->pool.gid_pn_req, |
408 | ZFCP_FC_CTELS_TMO); |
409 | if (!ret) { |
410 | wait_for_completion(&completion); |
411 | zfcp_fc_ns_gid_pn_eval(fc_req); |
412 | } |
413 | return ret; |
414 | } |
415 | |
416 | /** |
417 | * zfcp_fc_ns_gid_pn - initiate GID_PN nameserver request |
418 | * @port: port where GID_PN request is needed |
419 | * return: -ENOMEM on error, 0 otherwise |
420 | */ |
421 | static int zfcp_fc_ns_gid_pn(struct zfcp_port *port) |
422 | { |
423 | int ret; |
424 | struct zfcp_fc_req *fc_req; |
425 | struct zfcp_adapter *adapter = port->adapter; |
426 | |
427 | fc_req = mempool_alloc(pool: adapter->pool.gid_pn, GFP_ATOMIC); |
428 | if (!fc_req) |
429 | return -ENOMEM; |
430 | |
431 | memset(fc_req, 0, sizeof(*fc_req)); |
432 | |
433 | ret = zfcp_fc_wka_port_get(wka_port: &adapter->gs->ds); |
434 | if (ret) |
435 | goto out; |
436 | |
437 | ret = zfcp_fc_ns_gid_pn_request(port, fc_req); |
438 | |
439 | zfcp_fc_wka_port_put(wka_port: &adapter->gs->ds); |
440 | out: |
441 | mempool_free(element: fc_req, pool: adapter->pool.gid_pn); |
442 | return ret; |
443 | } |
444 | |
445 | void zfcp_fc_port_did_lookup(struct work_struct *work) |
446 | { |
447 | int ret; |
448 | struct zfcp_port *port = container_of(work, struct zfcp_port, |
449 | gid_pn_work); |
450 | |
451 | set_worker_desc("zgidpn%16llx" , port->wwpn); /* < WORKER_DESC_LEN=24 */ |
452 | ret = zfcp_fc_ns_gid_pn(port); |
453 | if (ret) { |
454 | /* could not issue gid_pn for some reason */ |
455 | zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1" ); |
456 | goto out; |
457 | } |
458 | |
459 | if (!port->d_id) { |
460 | zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); |
461 | goto out; |
462 | } |
463 | |
464 | zfcp_erp_port_reopen(port, clear: 0, dbftag: "fcgpn_3" ); |
465 | out: |
466 | put_device(dev: &port->dev); |
467 | } |
468 | |
469 | /** |
470 | * zfcp_fc_trigger_did_lookup - trigger the d_id lookup using a GID_PN request |
471 | * @port: The zfcp_port to lookup the d_id for. |
472 | */ |
473 | void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) |
474 | { |
475 | get_device(dev: &port->dev); |
476 | if (!queue_work(wq: port->adapter->work_queue, work: &port->gid_pn_work)) |
477 | put_device(dev: &port->dev); |
478 | } |
479 | |
480 | /** |
481 | * zfcp_fc_plogi_evaluate - evaluate PLOGI playload |
482 | * @port: zfcp_port structure |
483 | * @plogi: plogi payload |
484 | * |
485 | * Evaluate PLOGI playload and copy important fields into zfcp_port structure |
486 | */ |
487 | void zfcp_fc_plogi_evaluate(struct zfcp_port *port, struct fc_els_flogi *plogi) |
488 | { |
489 | if (be64_to_cpu(plogi->fl_wwpn) != port->wwpn) { |
490 | port->d_id = 0; |
491 | dev_warn(&port->adapter->ccw_device->dev, |
492 | "A port opened with WWPN 0x%016Lx returned data that " |
493 | "identifies it as WWPN 0x%016Lx\n" , |
494 | (unsigned long long) port->wwpn, |
495 | (unsigned long long) be64_to_cpu(plogi->fl_wwpn)); |
496 | return; |
497 | } |
498 | |
499 | port->wwnn = be64_to_cpu(plogi->fl_wwnn); |
500 | port->maxframe_size = be16_to_cpu(plogi->fl_csp.sp_bb_data); |
501 | |
502 | if (plogi->fl_cssp[0].cp_class & cpu_to_be16(FC_CPC_VALID)) |
503 | port->supported_classes |= FC_COS_CLASS1; |
504 | if (plogi->fl_cssp[1].cp_class & cpu_to_be16(FC_CPC_VALID)) |
505 | port->supported_classes |= FC_COS_CLASS2; |
506 | if (plogi->fl_cssp[2].cp_class & cpu_to_be16(FC_CPC_VALID)) |
507 | port->supported_classes |= FC_COS_CLASS3; |
508 | if (plogi->fl_cssp[3].cp_class & cpu_to_be16(FC_CPC_VALID)) |
509 | port->supported_classes |= FC_COS_CLASS4; |
510 | } |
511 | |
512 | static void zfcp_fc_adisc_handler(void *data) |
513 | { |
514 | struct zfcp_fc_req *fc_req = data; |
515 | struct zfcp_port *port = fc_req->ct_els.port; |
516 | struct fc_els_adisc *adisc_resp = &fc_req->u.adisc.rsp; |
517 | |
518 | if (fc_req->ct_els.status) { |
519 | /* request rejected or timed out */ |
520 | zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, |
521 | "fcadh_1" ); |
522 | goto out; |
523 | } |
524 | |
525 | if (!port->wwnn) |
526 | port->wwnn = be64_to_cpu(adisc_resp->adisc_wwnn); |
527 | |
528 | if ((port->wwpn != be64_to_cpu(adisc_resp->adisc_wwpn)) || |
529 | !(atomic_read(v: &port->status) & ZFCP_STATUS_COMMON_OPEN)) { |
530 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, |
531 | dbftag: "fcadh_2" ); |
532 | goto out; |
533 | } |
534 | |
535 | /* re-init to undo drop from zfcp_fc_adisc() */ |
536 | port->d_id = ntoh24(p: adisc_resp->adisc_port_id); |
537 | /* port is still good, nothing to do */ |
538 | out: |
539 | atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, v: &port->status); |
540 | put_device(dev: &port->dev); |
541 | kmem_cache_free(s: zfcp_fc_req_cache, objp: fc_req); |
542 | } |
543 | |
544 | static int zfcp_fc_adisc(struct zfcp_port *port) |
545 | { |
546 | struct zfcp_fc_req *fc_req; |
547 | struct zfcp_adapter *adapter = port->adapter; |
548 | struct Scsi_Host *shost = adapter->scsi_host; |
549 | u32 d_id; |
550 | int ret; |
551 | |
552 | fc_req = kmem_cache_zalloc(k: zfcp_fc_req_cache, GFP_ATOMIC); |
553 | if (!fc_req) |
554 | return -ENOMEM; |
555 | |
556 | fc_req->ct_els.port = port; |
557 | fc_req->ct_els.req = &fc_req->sg_req; |
558 | fc_req->ct_els.resp = &fc_req->sg_rsp; |
559 | sg_init_one(&fc_req->sg_req, &fc_req->u.adisc.req, |
560 | sizeof(struct fc_els_adisc)); |
561 | sg_init_one(&fc_req->sg_rsp, &fc_req->u.adisc.rsp, |
562 | sizeof(struct fc_els_adisc)); |
563 | |
564 | fc_req->ct_els.handler = zfcp_fc_adisc_handler; |
565 | fc_req->ct_els.handler_data = fc_req; |
566 | |
567 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports |
568 | without FC-AL-2 capability, so we don't set it */ |
569 | fc_req->u.adisc.req.adisc_wwpn = cpu_to_be64(fc_host_port_name(shost)); |
570 | fc_req->u.adisc.req.adisc_wwnn = cpu_to_be64(fc_host_node_name(shost)); |
571 | fc_req->u.adisc.req.adisc_cmd = ELS_ADISC; |
572 | hton24(p: fc_req->u.adisc.req.adisc_port_id, fc_host_port_id(shost)); |
573 | |
574 | d_id = port->d_id; /* remember as destination for send els below */ |
575 | /* |
576 | * Force fresh GID_PN lookup on next port recovery. |
577 | * Must happen after request setup and before sending request, |
578 | * to prevent race with port->d_id re-init in zfcp_fc_adisc_handler(). |
579 | */ |
580 | port->d_id = 0; |
581 | |
582 | ret = zfcp_fsf_send_els(adapter, d_id, &fc_req->ct_els, |
583 | ZFCP_FC_CTELS_TMO); |
584 | if (ret) |
585 | kmem_cache_free(s: zfcp_fc_req_cache, objp: fc_req); |
586 | |
587 | return ret; |
588 | } |
589 | |
590 | void zfcp_fc_link_test_work(struct work_struct *work) |
591 | { |
592 | struct zfcp_port *port = |
593 | container_of(work, struct zfcp_port, test_link_work); |
594 | int retval; |
595 | |
596 | set_worker_desc("zadisc%16llx" , port->wwpn); /* < WORKER_DESC_LEN=24 */ |
597 | |
598 | /* only issue one test command at one time per port */ |
599 | if (atomic_read(v: &port->status) & ZFCP_STATUS_PORT_LINK_TEST) |
600 | goto out; |
601 | |
602 | atomic_or(ZFCP_STATUS_PORT_LINK_TEST, v: &port->status); |
603 | |
604 | retval = zfcp_fc_adisc(port); |
605 | if (retval == 0) |
606 | return; |
607 | |
608 | /* send of ADISC was not possible */ |
609 | atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, v: &port->status); |
610 | zfcp_erp_port_forced_reopen(port, 0, "fcltwk1" ); |
611 | |
612 | out: |
613 | put_device(dev: &port->dev); |
614 | } |
615 | |
616 | /** |
617 | * zfcp_fc_test_link - lightweight link test procedure |
618 | * @port: port to be tested |
619 | * |
620 | * Test status of a link to a remote port using the ELS command ADISC. |
621 | * If there is a problem with the remote port, error recovery steps |
622 | * will be triggered. |
623 | */ |
624 | void zfcp_fc_test_link(struct zfcp_port *port) |
625 | { |
626 | get_device(dev: &port->dev); |
627 | if (!queue_work(wq: port->adapter->work_queue, work: &port->test_link_work)) |
628 | put_device(dev: &port->dev); |
629 | } |
630 | |
631 | /** |
632 | * zfcp_fc_sg_free_table - free memory used by scatterlists |
633 | * @sg: pointer to scatterlist |
634 | * @count: number of scatterlist which are to be free'ed |
635 | * the scatterlist are expected to reference pages always |
636 | */ |
637 | static void zfcp_fc_sg_free_table(struct scatterlist *sg, int count) |
638 | { |
639 | int i; |
640 | |
641 | for (i = 0; i < count; i++, sg = sg_next(sg)) |
642 | if (sg) |
643 | free_page((unsigned long) sg_virt(sg)); |
644 | else |
645 | break; |
646 | } |
647 | |
648 | /** |
649 | * zfcp_fc_sg_setup_table - init scatterlist and allocate, assign buffers |
650 | * @sg: pointer to struct scatterlist |
651 | * @count: number of scatterlists which should be assigned with buffers |
652 | * of size page |
653 | * |
654 | * Returns: 0 on success, -ENOMEM otherwise |
655 | */ |
656 | static int zfcp_fc_sg_setup_table(struct scatterlist *sg, int count) |
657 | { |
658 | void *addr; |
659 | int i; |
660 | |
661 | sg_init_table(sg, count); |
662 | for (i = 0; i < count; i++, sg = sg_next(sg)) { |
663 | addr = (void *) get_zeroed_page(GFP_KERNEL); |
664 | if (!addr) { |
665 | zfcp_fc_sg_free_table(sg, count: i); |
666 | return -ENOMEM; |
667 | } |
668 | sg_set_buf(sg, buf: addr, PAGE_SIZE); |
669 | } |
670 | return 0; |
671 | } |
672 | |
673 | static struct zfcp_fc_req *zfcp_fc_alloc_sg_env(int buf_num) |
674 | { |
675 | struct zfcp_fc_req *fc_req; |
676 | |
677 | fc_req = kmem_cache_zalloc(k: zfcp_fc_req_cache, GFP_KERNEL); |
678 | if (!fc_req) |
679 | return NULL; |
680 | |
681 | if (zfcp_fc_sg_setup_table(sg: &fc_req->sg_rsp, count: buf_num)) { |
682 | kmem_cache_free(s: zfcp_fc_req_cache, objp: fc_req); |
683 | return NULL; |
684 | } |
685 | |
686 | sg_init_one(&fc_req->sg_req, &fc_req->u.gpn_ft.req, |
687 | sizeof(struct zfcp_fc_gpn_ft_req)); |
688 | |
689 | return fc_req; |
690 | } |
691 | |
692 | static int zfcp_fc_send_gpn_ft(struct zfcp_fc_req *fc_req, |
693 | struct zfcp_adapter *adapter, int max_bytes) |
694 | { |
695 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; |
696 | struct zfcp_fc_gpn_ft_req *req = &fc_req->u.gpn_ft.req; |
697 | DECLARE_COMPLETION_ONSTACK(completion); |
698 | int ret; |
699 | |
700 | zfcp_fc_ct_ns_init(ct_hdr: &req->ct_hdr, cmd: FC_NS_GPN_FT, mr_size: max_bytes); |
701 | req->gpn_ft.fn_fc4_type = FC_TYPE_FCP; |
702 | |
703 | ct_els->handler = zfcp_fc_complete; |
704 | ct_els->handler_data = &completion; |
705 | ct_els->req = &fc_req->sg_req; |
706 | ct_els->resp = &fc_req->sg_rsp; |
707 | |
708 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL, |
709 | ZFCP_FC_CTELS_TMO); |
710 | if (!ret) |
711 | wait_for_completion(&completion); |
712 | return ret; |
713 | } |
714 | |
715 | static void zfcp_fc_validate_port(struct zfcp_port *port, struct list_head *lh) |
716 | { |
717 | if (!(atomic_read(v: &port->status) & ZFCP_STATUS_COMMON_NOESC)) |
718 | return; |
719 | |
720 | atomic_andnot(ZFCP_STATUS_COMMON_NOESC, v: &port->status); |
721 | |
722 | if ((port->supported_classes != 0) || |
723 | !list_empty(head: &port->unit_list)) |
724 | return; |
725 | |
726 | list_move_tail(list: &port->list, head: lh); |
727 | } |
728 | |
729 | static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_req *fc_req, |
730 | struct zfcp_adapter *adapter, int max_entries) |
731 | { |
732 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; |
733 | struct scatterlist *sg = &fc_req->sg_rsp; |
734 | struct fc_ct_hdr *hdr = sg_virt(sg); |
735 | struct fc_gpn_ft_resp *acc = sg_virt(sg); |
736 | struct zfcp_port *port, *tmp; |
737 | unsigned long flags; |
738 | LIST_HEAD(remove_lh); |
739 | u32 d_id; |
740 | int ret = 0, x, last = 0; |
741 | |
742 | if (ct_els->status) |
743 | return -EIO; |
744 | |
745 | if (hdr->ct_cmd != cpu_to_be16(FC_FS_ACC)) { |
746 | if (hdr->ct_reason == FC_FS_RJT_UNABL) |
747 | return -EAGAIN; /* might be a temporary condition */ |
748 | return -EIO; |
749 | } |
750 | |
751 | if (hdr->ct_mr_size) { |
752 | dev_warn(&adapter->ccw_device->dev, |
753 | "The name server reported %d words residual data\n" , |
754 | hdr->ct_mr_size); |
755 | return -E2BIG; |
756 | } |
757 | |
758 | /* first entry is the header */ |
759 | for (x = 1; x < max_entries && !last; x++) { |
760 | if (x % (ZFCP_FC_GPN_FT_ENT_PAGE + 1)) |
761 | acc++; |
762 | else |
763 | acc = sg_virt(sg: ++sg); |
764 | |
765 | last = acc->fp_flags & FC_NS_FID_LAST; |
766 | d_id = ntoh24(p: acc->fp_fid); |
767 | |
768 | /* don't attach ports with a well known address */ |
769 | if (d_id >= FC_FID_WELL_KNOWN_BASE) |
770 | continue; |
771 | /* skip the adapter's port and known remote ports */ |
772 | if (be64_to_cpu(acc->fp_wwpn) == |
773 | fc_host_port_name(adapter->scsi_host)) |
774 | continue; |
775 | |
776 | port = zfcp_port_enqueue(adapter, be64_to_cpu(acc->fp_wwpn), |
777 | ZFCP_STATUS_COMMON_NOESC, d_id); |
778 | if (!IS_ERR(ptr: port)) |
779 | zfcp_erp_port_reopen(port, clear: 0, dbftag: "fcegpf1" ); |
780 | else if (PTR_ERR(ptr: port) != -EEXIST) |
781 | ret = PTR_ERR(ptr: port); |
782 | } |
783 | |
784 | zfcp_erp_wait(adapter); |
785 | write_lock_irqsave(&adapter->port_list_lock, flags); |
786 | list_for_each_entry_safe(port, tmp, &adapter->port_list, list) |
787 | zfcp_fc_validate_port(port, lh: &remove_lh); |
788 | write_unlock_irqrestore(&adapter->port_list_lock, flags); |
789 | |
790 | list_for_each_entry_safe(port, tmp, &remove_lh, list) { |
791 | zfcp_erp_port_shutdown(port, 0, "fcegpf2" ); |
792 | device_unregister(dev: &port->dev); |
793 | } |
794 | |
795 | return ret; |
796 | } |
797 | |
798 | /** |
799 | * zfcp_fc_scan_ports - scan remote ports and attach new ports |
800 | * @work: reference to scheduled work |
801 | */ |
802 | void zfcp_fc_scan_ports(struct work_struct *work) |
803 | { |
804 | struct delayed_work *dw = to_delayed_work(work); |
805 | struct zfcp_adapter *adapter = container_of(dw, struct zfcp_adapter, |
806 | scan_work); |
807 | int ret, i; |
808 | struct zfcp_fc_req *fc_req; |
809 | int chain, max_entries, buf_num, max_bytes; |
810 | |
811 | zfcp_fc_port_scan_time(adapter); |
812 | |
813 | chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS; |
814 | buf_num = chain ? ZFCP_FC_GPN_FT_NUM_BUFS : 1; |
815 | max_entries = chain ? ZFCP_FC_GPN_FT_MAX_ENT : ZFCP_FC_GPN_FT_ENT_PAGE; |
816 | max_bytes = chain ? ZFCP_FC_GPN_FT_MAX_SIZE : ZFCP_FC_CT_SIZE_PAGE; |
817 | |
818 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT && |
819 | fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) |
820 | return; |
821 | |
822 | if (zfcp_fc_wka_port_get(wka_port: &adapter->gs->ds)) |
823 | return; |
824 | |
825 | fc_req = zfcp_fc_alloc_sg_env(buf_num); |
826 | if (!fc_req) |
827 | goto out; |
828 | |
829 | for (i = 0; i < 3; i++) { |
830 | ret = zfcp_fc_send_gpn_ft(fc_req, adapter, max_bytes); |
831 | if (!ret) { |
832 | ret = zfcp_fc_eval_gpn_ft(fc_req, adapter, max_entries); |
833 | if (ret == -EAGAIN) |
834 | ssleep(seconds: 1); |
835 | else |
836 | break; |
837 | } |
838 | } |
839 | zfcp_fc_sg_free_table(sg: &fc_req->sg_rsp, count: buf_num); |
840 | kmem_cache_free(s: zfcp_fc_req_cache, objp: fc_req); |
841 | out: |
842 | zfcp_fc_wka_port_put(wka_port: &adapter->gs->ds); |
843 | } |
844 | |
845 | static int zfcp_fc_gspn(struct zfcp_adapter *adapter, |
846 | struct zfcp_fc_req *fc_req) |
847 | { |
848 | DECLARE_COMPLETION_ONSTACK(completion); |
849 | char devno[] = "DEVNO:" ; |
850 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; |
851 | struct zfcp_fc_gspn_req *gspn_req = &fc_req->u.gspn.req; |
852 | struct zfcp_fc_gspn_rsp *gspn_rsp = &fc_req->u.gspn.rsp; |
853 | int ret; |
854 | |
855 | zfcp_fc_ct_ns_init(ct_hdr: &gspn_req->ct_hdr, cmd: FC_NS_GSPN_ID, |
856 | FC_SYMBOLIC_NAME_SIZE); |
857 | hton24(p: gspn_req->gspn.fp_fid, fc_host_port_id(adapter->scsi_host)); |
858 | |
859 | sg_init_one(&fc_req->sg_req, gspn_req, sizeof(*gspn_req)); |
860 | sg_init_one(&fc_req->sg_rsp, gspn_rsp, sizeof(*gspn_rsp)); |
861 | |
862 | ct_els->handler = zfcp_fc_complete; |
863 | ct_els->handler_data = &completion; |
864 | ct_els->req = &fc_req->sg_req; |
865 | ct_els->resp = &fc_req->sg_rsp; |
866 | |
867 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL, |
868 | ZFCP_FC_CTELS_TMO); |
869 | if (ret) |
870 | return ret; |
871 | |
872 | wait_for_completion(&completion); |
873 | if (ct_els->status) |
874 | return ct_els->status; |
875 | |
876 | if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_NPIV && |
877 | !(strstr(gspn_rsp->gspn.fp_name, devno))) |
878 | snprintf(fc_host_symbolic_name(adapter->scsi_host), |
879 | FC_SYMBOLIC_NAME_SIZE, fmt: "%s%s %s NAME: %s" , |
880 | gspn_rsp->gspn.fp_name, devno, |
881 | dev_name(dev: &adapter->ccw_device->dev), |
882 | init_utsname()->nodename); |
883 | else |
884 | strscpy(fc_host_symbolic_name(adapter->scsi_host), |
885 | q: gspn_rsp->gspn.fp_name, FC_SYMBOLIC_NAME_SIZE); |
886 | |
887 | return 0; |
888 | } |
889 | |
890 | static void zfcp_fc_rspn(struct zfcp_adapter *adapter, |
891 | struct zfcp_fc_req *fc_req) |
892 | { |
893 | DECLARE_COMPLETION_ONSTACK(completion); |
894 | struct Scsi_Host *shost = adapter->scsi_host; |
895 | struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els; |
896 | struct zfcp_fc_rspn_req *rspn_req = &fc_req->u.rspn.req; |
897 | struct fc_ct_hdr *rspn_rsp = &fc_req->u.rspn.rsp; |
898 | int ret, len; |
899 | |
900 | zfcp_fc_ct_ns_init(ct_hdr: &rspn_req->ct_hdr, cmd: FC_NS_RSPN_ID, |
901 | FC_SYMBOLIC_NAME_SIZE); |
902 | hton24(p: rspn_req->rspn.fr_fid.fp_fid, fc_host_port_id(shost)); |
903 | len = strlcpy(p: rspn_req->rspn.fr_name, fc_host_symbolic_name(shost), |
904 | FC_SYMBOLIC_NAME_SIZE); |
905 | rspn_req->rspn.fr_name_len = len; |
906 | |
907 | sg_init_one(&fc_req->sg_req, rspn_req, sizeof(*rspn_req)); |
908 | sg_init_one(&fc_req->sg_rsp, rspn_rsp, sizeof(*rspn_rsp)); |
909 | |
910 | ct_els->handler = zfcp_fc_complete; |
911 | ct_els->handler_data = &completion; |
912 | ct_els->req = &fc_req->sg_req; |
913 | ct_els->resp = &fc_req->sg_rsp; |
914 | |
915 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL, |
916 | ZFCP_FC_CTELS_TMO); |
917 | if (!ret) |
918 | wait_for_completion(&completion); |
919 | } |
920 | |
921 | /** |
922 | * zfcp_fc_sym_name_update - Retrieve and update the symbolic port name |
923 | * @work: ns_up_work of the adapter where to update the symbolic port name |
924 | * |
925 | * Retrieve the current symbolic port name that may have been set by |
926 | * the hardware using the GSPN request and update the fc_host |
927 | * symbolic_name sysfs attribute. When running in NPIV mode (and hence |
928 | * the port name is unique for this system), update the symbolic port |
929 | * name to add Linux specific information and update the FC nameserver |
930 | * using the RSPN request. |
931 | */ |
932 | void zfcp_fc_sym_name_update(struct work_struct *work) |
933 | { |
934 | struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter, |
935 | ns_up_work); |
936 | int ret; |
937 | struct zfcp_fc_req *fc_req; |
938 | |
939 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT && |
940 | fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) |
941 | return; |
942 | |
943 | fc_req = kmem_cache_zalloc(k: zfcp_fc_req_cache, GFP_KERNEL); |
944 | if (!fc_req) |
945 | return; |
946 | |
947 | ret = zfcp_fc_wka_port_get(wka_port: &adapter->gs->ds); |
948 | if (ret) |
949 | goto out_free; |
950 | |
951 | ret = zfcp_fc_gspn(adapter, fc_req); |
952 | if (ret || fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) |
953 | goto out_ds_put; |
954 | |
955 | memset(fc_req, 0, sizeof(*fc_req)); |
956 | zfcp_fc_rspn(adapter, fc_req); |
957 | |
958 | out_ds_put: |
959 | zfcp_fc_wka_port_put(wka_port: &adapter->gs->ds); |
960 | out_free: |
961 | kmem_cache_free(s: zfcp_fc_req_cache, objp: fc_req); |
962 | } |
963 | |
964 | static void zfcp_fc_ct_els_job_handler(void *data) |
965 | { |
966 | struct bsg_job *job = data; |
967 | struct zfcp_fsf_ct_els *zfcp_ct_els = job->dd_data; |
968 | struct fc_bsg_reply *jr = job->reply; |
969 | |
970 | jr->reply_payload_rcv_len = job->reply_payload.payload_len; |
971 | jr->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; |
972 | jr->result = zfcp_ct_els->status ? -EIO : 0; |
973 | bsg_job_done(job, result: jr->result, reply_payload_rcv_len: jr->reply_payload_rcv_len); |
974 | } |
975 | |
976 | static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct bsg_job *job) |
977 | { |
978 | u32 preamble_word1; |
979 | u8 gs_type; |
980 | struct zfcp_adapter *adapter; |
981 | struct fc_bsg_request *bsg_request = job->request; |
982 | struct fc_rport *rport = fc_bsg_to_rport(job); |
983 | struct Scsi_Host *shost; |
984 | |
985 | preamble_word1 = bsg_request->rqst_data.r_ct.preamble_word1; |
986 | gs_type = (preamble_word1 & 0xff000000) >> 24; |
987 | |
988 | shost = rport ? rport_to_shost(rport) : fc_bsg_to_shost(job); |
989 | adapter = (struct zfcp_adapter *) shost->hostdata[0]; |
990 | |
991 | switch (gs_type) { |
992 | case FC_FST_ALIAS: |
993 | return &adapter->gs->as; |
994 | case FC_FST_MGMT: |
995 | return &adapter->gs->ms; |
996 | case FC_FST_TIME: |
997 | return &adapter->gs->ts; |
998 | break; |
999 | case FC_FST_DIR: |
1000 | return &adapter->gs->ds; |
1001 | break; |
1002 | default: |
1003 | return NULL; |
1004 | } |
1005 | } |
1006 | |
1007 | static void zfcp_fc_ct_job_handler(void *data) |
1008 | { |
1009 | struct bsg_job *job = data; |
1010 | struct zfcp_fc_wka_port *wka_port; |
1011 | |
1012 | wka_port = zfcp_fc_job_wka_port(job); |
1013 | zfcp_fc_wka_port_put(wka_port); |
1014 | |
1015 | zfcp_fc_ct_els_job_handler(data); |
1016 | } |
1017 | |
1018 | static int zfcp_fc_exec_els_job(struct bsg_job *job, |
1019 | struct zfcp_adapter *adapter) |
1020 | { |
1021 | struct zfcp_fsf_ct_els *els = job->dd_data; |
1022 | struct fc_rport *rport = fc_bsg_to_rport(job); |
1023 | struct fc_bsg_request *bsg_request = job->request; |
1024 | struct zfcp_port *port; |
1025 | u32 d_id; |
1026 | |
1027 | if (rport) { |
1028 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); |
1029 | if (!port) |
1030 | return -EINVAL; |
1031 | |
1032 | d_id = port->d_id; |
1033 | put_device(dev: &port->dev); |
1034 | } else |
1035 | d_id = ntoh24(p: bsg_request->rqst_data.h_els.port_id); |
1036 | |
1037 | els->handler = zfcp_fc_ct_els_job_handler; |
1038 | return zfcp_fsf_send_els(adapter, d_id, els, job->timeout / HZ); |
1039 | } |
1040 | |
1041 | static int zfcp_fc_exec_ct_job(struct bsg_job *job, |
1042 | struct zfcp_adapter *adapter) |
1043 | { |
1044 | int ret; |
1045 | struct zfcp_fsf_ct_els *ct = job->dd_data; |
1046 | struct zfcp_fc_wka_port *wka_port; |
1047 | |
1048 | wka_port = zfcp_fc_job_wka_port(job); |
1049 | if (!wka_port) |
1050 | return -EINVAL; |
1051 | |
1052 | ret = zfcp_fc_wka_port_get(wka_port); |
1053 | if (ret) |
1054 | return ret; |
1055 | |
1056 | ct->handler = zfcp_fc_ct_job_handler; |
1057 | ret = zfcp_fsf_send_ct(wka_port, ct, NULL, job->timeout / HZ); |
1058 | if (ret) |
1059 | zfcp_fc_wka_port_put(wka_port); |
1060 | |
1061 | return ret; |
1062 | } |
1063 | |
1064 | int zfcp_fc_exec_bsg_job(struct bsg_job *job) |
1065 | { |
1066 | struct Scsi_Host *shost; |
1067 | struct zfcp_adapter *adapter; |
1068 | struct zfcp_fsf_ct_els *ct_els = job->dd_data; |
1069 | struct fc_bsg_request *bsg_request = job->request; |
1070 | struct fc_rport *rport = fc_bsg_to_rport(job); |
1071 | |
1072 | shost = rport ? rport_to_shost(rport) : fc_bsg_to_shost(job); |
1073 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; |
1074 | |
1075 | if (!(atomic_read(v: &adapter->status) & ZFCP_STATUS_COMMON_OPEN)) |
1076 | return -EINVAL; |
1077 | |
1078 | ct_els->req = job->request_payload.sg_list; |
1079 | ct_els->resp = job->reply_payload.sg_list; |
1080 | ct_els->handler_data = job; |
1081 | |
1082 | switch (bsg_request->msgcode) { |
1083 | case FC_BSG_RPT_ELS: |
1084 | case FC_BSG_HST_ELS_NOLOGIN: |
1085 | return zfcp_fc_exec_els_job(job, adapter); |
1086 | case FC_BSG_RPT_CT: |
1087 | case FC_BSG_HST_CT: |
1088 | return zfcp_fc_exec_ct_job(job, adapter); |
1089 | default: |
1090 | return -EINVAL; |
1091 | } |
1092 | } |
1093 | |
1094 | int zfcp_fc_timeout_bsg_job(struct bsg_job *job) |
1095 | { |
1096 | /* hardware tracks timeout, reset bsg timeout to not interfere */ |
1097 | return -EAGAIN; |
1098 | } |
1099 | |
1100 | int zfcp_fc_gs_setup(struct zfcp_adapter *adapter) |
1101 | { |
1102 | struct zfcp_fc_wka_ports *wka_ports; |
1103 | |
1104 | wka_ports = kzalloc(size: sizeof(struct zfcp_fc_wka_ports), GFP_KERNEL); |
1105 | if (!wka_ports) |
1106 | return -ENOMEM; |
1107 | |
1108 | adapter->gs = wka_ports; |
1109 | zfcp_fc_wka_port_init(wka_port: &wka_ports->ms, d_id: FC_FID_MGMT_SERV, adapter); |
1110 | zfcp_fc_wka_port_init(wka_port: &wka_ports->ts, d_id: FC_FID_TIME_SERV, adapter); |
1111 | zfcp_fc_wka_port_init(wka_port: &wka_ports->ds, d_id: FC_FID_DIR_SERV, adapter); |
1112 | zfcp_fc_wka_port_init(wka_port: &wka_ports->as, d_id: FC_FID_ALIASES, adapter); |
1113 | |
1114 | return 0; |
1115 | } |
1116 | |
1117 | void zfcp_fc_gs_destroy(struct zfcp_adapter *adapter) |
1118 | { |
1119 | kfree(objp: adapter->gs); |
1120 | adapter->gs = NULL; |
1121 | } |
1122 | |
1123 | |