1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * zfcp device driver |
4 | * |
5 | * Interface to Linux SCSI midlayer. |
6 | * |
7 | * Copyright IBM Corp. 2002, 2020 |
8 | */ |
9 | |
10 | #define KMSG_COMPONENT "zfcp" |
11 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
12 | |
13 | #include <linux/module.h> |
14 | #include <linux/types.h> |
15 | #include <linux/slab.h> |
16 | #include <scsi/fc/fc_fcp.h> |
17 | #include <scsi/scsi_eh.h> |
18 | #include <linux/atomic.h> |
19 | #include "zfcp_ext.h" |
20 | #include "zfcp_dbf.h" |
21 | #include "zfcp_fc.h" |
22 | #include "zfcp_reqlist.h" |
23 | |
24 | static unsigned int default_depth = 32; |
25 | module_param_named(queue_depth, default_depth, uint, 0600); |
26 | MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices" ); |
27 | |
28 | static bool enable_dif; |
29 | module_param_named(dif, enable_dif, bool, 0400); |
30 | MODULE_PARM_DESC(dif, "Enable DIF data integrity support (default off)" ); |
31 | |
32 | bool zfcp_experimental_dix; |
33 | module_param_named(dix, zfcp_experimental_dix, bool, 0400); |
34 | MODULE_PARM_DESC(dix, "Enable experimental DIX (data integrity extension) support which implies DIF support (default off)" ); |
35 | |
36 | static bool allow_lun_scan = true; |
37 | module_param(allow_lun_scan, bool, 0600); |
38 | MODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs" ); |
39 | |
40 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdev) |
41 | { |
42 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
43 | |
44 | /* if previous slave_alloc returned early, there is nothing to do */ |
45 | if (!zfcp_sdev->port) |
46 | return; |
47 | |
48 | zfcp_erp_lun_shutdown_wait(sdev, "scssd_1" ); |
49 | put_device(dev: &zfcp_sdev->port->dev); |
50 | } |
51 | |
52 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) |
53 | { |
54 | if (sdp->tagged_supported) |
55 | scsi_change_queue_depth(sdp, default_depth); |
56 | return 0; |
57 | } |
58 | |
59 | static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) |
60 | { |
61 | set_host_byte(cmd: scpnt, status: result); |
62 | zfcp_dbf_scsi_fail_send(scmd: scpnt); |
63 | scsi_done(cmd: scpnt); |
64 | } |
65 | |
66 | static |
67 | int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt) |
68 | { |
69 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev: scpnt->device); |
70 | struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device)); |
71 | int status, scsi_result, ret; |
72 | |
73 | /* reset the status for this request */ |
74 | scpnt->result = 0; |
75 | scpnt->host_scribble = NULL; |
76 | |
77 | scsi_result = fc_remote_port_chkready(rport); |
78 | if (unlikely(scsi_result)) { |
79 | scpnt->result = scsi_result; |
80 | zfcp_dbf_scsi_fail_send(scmd: scpnt); |
81 | scsi_done(cmd: scpnt); |
82 | return 0; |
83 | } |
84 | |
85 | status = atomic_read(v: &zfcp_sdev->status); |
86 | if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) && |
87 | !(atomic_read(v: &zfcp_sdev->port->status) & |
88 | ZFCP_STATUS_COMMON_ERP_FAILED)) { |
89 | /* only LUN access denied, but port is good |
90 | * not covered by FC transport, have to fail here */ |
91 | zfcp_scsi_command_fail(scpnt, result: DID_ERROR); |
92 | return 0; |
93 | } |
94 | |
95 | if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) { |
96 | /* This could be |
97 | * call to rport_delete pending: mimic retry from |
98 | * fc_remote_port_chkready until rport is BLOCKED |
99 | */ |
100 | zfcp_scsi_command_fail(scpnt, result: DID_IMM_RETRY); |
101 | return 0; |
102 | } |
103 | |
104 | ret = zfcp_fsf_fcp_cmnd(scpnt); |
105 | if (unlikely(ret == -EBUSY)) |
106 | return SCSI_MLQUEUE_DEVICE_BUSY; |
107 | else if (unlikely(ret < 0)) |
108 | return SCSI_MLQUEUE_HOST_BUSY; |
109 | |
110 | return ret; |
111 | } |
112 | |
113 | static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) |
114 | { |
115 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
116 | struct zfcp_adapter *adapter = |
117 | (struct zfcp_adapter *) sdev->host->hostdata[0]; |
118 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
119 | struct zfcp_port *port; |
120 | struct zfcp_unit *unit; |
121 | int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE; |
122 | |
123 | zfcp_sdev->erp_action.adapter = adapter; |
124 | zfcp_sdev->erp_action.sdev = sdev; |
125 | |
126 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); |
127 | if (!port) |
128 | return -ENXIO; |
129 | |
130 | zfcp_sdev->erp_action.port = port; |
131 | |
132 | mutex_lock(&zfcp_sysfs_port_units_mutex); |
133 | if (zfcp_sysfs_port_is_removing(port)) { |
134 | /* port is already gone */ |
135 | mutex_unlock(lock: &zfcp_sysfs_port_units_mutex); |
136 | put_device(dev: &port->dev); /* undo zfcp_get_port_by_wwpn() */ |
137 | return -ENXIO; |
138 | } |
139 | mutex_unlock(lock: &zfcp_sysfs_port_units_mutex); |
140 | |
141 | unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev)); |
142 | if (unit) |
143 | put_device(dev: &unit->dev); |
144 | |
145 | if (!unit && !(allow_lun_scan && npiv)) { |
146 | put_device(dev: &port->dev); |
147 | return -ENXIO; |
148 | } |
149 | |
150 | zfcp_sdev->port = port; |
151 | zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF; |
152 | zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF; |
153 | zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF; |
154 | zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF; |
155 | zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF; |
156 | zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF; |
157 | spin_lock_init(&zfcp_sdev->latencies.lock); |
158 | |
159 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING); |
160 | zfcp_erp_lun_reopen(sdev, 0, "scsla_1" ); |
161 | zfcp_erp_wait(port->adapter); |
162 | |
163 | return 0; |
164 | } |
165 | |
166 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
167 | { |
168 | struct Scsi_Host *scsi_host = scpnt->device->host; |
169 | struct zfcp_adapter *adapter = |
170 | (struct zfcp_adapter *) scsi_host->hostdata[0]; |
171 | struct zfcp_fsf_req *old_req, *abrt_req; |
172 | unsigned long flags; |
173 | u64 old_reqid = (u64) scpnt->host_scribble; |
174 | int retval = SUCCESS, ret; |
175 | int retry = 3; |
176 | char *dbf_tag; |
177 | |
178 | /* avoid race condition between late normal completion and abort */ |
179 | write_lock_irqsave(&adapter->abort_lock, flags); |
180 | |
181 | old_req = zfcp_reqlist_find(rl: adapter->req_list, req_id: old_reqid); |
182 | if (!old_req) { |
183 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
184 | zfcp_dbf_scsi_abort(tag: "abrt_or" , scmd: scpnt, NULL); |
185 | return FAILED; /* completion could be in progress */ |
186 | } |
187 | old_req->data = NULL; |
188 | |
189 | /* don't access old fsf_req after releasing the abort_lock */ |
190 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
191 | |
192 | while (retry--) { |
193 | abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt); |
194 | if (abrt_req) |
195 | break; |
196 | |
197 | zfcp_dbf_scsi_abort(tag: "abrt_wt" , scmd: scpnt, NULL); |
198 | zfcp_erp_wait(adapter); |
199 | ret = fc_block_scsi_eh(cmnd: scpnt); |
200 | if (ret) { |
201 | zfcp_dbf_scsi_abort(tag: "abrt_bl" , scmd: scpnt, NULL); |
202 | return ret; |
203 | } |
204 | if (!(atomic_read(v: &adapter->status) & |
205 | ZFCP_STATUS_COMMON_RUNNING)) { |
206 | zfcp_dbf_scsi_abort(tag: "abrt_ru" , scmd: scpnt, NULL); |
207 | return SUCCESS; |
208 | } |
209 | } |
210 | if (!abrt_req) { |
211 | zfcp_dbf_scsi_abort(tag: "abrt_ar" , scmd: scpnt, NULL); |
212 | return FAILED; |
213 | } |
214 | |
215 | wait_for_completion(&abrt_req->completion); |
216 | |
217 | if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) |
218 | dbf_tag = "abrt_ok" ; |
219 | else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) |
220 | dbf_tag = "abrt_nn" ; |
221 | else { |
222 | dbf_tag = "abrt_fa" ; |
223 | retval = FAILED; |
224 | } |
225 | zfcp_dbf_scsi_abort(tag: dbf_tag, scmd: scpnt, fsf_req: abrt_req); |
226 | zfcp_fsf_req_free(abrt_req); |
227 | return retval; |
228 | } |
229 | |
230 | struct zfcp_scsi_req_filter { |
231 | u8 tmf_scope; |
232 | u32 lun_handle; |
233 | u32 port_handle; |
234 | }; |
235 | |
236 | static void zfcp_scsi_forget_cmnd(struct zfcp_fsf_req *old_req, void *data) |
237 | { |
238 | struct zfcp_scsi_req_filter *filter = |
239 | (struct zfcp_scsi_req_filter *)data; |
240 | |
241 | /* already aborted - prevent side-effects - or not a SCSI command */ |
242 | if (old_req->data == NULL || |
243 | zfcp_fsf_req_is_status_read_buffer(req: old_req) || |
244 | old_req->qtcb->header.fsf_command != FSF_QTCB_FCP_CMND) |
245 | return; |
246 | |
247 | /* (tmf_scope == FCP_TMF_TGT_RESET || tmf_scope == FCP_TMF_LUN_RESET) */ |
248 | if (old_req->qtcb->header.port_handle != filter->port_handle) |
249 | return; |
250 | |
251 | if (filter->tmf_scope == FCP_TMF_LUN_RESET && |
252 | old_req->qtcb->header.lun_handle != filter->lun_handle) |
253 | return; |
254 | |
255 | zfcp_dbf_scsi_nullcmnd(scmnd: (struct scsi_cmnd *)old_req->data, fsf_req: old_req); |
256 | old_req->data = NULL; |
257 | } |
258 | |
259 | static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags) |
260 | { |
261 | struct zfcp_adapter *adapter = zsdev->port->adapter; |
262 | struct zfcp_scsi_req_filter filter = { |
263 | .tmf_scope = FCP_TMF_TGT_RESET, |
264 | .port_handle = zsdev->port->handle, |
265 | }; |
266 | unsigned long flags; |
267 | |
268 | if (tm_flags == FCP_TMF_LUN_RESET) { |
269 | filter.tmf_scope = FCP_TMF_LUN_RESET; |
270 | filter.lun_handle = zsdev->lun_handle; |
271 | } |
272 | |
273 | /* |
274 | * abort_lock secures against other processings - in the abort-function |
275 | * and normal cmnd-handler - of (struct zfcp_fsf_req *)->data |
276 | */ |
277 | write_lock_irqsave(&adapter->abort_lock, flags); |
278 | zfcp_reqlist_apply_for_all(rl: adapter->req_list, f: zfcp_scsi_forget_cmnd, |
279 | data: &filter); |
280 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
281 | } |
282 | |
283 | /** |
284 | * zfcp_scsi_task_mgmt_function() - Send a task management function (sync). |
285 | * @sdev: Pointer to SCSI device to send the task management command to. |
286 | * @tm_flags: Task management flags, |
287 | * here we only handle %FCP_TMF_TGT_RESET or %FCP_TMF_LUN_RESET. |
288 | */ |
289 | static int zfcp_scsi_task_mgmt_function(struct scsi_device *sdev, u8 tm_flags) |
290 | { |
291 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); |
292 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; |
293 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
294 | struct zfcp_fsf_req *fsf_req = NULL; |
295 | int retval = SUCCESS, ret; |
296 | int retry = 3; |
297 | |
298 | while (retry--) { |
299 | fsf_req = zfcp_fsf_fcp_task_mgmt(sdev, tm_flags); |
300 | if (fsf_req) |
301 | break; |
302 | |
303 | zfcp_dbf_scsi_devreset(tag: "wait" , sdev, flag: tm_flags, NULL); |
304 | zfcp_erp_wait(adapter); |
305 | ret = fc_block_rport(rport); |
306 | if (ret) { |
307 | zfcp_dbf_scsi_devreset(tag: "fiof" , sdev, flag: tm_flags, NULL); |
308 | return ret; |
309 | } |
310 | |
311 | if (!(atomic_read(v: &adapter->status) & |
312 | ZFCP_STATUS_COMMON_RUNNING)) { |
313 | zfcp_dbf_scsi_devreset(tag: "nres" , sdev, flag: tm_flags, NULL); |
314 | return SUCCESS; |
315 | } |
316 | } |
317 | if (!fsf_req) { |
318 | zfcp_dbf_scsi_devreset(tag: "reqf" , sdev, flag: tm_flags, NULL); |
319 | return FAILED; |
320 | } |
321 | |
322 | wait_for_completion(&fsf_req->completion); |
323 | |
324 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { |
325 | zfcp_dbf_scsi_devreset(tag: "fail" , sdev, flag: tm_flags, fsf_req); |
326 | retval = FAILED; |
327 | } else { |
328 | zfcp_dbf_scsi_devreset(tag: "okay" , sdev, flag: tm_flags, fsf_req); |
329 | zfcp_scsi_forget_cmnds(zsdev: zfcp_sdev, tm_flags); |
330 | } |
331 | |
332 | zfcp_fsf_req_free(fsf_req); |
333 | return retval; |
334 | } |
335 | |
336 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) |
337 | { |
338 | struct scsi_device *sdev = scpnt->device; |
339 | |
340 | return zfcp_scsi_task_mgmt_function(sdev, FCP_TMF_LUN_RESET); |
341 | } |
342 | |
343 | static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) |
344 | { |
345 | struct scsi_target *starget = scsi_target(sdev: scpnt->device); |
346 | struct fc_rport *rport = starget_to_rport(starget); |
347 | struct Scsi_Host *shost = rport_to_shost(rport); |
348 | struct scsi_device *sdev = NULL, *tmp_sdev; |
349 | struct zfcp_adapter *adapter = |
350 | (struct zfcp_adapter *)shost->hostdata[0]; |
351 | int ret; |
352 | |
353 | shost_for_each_device(tmp_sdev, shost) { |
354 | if (tmp_sdev->id == starget->id) { |
355 | sdev = tmp_sdev; |
356 | break; |
357 | } |
358 | } |
359 | if (!sdev) { |
360 | ret = FAILED; |
361 | zfcp_dbf_scsi_eh(tag: "tr_nosd" , adapter, scsi_id: starget->id, ret); |
362 | return ret; |
363 | } |
364 | |
365 | ret = zfcp_scsi_task_mgmt_function(sdev, FCP_TMF_TGT_RESET); |
366 | |
367 | /* release reference from above shost_for_each_device */ |
368 | if (sdev) |
369 | scsi_device_put(tmp_sdev); |
370 | |
371 | return ret; |
372 | } |
373 | |
374 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
375 | { |
376 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev: scpnt->device); |
377 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; |
378 | int ret = SUCCESS, fc_ret; |
379 | |
380 | if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) { |
381 | zfcp_erp_port_forced_reopen_all(adapter, clear: 0, dbftag: "schrh_p" ); |
382 | zfcp_erp_wait(adapter); |
383 | } |
384 | zfcp_erp_adapter_reopen(adapter, 0, "schrh_1" ); |
385 | zfcp_erp_wait(adapter); |
386 | fc_ret = fc_block_scsi_eh(cmnd: scpnt); |
387 | if (fc_ret) |
388 | ret = fc_ret; |
389 | |
390 | zfcp_dbf_scsi_eh(tag: "schrh_r" , adapter, scsi_id: ~0, ret); |
391 | return ret; |
392 | } |
393 | |
394 | /** |
395 | * zfcp_scsi_sysfs_host_reset() - Support scsi_host sysfs attribute host_reset. |
396 | * @shost: Pointer to Scsi_Host to perform action on. |
397 | * @reset_type: We support %SCSI_ADAPTER_RESET but not %SCSI_FIRMWARE_RESET. |
398 | * |
399 | * Return: 0 on %SCSI_ADAPTER_RESET, -%EOPNOTSUPP otherwise. |
400 | * |
401 | * This is similar to zfcp_sysfs_adapter_failed_store(). |
402 | */ |
403 | static int zfcp_scsi_sysfs_host_reset(struct Scsi_Host *shost, int reset_type) |
404 | { |
405 | struct zfcp_adapter *adapter = |
406 | (struct zfcp_adapter *)shost->hostdata[0]; |
407 | int ret = 0; |
408 | |
409 | if (reset_type != SCSI_ADAPTER_RESET) { |
410 | ret = -EOPNOTSUPP; |
411 | zfcp_dbf_scsi_eh(tag: "scshr_n" , adapter, scsi_id: ~0, ret); |
412 | return ret; |
413 | } |
414 | |
415 | zfcp_erp_adapter_reset_sync(adapter, dbftag: "scshr_y" ); |
416 | return ret; |
417 | } |
418 | |
419 | struct scsi_transport_template *zfcp_scsi_transport_template; |
420 | |
421 | static const struct scsi_host_template zfcp_scsi_host_template = { |
422 | .module = THIS_MODULE, |
423 | .name = "zfcp" , |
424 | .queuecommand = zfcp_scsi_queuecommand, |
425 | .eh_timed_out = fc_eh_timed_out, |
426 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, |
427 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, |
428 | .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler, |
429 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, |
430 | .slave_alloc = zfcp_scsi_slave_alloc, |
431 | .slave_configure = zfcp_scsi_slave_configure, |
432 | .slave_destroy = zfcp_scsi_slave_destroy, |
433 | .change_queue_depth = scsi_change_queue_depth, |
434 | .host_reset = zfcp_scsi_sysfs_host_reset, |
435 | .proc_name = "zfcp" , |
436 | .can_queue = 4096, |
437 | .this_id = -1, |
438 | .sg_tablesize = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1) |
439 | * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2), |
440 | /* GCD, adjusted later */ |
441 | .max_sectors = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1) |
442 | * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8, |
443 | /* GCD, adjusted later */ |
444 | /* report size limit per scatter-gather segment */ |
445 | .max_segment_size = ZFCP_QDIO_SBALE_LEN, |
446 | .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1, |
447 | .shost_groups = zfcp_sysfs_shost_attr_groups, |
448 | .sdev_groups = zfcp_sysfs_sdev_attr_groups, |
449 | .track_queue_depth = 1, |
450 | .supported_mode = MODE_INITIATOR, |
451 | }; |
452 | |
453 | /** |
454 | * zfcp_scsi_adapter_register() - Allocate and register SCSI and FC host with |
455 | * SCSI midlayer |
456 | * @adapter: The zfcp adapter to register with the SCSI midlayer |
457 | * |
458 | * Allocates the SCSI host object for the given adapter, sets basic properties |
459 | * (such as the transport template, QDIO limits, ...), and registers it with |
460 | * the midlayer. |
461 | * |
462 | * During registration with the midlayer the corresponding FC host object for |
463 | * the referenced transport class is also implicitely allocated. |
464 | * |
465 | * Upon success adapter->scsi_host is set, and upon failure it remains NULL. If |
466 | * adapter->scsi_host is already set, nothing is done. |
467 | * |
468 | * Return: |
469 | * * 0 - Allocation and registration was successful |
470 | * * -EEXIST - SCSI and FC host did already exist, nothing was done, nothing |
471 | * was changed |
472 | * * -EIO - Allocation or registration failed |
473 | */ |
474 | int zfcp_scsi_adapter_register(struct zfcp_adapter *adapter) |
475 | { |
476 | struct ccw_dev_id dev_id; |
477 | |
478 | if (adapter->scsi_host) |
479 | return -EEXIST; |
480 | |
481 | ccw_device_get_id(adapter->ccw_device, &dev_id); |
482 | /* register adapter as SCSI host with mid layer of SCSI stack */ |
483 | adapter->scsi_host = scsi_host_alloc(&zfcp_scsi_host_template, |
484 | sizeof (struct zfcp_adapter *)); |
485 | if (!adapter->scsi_host) |
486 | goto err_out; |
487 | |
488 | /* tell the SCSI stack some characteristics of this adapter */ |
489 | adapter->scsi_host->max_id = 511; |
490 | adapter->scsi_host->max_lun = 0xFFFFFFFF; |
491 | adapter->scsi_host->max_channel = 0; |
492 | adapter->scsi_host->unique_id = dev_id.devno; |
493 | adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */ |
494 | adapter->scsi_host->transportt = zfcp_scsi_transport_template; |
495 | |
496 | /* make all basic properties known at registration time */ |
497 | zfcp_qdio_shost_update(adapter, qdio: adapter->qdio); |
498 | zfcp_scsi_set_prot(adapter); |
499 | |
500 | adapter->scsi_host->hostdata[0] = (unsigned long) adapter; |
501 | |
502 | if (scsi_add_host(host: adapter->scsi_host, dev: &adapter->ccw_device->dev)) { |
503 | scsi_host_put(t: adapter->scsi_host); |
504 | goto err_out; |
505 | } |
506 | |
507 | return 0; |
508 | err_out: |
509 | adapter->scsi_host = NULL; |
510 | dev_err(&adapter->ccw_device->dev, |
511 | "Registering the FCP device with the SCSI stack failed\n" ); |
512 | return -EIO; |
513 | } |
514 | |
515 | /** |
516 | * zfcp_scsi_adapter_unregister - Unregister SCSI and FC host from SCSI midlayer |
517 | * @adapter: The zfcp adapter to unregister. |
518 | */ |
519 | void zfcp_scsi_adapter_unregister(struct zfcp_adapter *adapter) |
520 | { |
521 | struct Scsi_Host *shost; |
522 | struct zfcp_port *port; |
523 | |
524 | shost = adapter->scsi_host; |
525 | if (!shost) |
526 | return; |
527 | |
528 | read_lock_irq(&adapter->port_list_lock); |
529 | list_for_each_entry(port, &adapter->port_list, list) |
530 | port->rport = NULL; |
531 | read_unlock_irq(&adapter->port_list_lock); |
532 | |
533 | fc_remove_host(shost); |
534 | scsi_remove_host(shost); |
535 | scsi_host_put(t: shost); |
536 | adapter->scsi_host = NULL; |
537 | } |
538 | |
539 | static struct fc_host_statistics* |
540 | zfcp_scsi_init_fc_host_stats(struct zfcp_adapter *adapter) |
541 | { |
542 | struct fc_host_statistics *fc_stats; |
543 | |
544 | if (!adapter->fc_stats) { |
545 | fc_stats = kmalloc(size: sizeof(*fc_stats), GFP_KERNEL); |
546 | if (!fc_stats) |
547 | return NULL; |
548 | adapter->fc_stats = fc_stats; /* freed in adapter_release */ |
549 | } |
550 | memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats)); |
551 | return adapter->fc_stats; |
552 | } |
553 | |
554 | static void zfcp_scsi_adjust_fc_host_stats(struct fc_host_statistics *fc_stats, |
555 | struct fsf_qtcb_bottom_port *data, |
556 | struct fsf_qtcb_bottom_port *old) |
557 | { |
558 | fc_stats->seconds_since_last_reset = |
559 | data->seconds_since_last_reset - old->seconds_since_last_reset; |
560 | fc_stats->tx_frames = data->tx_frames - old->tx_frames; |
561 | fc_stats->tx_words = data->tx_words - old->tx_words; |
562 | fc_stats->rx_frames = data->rx_frames - old->rx_frames; |
563 | fc_stats->rx_words = data->rx_words - old->rx_words; |
564 | fc_stats->lip_count = data->lip - old->lip; |
565 | fc_stats->nos_count = data->nos - old->nos; |
566 | fc_stats->error_frames = data->error_frames - old->error_frames; |
567 | fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames; |
568 | fc_stats->link_failure_count = data->link_failure - old->link_failure; |
569 | fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync; |
570 | fc_stats->loss_of_signal_count = |
571 | data->loss_of_signal - old->loss_of_signal; |
572 | fc_stats->prim_seq_protocol_err_count = |
573 | data->psp_error_counts - old->psp_error_counts; |
574 | fc_stats->invalid_tx_word_count = |
575 | data->invalid_tx_words - old->invalid_tx_words; |
576 | fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs; |
577 | fc_stats->fcp_input_requests = |
578 | data->input_requests - old->input_requests; |
579 | fc_stats->fcp_output_requests = |
580 | data->output_requests - old->output_requests; |
581 | fc_stats->fcp_control_requests = |
582 | data->control_requests - old->control_requests; |
583 | fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb; |
584 | fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb; |
585 | } |
586 | |
587 | static void zfcp_scsi_set_fc_host_stats(struct fc_host_statistics *fc_stats, |
588 | struct fsf_qtcb_bottom_port *data) |
589 | { |
590 | fc_stats->seconds_since_last_reset = data->seconds_since_last_reset; |
591 | fc_stats->tx_frames = data->tx_frames; |
592 | fc_stats->tx_words = data->tx_words; |
593 | fc_stats->rx_frames = data->rx_frames; |
594 | fc_stats->rx_words = data->rx_words; |
595 | fc_stats->lip_count = data->lip; |
596 | fc_stats->nos_count = data->nos; |
597 | fc_stats->error_frames = data->error_frames; |
598 | fc_stats->dumped_frames = data->dumped_frames; |
599 | fc_stats->link_failure_count = data->link_failure; |
600 | fc_stats->loss_of_sync_count = data->loss_of_sync; |
601 | fc_stats->loss_of_signal_count = data->loss_of_signal; |
602 | fc_stats->prim_seq_protocol_err_count = data->psp_error_counts; |
603 | fc_stats->invalid_tx_word_count = data->invalid_tx_words; |
604 | fc_stats->invalid_crc_count = data->invalid_crcs; |
605 | fc_stats->fcp_input_requests = data->input_requests; |
606 | fc_stats->fcp_output_requests = data->output_requests; |
607 | fc_stats->fcp_control_requests = data->control_requests; |
608 | fc_stats->fcp_input_megabytes = data->input_mb; |
609 | fc_stats->fcp_output_megabytes = data->output_mb; |
610 | } |
611 | |
612 | static struct fc_host_statistics * |
613 | zfcp_scsi_get_fc_host_stats(struct Scsi_Host *host) |
614 | { |
615 | struct zfcp_adapter *adapter; |
616 | struct fc_host_statistics *fc_stats; |
617 | struct fsf_qtcb_bottom_port *data; |
618 | int ret; |
619 | |
620 | adapter = (struct zfcp_adapter *)host->hostdata[0]; |
621 | fc_stats = zfcp_scsi_init_fc_host_stats(adapter); |
622 | if (!fc_stats) |
623 | return NULL; |
624 | |
625 | data = kzalloc(size: sizeof(*data), GFP_KERNEL); |
626 | if (!data) |
627 | return NULL; |
628 | |
629 | ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data); |
630 | if (ret != 0 && ret != -EAGAIN) { |
631 | kfree(objp: data); |
632 | return NULL; |
633 | } |
634 | |
635 | if (adapter->stats_reset && |
636 | ((jiffies/HZ - adapter->stats_reset) < |
637 | data->seconds_since_last_reset)) |
638 | zfcp_scsi_adjust_fc_host_stats(fc_stats, data, |
639 | old: adapter->stats_reset_data); |
640 | else |
641 | zfcp_scsi_set_fc_host_stats(fc_stats, data); |
642 | |
643 | kfree(objp: data); |
644 | return fc_stats; |
645 | } |
646 | |
647 | static void zfcp_scsi_reset_fc_host_stats(struct Scsi_Host *shost) |
648 | { |
649 | struct zfcp_adapter *adapter; |
650 | struct fsf_qtcb_bottom_port *data; |
651 | int ret; |
652 | |
653 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; |
654 | data = kzalloc(size: sizeof(*data), GFP_KERNEL); |
655 | if (!data) |
656 | return; |
657 | |
658 | ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data); |
659 | if (ret != 0 && ret != -EAGAIN) |
660 | kfree(objp: data); |
661 | else { |
662 | adapter->stats_reset = jiffies/HZ; |
663 | kfree(objp: adapter->stats_reset_data); |
664 | adapter->stats_reset_data = data; /* finally freed in |
665 | adapter_release */ |
666 | } |
667 | } |
668 | |
669 | static void zfcp_scsi_get_host_port_state(struct Scsi_Host *shost) |
670 | { |
671 | struct zfcp_adapter *adapter = |
672 | (struct zfcp_adapter *)shost->hostdata[0]; |
673 | int status = atomic_read(v: &adapter->status); |
674 | |
675 | if ((status & ZFCP_STATUS_COMMON_RUNNING) && |
676 | !(status & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)) |
677 | fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; |
678 | else if (status & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED) |
679 | fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; |
680 | else if (status & ZFCP_STATUS_COMMON_ERP_FAILED) |
681 | fc_host_port_state(shost) = FC_PORTSTATE_ERROR; |
682 | else |
683 | fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; |
684 | } |
685 | |
686 | static void zfcp_scsi_set_rport_dev_loss_tmo(struct fc_rport *rport, |
687 | u32 timeout) |
688 | { |
689 | rport->dev_loss_tmo = timeout; |
690 | } |
691 | |
692 | /** |
693 | * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport |
694 | * @rport: The FC rport where to teminate I/O |
695 | * |
696 | * Abort all pending SCSI commands for a port by closing the |
697 | * port. Using a reopen avoids a conflict with a shutdown |
698 | * overwriting a reopen. The "forced" ensures that a disappeared port |
699 | * is not opened again as valid due to the cached plogi data in |
700 | * non-NPIV mode. |
701 | */ |
702 | static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) |
703 | { |
704 | struct zfcp_port *port; |
705 | struct Scsi_Host *shost = rport_to_shost(rport); |
706 | struct zfcp_adapter *adapter = |
707 | (struct zfcp_adapter *)shost->hostdata[0]; |
708 | |
709 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); |
710 | |
711 | if (port) { |
712 | zfcp_erp_port_forced_reopen(port, 0, "sctrpi1" ); |
713 | put_device(dev: &port->dev); |
714 | } else { |
715 | zfcp_erp_port_forced_no_port_dbf( |
716 | dbftag: "sctrpin" , adapter, |
717 | port_name: rport->port_name /* zfcp_scsi_rport_register */, |
718 | port_id: rport->port_id /* zfcp_scsi_rport_register */); |
719 | } |
720 | } |
721 | |
722 | static void zfcp_scsi_rport_register(struct zfcp_port *port) |
723 | { |
724 | struct fc_rport_identifiers ids; |
725 | struct fc_rport *rport; |
726 | |
727 | if (port->rport) |
728 | return; |
729 | |
730 | ids.node_name = port->wwnn; |
731 | ids.port_name = port->wwpn; |
732 | ids.port_id = port->d_id; |
733 | ids.roles = FC_RPORT_ROLE_FCP_TARGET; |
734 | |
735 | zfcp_dbf_rec_trig_lock(tag: "scpaddy" , adapter: port->adapter, port, NULL, |
736 | want: ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, |
737 | need: ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); |
738 | rport = fc_remote_port_add(shost: port->adapter->scsi_host, channel: 0, ids: &ids); |
739 | if (!rport) { |
740 | dev_err(&port->adapter->ccw_device->dev, |
741 | "Registering port 0x%016Lx failed\n" , |
742 | (unsigned long long)port->wwpn); |
743 | return; |
744 | } |
745 | |
746 | rport->maxframe_size = port->maxframe_size; |
747 | rport->supported_classes = port->supported_classes; |
748 | port->rport = rport; |
749 | port->starget_id = rport->scsi_target_id; |
750 | |
751 | zfcp_unit_queue_scsi_scan(port); |
752 | } |
753 | |
754 | static void zfcp_scsi_rport_block(struct zfcp_port *port) |
755 | { |
756 | struct fc_rport *rport = port->rport; |
757 | |
758 | if (rport) { |
759 | zfcp_dbf_rec_trig_lock(tag: "scpdely" , adapter: port->adapter, port, NULL, |
760 | want: ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, |
761 | need: ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); |
762 | fc_remote_port_delete(rport); |
763 | port->rport = NULL; |
764 | } |
765 | } |
766 | |
767 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) |
768 | { |
769 | get_device(dev: &port->dev); |
770 | port->rport_task = RPORT_ADD; |
771 | |
772 | if (!queue_work(wq: port->adapter->work_queue, work: &port->rport_work)) |
773 | put_device(dev: &port->dev); |
774 | } |
775 | |
776 | void zfcp_scsi_schedule_rport_block(struct zfcp_port *port) |
777 | { |
778 | get_device(dev: &port->dev); |
779 | port->rport_task = RPORT_DEL; |
780 | |
781 | if (port->rport && queue_work(wq: port->adapter->work_queue, |
782 | work: &port->rport_work)) |
783 | return; |
784 | |
785 | put_device(dev: &port->dev); |
786 | } |
787 | |
788 | void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter) |
789 | { |
790 | unsigned long flags; |
791 | struct zfcp_port *port; |
792 | |
793 | read_lock_irqsave(&adapter->port_list_lock, flags); |
794 | list_for_each_entry(port, &adapter->port_list, list) |
795 | zfcp_scsi_schedule_rport_block(port); |
796 | read_unlock_irqrestore(&adapter->port_list_lock, flags); |
797 | } |
798 | |
799 | void zfcp_scsi_rport_work(struct work_struct *work) |
800 | { |
801 | struct zfcp_port *port = container_of(work, struct zfcp_port, |
802 | rport_work); |
803 | |
804 | set_worker_desc("zrp%c-%16llx" , |
805 | (port->rport_task == RPORT_ADD) ? 'a' : 'd', |
806 | port->wwpn); /* < WORKER_DESC_LEN=24 */ |
807 | while (port->rport_task) { |
808 | if (port->rport_task == RPORT_ADD) { |
809 | port->rport_task = RPORT_NONE; |
810 | zfcp_scsi_rport_register(port); |
811 | } else { |
812 | port->rport_task = RPORT_NONE; |
813 | zfcp_scsi_rport_block(port); |
814 | } |
815 | } |
816 | |
817 | put_device(dev: &port->dev); |
818 | } |
819 | |
820 | /** |
821 | * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host |
822 | * @adapter: The adapter where to configure DIF/DIX for the SCSI host |
823 | */ |
824 | void zfcp_scsi_set_prot(struct zfcp_adapter *adapter) |
825 | { |
826 | unsigned int mask = 0; |
827 | unsigned int data_div; |
828 | struct Scsi_Host *shost = adapter->scsi_host; |
829 | |
830 | data_div = atomic_read(v: &adapter->status) & |
831 | ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED; |
832 | |
833 | if ((enable_dif || zfcp_experimental_dix) && |
834 | adapter->adapter_features & FSF_FEATURE_DIF_PROT_TYPE1) |
835 | mask |= SHOST_DIF_TYPE1_PROTECTION; |
836 | |
837 | if (zfcp_experimental_dix && data_div && |
838 | adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) { |
839 | mask |= SHOST_DIX_TYPE1_PROTECTION; |
840 | scsi_host_set_guard(shost, type: SHOST_DIX_GUARD_IP); |
841 | shost->sg_prot_tablesize = adapter->qdio->max_sbale_per_req / 2; |
842 | shost->sg_tablesize = adapter->qdio->max_sbale_per_req / 2; |
843 | shost->max_sectors = shost->sg_tablesize * 8; |
844 | } |
845 | |
846 | scsi_host_set_prot(shost, mask); |
847 | } |
848 | |
849 | /** |
850 | * zfcp_scsi_dif_sense_error - Report DIF/DIX error as driver sense error |
851 | * @scmd: The SCSI command to report the error for |
852 | * @ascq: The ASCQ to put in the sense buffer |
853 | * |
854 | * See the error handling in sd_done for the sense codes used here. |
855 | * Set DID_SOFT_ERROR to retry the request, if possible. |
856 | */ |
857 | void zfcp_scsi_dif_sense_error(struct scsi_cmnd *scmd, int ascq) |
858 | { |
859 | scsi_build_sense(scmd, desc: 1, ILLEGAL_REQUEST, asc: 0x10, ascq); |
860 | set_host_byte(cmd: scmd, status: DID_SOFT_ERROR); |
861 | } |
862 | |
863 | void zfcp_scsi_shost_update_config_data( |
864 | struct zfcp_adapter *const adapter, |
865 | const struct fsf_qtcb_bottom_config *const bottom, |
866 | const bool bottom_incomplete) |
867 | { |
868 | struct Scsi_Host *const shost = adapter->scsi_host; |
869 | const struct fc_els_flogi *nsp, *plogi; |
870 | |
871 | if (shost == NULL) |
872 | return; |
873 | |
874 | snprintf(fc_host_firmware_version(shost), FC_VERSION_STRING_SIZE, |
875 | fmt: "0x%08x" , bottom->lic_version); |
876 | |
877 | if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { |
878 | snprintf(fc_host_hardware_version(shost), |
879 | FC_VERSION_STRING_SIZE, |
880 | fmt: "0x%08x" , bottom->hardware_version); |
881 | memcpy(fc_host_serial_number(shost), bottom->serial_number, |
882 | min(FC_SERIAL_NUMBER_SIZE, 17)); |
883 | EBCASC(fc_host_serial_number(shost), |
884 | min(FC_SERIAL_NUMBER_SIZE, 17)); |
885 | } |
886 | |
887 | /* adjust pointers for missing command code */ |
888 | nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param |
889 | - sizeof(u32)); |
890 | plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload |
891 | - sizeof(u32)); |
892 | |
893 | snprintf(fc_host_manufacturer(shost), FC_SERIAL_NUMBER_SIZE, fmt: "%s" , |
894 | "IBM" ); |
895 | fc_host_port_name(shost) = be64_to_cpu(nsp->fl_wwpn); |
896 | fc_host_node_name(shost) = be64_to_cpu(nsp->fl_wwnn); |
897 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; |
898 | |
899 | zfcp_scsi_set_prot(adapter); |
900 | |
901 | /* do not evaluate invalid fields */ |
902 | if (bottom_incomplete) |
903 | return; |
904 | |
905 | fc_host_port_id(shost) = ntoh24(p: bottom->s_id); |
906 | fc_host_speed(shost) = |
907 | zfcp_fsf_convert_portspeed(fsf_speed: bottom->fc_link_speed); |
908 | |
909 | snprintf(fc_host_model(shost), FC_SYMBOLIC_NAME_SIZE, fmt: "0x%04x" , |
910 | bottom->adapter_type); |
911 | |
912 | switch (bottom->fc_topology) { |
913 | case FSF_TOPO_P2P: |
914 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; |
915 | fc_host_fabric_name(shost) = 0; |
916 | break; |
917 | case FSF_TOPO_FABRIC: |
918 | fc_host_fabric_name(shost) = be64_to_cpu(plogi->fl_wwnn); |
919 | if (bottom->connection_features & FSF_FEATURE_NPIV_MODE) |
920 | fc_host_port_type(shost) = FC_PORTTYPE_NPIV; |
921 | else |
922 | fc_host_port_type(shost) = FC_PORTTYPE_NPORT; |
923 | break; |
924 | case FSF_TOPO_AL: |
925 | fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; |
926 | fallthrough; |
927 | default: |
928 | fc_host_fabric_name(shost) = 0; |
929 | break; |
930 | } |
931 | } |
932 | |
933 | void zfcp_scsi_shost_update_port_data( |
934 | struct zfcp_adapter *const adapter, |
935 | const struct fsf_qtcb_bottom_port *const bottom) |
936 | { |
937 | struct Scsi_Host *const shost = adapter->scsi_host; |
938 | |
939 | if (shost == NULL) |
940 | return; |
941 | |
942 | fc_host_permanent_port_name(shost) = bottom->wwpn; |
943 | fc_host_maxframe_size(shost) = bottom->maximum_frame_size; |
944 | fc_host_supported_speeds(shost) = |
945 | zfcp_fsf_convert_portspeed(fsf_speed: bottom->supported_speed); |
946 | memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, |
947 | FC_FC4_LIST_SIZE); |
948 | memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, |
949 | FC_FC4_LIST_SIZE); |
950 | } |
951 | |
952 | struct fc_function_template zfcp_transport_functions = { |
953 | .show_starget_port_id = 1, |
954 | .show_starget_port_name = 1, |
955 | .show_starget_node_name = 1, |
956 | .show_rport_supported_classes = 1, |
957 | .show_rport_maxframe_size = 1, |
958 | .show_rport_dev_loss_tmo = 1, |
959 | .show_host_node_name = 1, |
960 | .show_host_port_name = 1, |
961 | .show_host_permanent_port_name = 1, |
962 | .show_host_supported_classes = 1, |
963 | .show_host_supported_fc4s = 1, |
964 | .show_host_supported_speeds = 1, |
965 | .show_host_maxframe_size = 1, |
966 | .show_host_serial_number = 1, |
967 | .show_host_manufacturer = 1, |
968 | .show_host_model = 1, |
969 | .show_host_hardware_version = 1, |
970 | .show_host_firmware_version = 1, |
971 | .get_fc_host_stats = zfcp_scsi_get_fc_host_stats, |
972 | .reset_fc_host_stats = zfcp_scsi_reset_fc_host_stats, |
973 | .set_rport_dev_loss_tmo = zfcp_scsi_set_rport_dev_loss_tmo, |
974 | .get_host_port_state = zfcp_scsi_get_host_port_state, |
975 | .terminate_rport_io = zfcp_scsi_terminate_rport_io, |
976 | .show_host_port_state = 1, |
977 | .show_host_active_fc4s = 1, |
978 | .bsg_request = zfcp_fc_exec_bsg_job, |
979 | .bsg_timeout = zfcp_fc_timeout_bsg_job, |
980 | /* no functions registered for following dynamic attributes but |
981 | directly set by LLDD */ |
982 | .show_host_port_type = 1, |
983 | .show_host_symbolic_name = 1, |
984 | .show_host_speed = 1, |
985 | .show_host_port_id = 1, |
986 | .show_host_fabric_name = 1, |
987 | .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els), |
988 | }; |
989 | |