zfcp_scsi.c 28.4 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
 * zfcp device driver
Linus Torvalds's avatar
Linus Torvalds committed
4
 *
5
 * Interface to Linux SCSI midlayer.
6
 *
7
 * Copyright IBM Corp. 2002, 2020
Linus Torvalds's avatar
Linus Torvalds committed
8 9
 */

10 11 12
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

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>
Arun Sharma's avatar
Arun Sharma committed
18
#include <linux/atomic.h>
19 20
#include "zfcp_ext.h"
#include "zfcp_dbf.h"
21
#include "zfcp_fc.h"
22
#include "zfcp_reqlist.h"
Linus Torvalds's avatar
Linus Torvalds committed
23

24 25 26 27
static unsigned int default_depth = 32;
module_param_named(queue_depth, default_depth, uint, 0600);
MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices");

28
static bool enable_dif;
29
module_param_named(dif, enable_dif, bool, 0400);
30 31 32 33 34
MODULE_PARM_DESC(dif, "Enable DIF data integrity support (default off)");

bool zfcp_experimental_dix;
module_param_named(dix, zfcp_experimental_dix, bool, 0400);
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 38 39
module_param(allow_lun_scan, bool, 0600);
MODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs");

40
static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
Linus Torvalds's avatar
Linus Torvalds committed
41
{
42 43
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);

44 45 46 47
	/* if previous slave_alloc returned early, there is nothing to do */
	if (!zfcp_sdev->port)
		return;

48 49
	zfcp_erp_lun_shutdown_wait(sdev, "scssd_1");
	put_device(&zfcp_sdev->port->dev);
Linus Torvalds's avatar
Linus Torvalds committed
50 51
}

52
static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
Linus Torvalds's avatar
Linus Torvalds committed
53 54
{
	if (sdp->tagged_supported)
55
		scsi_change_queue_depth(sdp, default_depth);
Linus Torvalds's avatar
Linus Torvalds committed
56 57 58
	return 0;
}

59
static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
Linus Torvalds's avatar
Linus Torvalds committed
60
{
61
	set_host_byte(scpnt, result);
62
	zfcp_dbf_scsi_fail_send(scpnt);
Linus Torvalds's avatar
Linus Torvalds committed
63 64 65
	scpnt->scsi_done(scpnt);
}

66 67
static
int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
Linus Torvalds's avatar
Linus Torvalds committed
68
{
69
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
70
	struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
71
	int    status, scsi_result, ret;
Linus Torvalds's avatar
Linus Torvalds committed
72 73 74 75 76

	/* reset the status for this request */
	scpnt->result = 0;
	scpnt->host_scribble = NULL;

77 78 79
	scsi_result = fc_remote_port_chkready(rport);
	if (unlikely(scsi_result)) {
		scpnt->result = scsi_result;
80
		zfcp_dbf_scsi_fail_send(scpnt);
81 82 83 84
		scpnt->scsi_done(scpnt);
		return 0;
	}

85
	status = atomic_read(&zfcp_sdev->status);
86
	if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) &&
87
		     !(atomic_read(&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, DID_ERROR);
92
		return 0;
93 94
	}

95
	if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
96
		/* This could be
97 98 99 100 101 102 103
		 * call to rport_delete pending: mimic retry from
		 * 	fc_remote_port_chkready until rport is BLOCKED
		 */
		zfcp_scsi_command_fail(scpnt, DID_IMM_RETRY);
		return 0;
	}

104
	ret = zfcp_fsf_fcp_cmnd(scpnt);
105
	if (unlikely(ret == -EBUSY))
106
		return SCSI_MLQUEUE_DEVICE_BUSY;
107 108
	else if (unlikely(ret < 0))
		return SCSI_MLQUEUE_HOST_BUSY;
Linus Torvalds's avatar
Linus Torvalds committed
109

110
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
111 112
}

113
static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
Linus Torvalds's avatar
Linus Torvalds committed
114
{
115 116 117 118
	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
	struct zfcp_adapter *adapter =
		(struct zfcp_adapter *) sdev->host->hostdata[0];
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
Linus Torvalds's avatar
Linus Torvalds committed
119
	struct zfcp_port *port;
120
	struct zfcp_unit *unit;
121
	int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE;
Linus Torvalds's avatar
Linus Torvalds committed
122

123 124 125
	zfcp_sdev->erp_action.adapter = adapter;
	zfcp_sdev->erp_action.sdev = sdev;

126 127 128
	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
	if (!port)
		return -ENXIO;
129

130 131
	zfcp_sdev->erp_action.port = port;

132 133 134 135 136 137 138 139 140
	mutex_lock(&zfcp_sysfs_port_units_mutex);
	if (zfcp_sysfs_port_is_removing(port)) {
		/* port is already gone */
		mutex_unlock(&zfcp_sysfs_port_units_mutex);
		put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */
		return -ENXIO;
	}
	mutex_unlock(&zfcp_sysfs_port_units_mutex);

141 142 143
	unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
	if (unit)
		put_device(&unit->dev);
144

145
	if (!unit && !(allow_lun_scan && npiv)) {
146 147
		put_device(&port->dev);
		return -ENXIO;
148 149
	}

150 151 152 153 154 155 156 157
	zfcp_sdev->port = port;
	zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF;
	zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF;
	zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF;
	zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF;
	zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF;
	zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF;
	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 162 163
	zfcp_erp_wait(port->adapter);

	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
164 165
}

166
static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
Linus Torvalds's avatar
Linus Torvalds committed
167
{
168 169 170 171
	struct Scsi_Host *scsi_host = scpnt->device->host;
	struct zfcp_adapter *adapter =
		(struct zfcp_adapter *) scsi_host->hostdata[0];
	struct zfcp_fsf_req *old_req, *abrt_req;
Linus Torvalds's avatar
Linus Torvalds committed
172
	unsigned long flags;
173
	unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
174
	int retval = SUCCESS, ret;
175
	int retry = 3;
176
	char *dbf_tag;
Linus Torvalds's avatar
Linus Torvalds committed
177

178
	/* avoid race condition between late normal completion and abort */
Linus Torvalds's avatar
Linus Torvalds committed
179 180
	write_lock_irqsave(&adapter->abort_lock, flags);

181
	old_req = zfcp_reqlist_find(adapter->req_list, old_reqid);
182
	if (!old_req) {
Linus Torvalds's avatar
Linus Torvalds committed
183
		write_unlock_irqrestore(&adapter->abort_lock, flags);
184
		zfcp_dbf_scsi_abort("abrt_or", scpnt, NULL);
185
		return FAILED; /* completion could be in progress */
Linus Torvalds's avatar
Linus Torvalds committed
186
	}
187
	old_req->data = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
188

189
	/* don't access old fsf_req after releasing the abort_lock */
Linus Torvalds's avatar
Linus Torvalds committed
190
	write_unlock_irqrestore(&adapter->abort_lock, flags);
191

192
	while (retry--) {
193
		abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt);
194 195 196
		if (abrt_req)
			break;

197
		zfcp_dbf_scsi_abort("abrt_wt", scpnt, NULL);
198
		zfcp_erp_wait(adapter);
199
		ret = fc_block_scsi_eh(scpnt);
200 201
		if (ret) {
			zfcp_dbf_scsi_abort("abrt_bl", scpnt, NULL);
202
			return ret;
203
		}
204 205
		if (!(atomic_read(&adapter->status) &
		      ZFCP_STATUS_COMMON_RUNNING)) {
206
			zfcp_dbf_scsi_abort("abrt_ru", scpnt, NULL);
207 208
			return SUCCESS;
		}
Linus Torvalds's avatar
Linus Torvalds committed
209
	}
210 211
	if (!abrt_req) {
		zfcp_dbf_scsi_abort("abrt_ar", scpnt, NULL);
212
		return FAILED;
213
	}
Linus Torvalds's avatar
Linus Torvalds committed
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";
Linus Torvalds's avatar
Linus Torvalds committed
223 224
		retval = FAILED;
	}
225
	zfcp_dbf_scsi_abort(dbf_tag, scpnt, abrt_req);
226
	zfcp_fsf_req_free(abrt_req);
227
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
228 229
}

230 231 232 233 234 235 236 237 238 239 240 241
struct zfcp_scsi_req_filter {
	u8 tmf_scope;
	u32 lun_handle;
	u32 port_handle;
};

static void zfcp_scsi_forget_cmnd(struct zfcp_fsf_req *old_req, void *data)
{
	struct zfcp_scsi_req_filter *filter =
		(struct zfcp_scsi_req_filter *)data;

	/* already aborted - prevent side-effects - or not a SCSI command */
242 243 244
	if (old_req->data == NULL ||
	    zfcp_fsf_req_is_status_read_buffer(old_req) ||
	    old_req->qtcb->header.fsf_command != FSF_QTCB_FCP_CMND)
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
		return;

	/* (tmf_scope == FCP_TMF_TGT_RESET || tmf_scope == FCP_TMF_LUN_RESET) */
	if (old_req->qtcb->header.port_handle != filter->port_handle)
		return;

	if (filter->tmf_scope == FCP_TMF_LUN_RESET &&
	    old_req->qtcb->header.lun_handle != filter->lun_handle)
		return;

	zfcp_dbf_scsi_nullcmnd((struct scsi_cmnd *)old_req->data, old_req);
	old_req->data = NULL;
}

static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags)
{
	struct zfcp_adapter *adapter = zsdev->port->adapter;
	struct zfcp_scsi_req_filter filter = {
		.tmf_scope = FCP_TMF_TGT_RESET,
		.port_handle = zsdev->port->handle,
	};
	unsigned long flags;

	if (tm_flags == FCP_TMF_LUN_RESET) {
		filter.tmf_scope = FCP_TMF_LUN_RESET;
		filter.lun_handle = zsdev->lun_handle;
	}

	/*
	 * abort_lock secures against other processings - in the abort-function
	 * and normal cmnd-handler - of (struct zfcp_fsf_req *)->data
	 */
	write_lock_irqsave(&adapter->abort_lock, flags);
	zfcp_reqlist_apply_for_all(adapter->req_list, zfcp_scsi_forget_cmnd,
				   &filter);
	write_unlock_irqrestore(&adapter->abort_lock, flags);
}

283
/**
284
 * zfcp_scsi_task_mgmt_function() - Send a task management function (sync).
285 286 287 288
 * @sdev: Pointer to SCSI device to send the task management command to.
 * @tm_flags: Task management flags,
 *	      here we only handle %FCP_TMF_TGT_RESET or %FCP_TMF_LUN_RESET.
 */
289
static int zfcp_scsi_task_mgmt_function(struct scsi_device *sdev, u8 tm_flags)
Linus Torvalds's avatar
Linus Torvalds committed
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 297 298
	int retry = 3;

	while (retry--) {
299
		fsf_req = zfcp_fsf_fcp_task_mgmt(sdev, tm_flags);
300 301 302
		if (fsf_req)
			break;

303
		zfcp_dbf_scsi_devreset("wait", sdev, tm_flags, NULL);
304
		zfcp_erp_wait(adapter);
305
		ret = fc_block_rport(rport);
306
		if (ret) {
307
			zfcp_dbf_scsi_devreset("fiof", sdev, tm_flags, NULL);
308
			return ret;
309
		}
310

311 312
		if (!(atomic_read(&adapter->status) &
		      ZFCP_STATUS_COMMON_RUNNING)) {
313
			zfcp_dbf_scsi_devreset("nres", sdev, tm_flags, NULL);
314 315
			return SUCCESS;
		}
Linus Torvalds's avatar
Linus Torvalds committed
316
	}
317
	if (!fsf_req) {
318
		zfcp_dbf_scsi_devreset("reqf", sdev, tm_flags, NULL);
319
		return FAILED;
320
	}
Linus Torvalds's avatar
Linus Torvalds committed
321

322
	wait_for_completion(&fsf_req->completion);
323

324
	if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
325
		zfcp_dbf_scsi_devreset("fail", sdev, tm_flags, fsf_req);
326
		retval = FAILED;
327
	} else {
328
		zfcp_dbf_scsi_devreset("okay", sdev, tm_flags, fsf_req);
329 330
		zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags);
	}
331 332

	zfcp_fsf_req_free(fsf_req);
Linus Torvalds's avatar
Linus Torvalds committed
333 334 335
	return retval;
}

336 337
static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
{
338 339
	struct scsi_device *sdev = scpnt->device;

340
	return zfcp_scsi_task_mgmt_function(sdev, FCP_TMF_LUN_RESET);
341 342 343 344
}

static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
{
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
	struct scsi_target *starget = scsi_target(scpnt->device);
	struct fc_rport *rport = starget_to_rport(starget);
	struct Scsi_Host *shost = rport_to_shost(rport);
	struct scsi_device *sdev = NULL, *tmp_sdev;
	struct zfcp_adapter *adapter =
		(struct zfcp_adapter *)shost->hostdata[0];
	int ret;

	shost_for_each_device(tmp_sdev, shost) {
		if (tmp_sdev->id == starget->id) {
			sdev = tmp_sdev;
			break;
		}
	}
	if (!sdev) {
		ret = FAILED;
		zfcp_dbf_scsi_eh("tr_nosd", adapter, starget->id, ret);
		return ret;
	}

365
	ret = zfcp_scsi_task_mgmt_function(sdev, FCP_TMF_TGT_RESET);
366 367 368 369 370 371

	/* release reference from above shost_for_each_device */
	if (sdev)
		scsi_device_put(tmp_sdev);

	return ret;
372 373
}

374
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
Linus Torvalds's avatar
Linus Torvalds committed
375
{
376 377
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
378
	int ret = SUCCESS, fc_ret;
Linus Torvalds's avatar
Linus Torvalds committed
379

380 381 382 383
	if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) {
		zfcp_erp_port_forced_reopen_all(adapter, 0, "schrh_p");
		zfcp_erp_wait(adapter);
	}
384
	zfcp_erp_adapter_reopen(adapter, 0, "schrh_1");
385
	zfcp_erp_wait(adapter);
386 387 388
	fc_ret = fc_block_scsi_eh(scpnt);
	if (fc_ret)
		ret = fc_ret;
Linus Torvalds's avatar
Linus Torvalds committed
389

390 391
	zfcp_dbf_scsi_eh("schrh_r", adapter, ~0, ret);
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
392 393
}

394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
/**
 * zfcp_scsi_sysfs_host_reset() - Support scsi_host sysfs attribute host_reset.
 * @shost: Pointer to Scsi_Host to perform action on.
 * @reset_type: We support %SCSI_ADAPTER_RESET but not %SCSI_FIRMWARE_RESET.
 *
 * Return: 0 on %SCSI_ADAPTER_RESET, -%EOPNOTSUPP otherwise.
 *
 * This is similar to zfcp_sysfs_adapter_failed_store().
 */
static int zfcp_scsi_sysfs_host_reset(struct Scsi_Host *shost, int reset_type)
{
	struct zfcp_adapter *adapter =
		(struct zfcp_adapter *)shost->hostdata[0];
	int ret = 0;

	if (reset_type != SCSI_ADAPTER_RESET) {
		ret = -EOPNOTSUPP;
		zfcp_dbf_scsi_eh("scshr_n", adapter, ~0, ret);
412
		return ret;
413
	}
Linus Torvalds's avatar
Linus Torvalds committed
414

415 416
	zfcp_erp_adapter_reset_sync(adapter, "scshr_y");
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
417 418
}

419 420 421 422 423 424
struct scsi_transport_template *zfcp_scsi_transport_template;

static struct scsi_host_template zfcp_scsi_host_template = {
	.module			 = THIS_MODULE,
	.name			 = "zfcp",
	.queuecommand		 = zfcp_scsi_queuecommand,
425
	.eh_timed_out		 = fc_eh_timed_out,
426 427 428 429 430 431 432
	.eh_abort_handler	 = zfcp_scsi_eh_abort_handler,
	.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
	.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
	.eh_host_reset_handler	 = zfcp_scsi_eh_host_reset_handler,
	.slave_alloc		 = zfcp_scsi_slave_alloc,
	.slave_configure	 = zfcp_scsi_slave_configure,
	.slave_destroy		 = zfcp_scsi_slave_destroy,
433
	.change_queue_depth	 = scsi_change_queue_depth,
434
	.host_reset		 = zfcp_scsi_sysfs_host_reset,
435 436 437
	.proc_name		 = "zfcp",
	.can_queue		 = 4096,
	.this_id		 = -1,
438 439 440 441 442 443
	.sg_tablesize		 = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
				     * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2),
				   /* GCD, adjusted later */
	.max_sectors		 = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
				     * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8,
				   /* GCD, adjusted later */
444 445
	/* report size limit per scatter-gather segment */
	.max_segment_size	 = ZFCP_QDIO_SBALE_LEN,
446 447 448
	.dma_boundary		 = ZFCP_QDIO_SBALE_LEN - 1,
	.shost_attrs		 = zfcp_sysfs_shost_attrs,
	.sdev_attrs		 = zfcp_sysfs_sdev_attrs,
449
	.track_queue_depth	 = 1,
450
	.supported_mode		 = MODE_INITIATOR,
451 452 453 454 455 456 457
};

/**
 * zfcp_scsi_adapter_register - Register SCSI and FC host with SCSI midlayer
 * @adapter: The zfcp adapter to register with the SCSI midlayer
 */
int zfcp_scsi_adapter_register(struct zfcp_adapter *adapter)
Linus Torvalds's avatar
Linus Torvalds committed
458
{
459
	struct ccw_dev_id dev_id;
Linus Torvalds's avatar
Linus Torvalds committed
460

461
	if (adapter->scsi_host)
462
		return 0;
463

464
	ccw_device_get_id(adapter->ccw_device, &dev_id);
Linus Torvalds's avatar
Linus Torvalds committed
465
	/* register adapter as SCSI host with mid layer of SCSI stack */
466
	adapter->scsi_host = scsi_host_alloc(&zfcp_scsi_host_template,
Linus Torvalds's avatar
Linus Torvalds committed
467 468
					     sizeof (struct zfcp_adapter *));
	if (!adapter->scsi_host) {
469
		dev_err(&adapter->ccw_device->dev,
470 471
			"Registering the FCP device with the "
			"SCSI stack failed\n");
472
		return -EIO;
Linus Torvalds's avatar
Linus Torvalds committed
473 474 475
	}

	/* tell the SCSI stack some characteristics of this adapter */
476 477
	adapter->scsi_host->max_id = 511;
	adapter->scsi_host->max_lun = 0xFFFFFFFF;
Linus Torvalds's avatar
Linus Torvalds committed
478
	adapter->scsi_host->max_channel = 0;
479
	adapter->scsi_host->unique_id = dev_id.devno;
480
	adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
481
	adapter->scsi_host->transportt = zfcp_scsi_transport_template;
Linus Torvalds's avatar
Linus Torvalds committed
482 483 484 485 486

	adapter->scsi_host->hostdata[0] = (unsigned long) adapter;

	if (scsi_add_host(adapter->scsi_host, &adapter->ccw_device->dev)) {
		scsi_host_put(adapter->scsi_host);
487
		return -EIO;
Linus Torvalds's avatar
Linus Torvalds committed
488
	}
489 490

	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
491 492
}

493 494 495 496 497
/**
 * zfcp_scsi_adapter_unregister - Unregister SCSI and FC host from SCSI midlayer
 * @adapter: The zfcp adapter to unregister.
 */
void zfcp_scsi_adapter_unregister(struct zfcp_adapter *adapter)
Linus Torvalds's avatar
Linus Torvalds committed
498 499
{
	struct Scsi_Host *shost;
500
	struct zfcp_port *port;
Linus Torvalds's avatar
Linus Torvalds committed
501 502 503 504

	shost = adapter->scsi_host;
	if (!shost)
		return;
505

506 507
	read_lock_irq(&adapter->port_list_lock);
	list_for_each_entry(port, &adapter->port_list, list)
508
		port->rport = NULL;
509
	read_unlock_irq(&adapter->port_list_lock);
510

511
	fc_remove_host(shost);
Linus Torvalds's avatar
Linus Torvalds committed
512 513 514 515 516
	scsi_remove_host(shost);
	scsi_host_put(shost);
	adapter->scsi_host = NULL;
}

517
static struct fc_host_statistics*
518
zfcp_scsi_init_fc_host_stats(struct zfcp_adapter *adapter)
Linus Torvalds's avatar
Linus Torvalds committed
519
{
520
	struct fc_host_statistics *fc_stats;
Linus Torvalds's avatar
Linus Torvalds committed
521

522 523 524 525
	if (!adapter->fc_stats) {
		fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
		if (!fc_stats)
			return NULL;
526
		adapter->fc_stats = fc_stats; /* freed in adapter_release */
527 528 529
	}
	memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
	return adapter->fc_stats;
Linus Torvalds's avatar
Linus Torvalds committed
530 531
}

532 533 534
static void zfcp_scsi_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
					   struct fsf_qtcb_bottom_port *data,
					   struct fsf_qtcb_bottom_port *old)
Linus Torvalds's avatar
Linus Torvalds committed
535
{
536 537
	fc_stats->seconds_since_last_reset =
		data->seconds_since_last_reset - old->seconds_since_last_reset;
538 539 540 541 542 543 544 545 546 547
	fc_stats->tx_frames = data->tx_frames - old->tx_frames;
	fc_stats->tx_words = data->tx_words - old->tx_words;
	fc_stats->rx_frames = data->rx_frames - old->rx_frames;
	fc_stats->rx_words = data->rx_words - old->rx_words;
	fc_stats->lip_count = data->lip - old->lip;
	fc_stats->nos_count = data->nos - old->nos;
	fc_stats->error_frames = data->error_frames - old->error_frames;
	fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;
	fc_stats->link_failure_count = data->link_failure - old->link_failure;
	fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;
548 549 550 551 552 553
	fc_stats->loss_of_signal_count =
		data->loss_of_signal - old->loss_of_signal;
	fc_stats->prim_seq_protocol_err_count =
		data->psp_error_counts - old->psp_error_counts;
	fc_stats->invalid_tx_word_count =
		data->invalid_tx_words - old->invalid_tx_words;
554
	fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;
555 556 557 558 559 560
	fc_stats->fcp_input_requests =
		data->input_requests - old->input_requests;
	fc_stats->fcp_output_requests =
		data->output_requests - old->output_requests;
	fc_stats->fcp_control_requests =
		data->control_requests - old->control_requests;
561 562 563
	fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;
	fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
}
Linus Torvalds's avatar
Linus Torvalds committed
564

565 566
static void zfcp_scsi_set_fc_host_stats(struct fc_host_statistics *fc_stats,
					struct fsf_qtcb_bottom_port *data)
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
{
	fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
	fc_stats->tx_frames = data->tx_frames;
	fc_stats->tx_words = data->tx_words;
	fc_stats->rx_frames = data->rx_frames;
	fc_stats->rx_words = data->rx_words;
	fc_stats->lip_count = data->lip;
	fc_stats->nos_count = data->nos;
	fc_stats->error_frames = data->error_frames;
	fc_stats->dumped_frames = data->dumped_frames;
	fc_stats->link_failure_count = data->link_failure;
	fc_stats->loss_of_sync_count = data->loss_of_sync;
	fc_stats->loss_of_signal_count = data->loss_of_signal;
	fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;
	fc_stats->invalid_tx_word_count = data->invalid_tx_words;
	fc_stats->invalid_crc_count = data->invalid_crcs;
	fc_stats->fcp_input_requests = data->input_requests;
	fc_stats->fcp_output_requests = data->output_requests;
	fc_stats->fcp_control_requests = data->control_requests;
	fc_stats->fcp_input_megabytes = data->input_mb;
	fc_stats->fcp_output_megabytes = data->output_mb;
}

590 591
static struct fc_host_statistics *
zfcp_scsi_get_fc_host_stats(struct Scsi_Host *host)
592 593 594 595 596 597
{
	struct zfcp_adapter *adapter;
	struct fc_host_statistics *fc_stats;
	struct fsf_qtcb_bottom_port *data;
	int ret;

598
	adapter = (struct zfcp_adapter *)host->hostdata[0];
599
	fc_stats = zfcp_scsi_init_fc_host_stats(adapter);
600 601 602
	if (!fc_stats)
		return NULL;

603
	data = kzalloc(sizeof(*data), GFP_KERNEL);
604 605 606
	if (!data)
		return NULL;

607
	ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
608
	if (ret != 0 && ret != -EAGAIN) {
609
		kfree(data);
610
		return NULL;
611 612 613 614
	}

	if (adapter->stats_reset &&
	    ((jiffies/HZ - adapter->stats_reset) <
615
	     data->seconds_since_last_reset))
616 617
		zfcp_scsi_adjust_fc_host_stats(fc_stats, data,
					       adapter->stats_reset_data);
618
	else
619
		zfcp_scsi_set_fc_host_stats(fc_stats, data);
620 621 622

	kfree(data);
	return fc_stats;
Linus Torvalds's avatar
Linus Torvalds committed
623 624
}

625
static void zfcp_scsi_reset_fc_host_stats(struct Scsi_Host *shost)
Linus Torvalds's avatar
Linus Torvalds committed
626
{
627
	struct zfcp_adapter *adapter;
628
	struct fsf_qtcb_bottom_port *data;
629
	int ret;
Linus Torvalds's avatar
Linus Torvalds committed
630

631
	adapter = (struct zfcp_adapter *)shost->hostdata[0];
632
	data = kzalloc(sizeof(*data), GFP_KERNEL);
633 634 635
	if (!data)
		return;

636
	ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
637
	if (ret != 0 && ret != -EAGAIN)
638
		kfree(data);
639
	else {
640
		adapter->stats_reset = jiffies/HZ;
641
		kfree(adapter->stats_reset_data);
642
		adapter->stats_reset_data = data; /* finally freed in
643
						     adapter_release */
644
	}
Linus Torvalds's avatar
Linus Torvalds committed
645 646
}

647
static void zfcp_scsi_get_host_port_state(struct Scsi_Host *shost)
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
{
	struct zfcp_adapter *adapter =
		(struct zfcp_adapter *)shost->hostdata[0];
	int status = atomic_read(&adapter->status);

	if ((status & ZFCP_STATUS_COMMON_RUNNING) &&
	    !(status & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED))
		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
	else if (status & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
	else if (status & ZFCP_STATUS_COMMON_ERP_FAILED)
		fc_host_port_state(shost) = FC_PORTSTATE_ERROR;
	else
		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
}

664 665
static void zfcp_scsi_set_rport_dev_loss_tmo(struct fc_rport *rport,
					     u32 timeout)
666 667 668 669
{
	rport->dev_loss_tmo = timeout;
}

670 671 672 673 674
/**
 * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport
 * @rport: The FC rport where to teminate I/O
 *
 * Abort all pending SCSI commands for a port by closing the
675 676 677 678
 * port. Using a reopen avoids a conflict with a shutdown
 * overwriting a reopen. The "forced" ensures that a disappeared port
 * is not opened again as valid due to the cached plogi data in
 * non-NPIV mode.
679 680 681
 */
static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
{
682
	struct zfcp_port *port;
683 684 685
	struct Scsi_Host *shost = rport_to_shost(rport);
	struct zfcp_adapter *adapter =
		(struct zfcp_adapter *)shost->hostdata[0];
686

687
	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
688

689
	if (port) {
690
		zfcp_erp_port_forced_reopen(port, 0, "sctrpi1");
691
		put_device(&port->dev);
692 693 694 695 696
	} else {
		zfcp_erp_port_forced_no_port_dbf(
			"sctrpin", adapter,
			rport->port_name /* zfcp_scsi_rport_register */,
			rport->port_id /* zfcp_scsi_rport_register */);
697
	}
698 699 700 701 702 703 704
}

static void zfcp_scsi_rport_register(struct zfcp_port *port)
{
	struct fc_rport_identifiers ids;
	struct fc_rport *rport;

705 706 707
	if (port->rport)
		return;

708 709 710 711 712
	ids.node_name = port->wwnn;
	ids.port_name = port->wwpn;
	ids.port_id = port->d_id;
	ids.roles = FC_RPORT_ROLE_FCP_TARGET;

713 714 715
	zfcp_dbf_rec_trig_lock("scpaddy", port->adapter, port, NULL,
			       ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
			       ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
716 717 718 719 720 721 722 723 724 725 726
	rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
	if (!rport) {
		dev_err(&port->adapter->ccw_device->dev,
			"Registering port 0x%016Lx failed\n",
			(unsigned long long)port->wwpn);
		return;
	}

	rport->maxframe_size = port->maxframe_size;
	rport->supported_classes = port->supported_classes;
	port->rport = rport;
727
	port->starget_id = rport->scsi_target_id;
728

729
	zfcp_unit_queue_scsi_scan(port);
730 731 732 733
}

static void zfcp_scsi_rport_block(struct zfcp_port *port)
{
734 735
	struct fc_rport *rport = port->rport;

736
	if (rport) {
737 738 739
		zfcp_dbf_rec_trig_lock("scpdely", port->adapter, port, NULL,
				       ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
				       ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
740
		fc_remote_port_delete(rport);
741 742
		port->rport = NULL;
	}
743 744 745 746
}

void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
{
747
	get_device(&port->dev);
748 749
	port->rport_task = RPORT_ADD;

750
	if (!queue_work(port->adapter->work_queue, &port->rport_work))
751
		put_device(&port->dev);
752 753 754 755
}

void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
{
756
	get_device(&port->dev);
757 758
	port->rport_task = RPORT_DEL;

759 760
	if (port->rport && queue_work(port->adapter->work_queue,
				      &port->rport_work))
761 762
		return;

763
	put_device(&port->dev);
764 765 766 767
}

void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
{
768
	unsigned long flags;
769 770
	struct zfcp_port *port;

771 772
	read_lock_irqsave(&adapter->port_list_lock, flags);
	list_for_each_entry(port, &adapter->port_list, list)
773
		zfcp_scsi_schedule_rport_block(port);
774
	read_unlock_irqrestore(&adapter->port_list_lock, flags);
775 776 777 778 779 780 781
}

void zfcp_scsi_rport_work(struct work_struct *work)
{
	struct zfcp_port *port = container_of(work, struct zfcp_port,
					      rport_work);

782 783 784
	set_worker_desc("zrp%c-%16llx",
			(port->rport_task == RPORT_ADD) ? 'a' : 'd',
			port->wwpn); /* < WORKER_DESC_LEN=24 */
785 786 787 788 789 790 791 792 793 794
	while (port->rport_task) {
		if (port->rport_task == RPORT_ADD) {
			port->rport_task = RPORT_NONE;
			zfcp_scsi_rport_register(port);
		} else {
			port->rport_task = RPORT_NONE;
			zfcp_scsi_rport_block(port);
		}
	}

795
	put_device(&port->dev);
796 797
}

798 799 800 801 802 803 804 805 806 807 808 809 810
/**
 * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host
 * @adapter: The adapter where to configure DIF/DIX for the SCSI host
 */
void zfcp_scsi_set_prot(struct zfcp_adapter *adapter)
{
	unsigned int mask = 0;
	unsigned int data_div;
	struct Scsi_Host *shost = adapter->scsi_host;

	data_div = atomic_read(&adapter->status) &
		   ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED;

811
	if ((enable_dif || zfcp_experimental_dix) &&
812 813 814
	    adapter->adapter_features & FSF_FEATURE_DIF_PROT_TYPE1)
		mask |= SHOST_DIF_TYPE1_PROTECTION;

815
	if (zfcp_experimental_dix && data_div &&
816 817 818
	    adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
		mask |= SHOST_DIX_TYPE1_PROTECTION;
		scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
819 820 821
		shost->sg_prot_tablesize = adapter->qdio->max_sbale_per_req / 2;
		shost->sg_tablesize = adapter->qdio->max_sbale_per_req / 2;
		shost->max_sectors = shost->sg_tablesize * 8;
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
	}

	scsi_host_set_prot(shost, mask);
}

/**
 * zfcp_scsi_dif_sense_error - Report DIF/DIX error as driver sense error
 * @scmd: The SCSI command to report the error for
 * @ascq: The ASCQ to put in the sense buffer
 *
 * See the error handling in sd_done for the sense codes used here.
 * Set DID_SOFT_ERROR to retry the request, if possible.
 */
void zfcp_scsi_dif_sense_error(struct scsi_cmnd *scmd, int ascq)
{
	scsi_build_sense_buffer(1, scmd->sense_buffer,
				ILLEGAL_REQUEST, 0x10, ascq);
	set_driver_byte(scmd, DRIVER_SENSE);
	scmd->result |= SAM_STAT_CHECK_CONDITION;
	set_host_byte(scmd, DID_SOFT_ERROR);
}

844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
void zfcp_scsi_shost_update_config_data(
	struct zfcp_adapter *const adapter,
	const struct fsf_qtcb_bottom_config *const bottom,
	const bool bottom_incomplete)
{
	struct Scsi_Host *const shost = adapter->scsi_host;
	const struct fc_els_flogi *nsp, *plogi;

	if (shost == NULL)
		return;

	snprintf(fc_host_firmware_version(shost), FC_VERSION_STRING_SIZE,
		 "0x%08x", bottom->lic_version);

	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
		snprintf(fc_host_hardware_version(shost),
			 FC_VERSION_STRING_SIZE,
			 "0x%08x", bottom->hardware_version);
		memcpy(fc_host_serial_number(shost), bottom->serial_number,
		       min(FC_SERIAL_NUMBER_SIZE, 17));
		EBCASC(fc_host_serial_number(shost),
		       min(FC_SERIAL_NUMBER_SIZE, 17));
	}

	/* adjust pointers for missing command code */
	nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param
					- sizeof(u32));
	plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload
					- sizeof(u32));

	snprintf(fc_host_manufacturer(shost), FC_SERIAL_NUMBER_SIZE, "%s",
		 "IBM");
	fc_host_port_name(shost) = be64_to_cpu(nsp->fl_wwpn);
	fc_host_node_name(shost) = be64_to_cpu(nsp->fl_wwnn);
	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;

	zfcp_scsi_set_prot(adapter);

	/* do not evaluate invalid fields */
	if (bottom_incomplete)
		return;

	fc_host_port_id(shost) = ntoh24(bottom->s_id);
	fc_host_speed(shost) =
		zfcp_fsf_convert_portspeed(bottom->fc_link_speed);

	snprintf(fc_host_model(shost), FC_SYMBOLIC_NAME_SIZE, "0x%04x",
		 bottom->adapter_type);

	switch (bottom->fc_topology) {
	case FSF_TOPO_P2P:
		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
		fc_host_fabric_name(shost) = 0;
		break;
	case FSF_TOPO_FABRIC:
		fc_host_fabric_name(shost) = be64_to_cpu(plogi->fl_wwnn);
		if (bottom->connection_features & FSF_FEATURE_NPIV_MODE)
			fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
		else
			fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
		break;
	case FSF_TOPO_AL:
		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
		fallthrough;
	default:
		fc_host_fabric_name(shost) = 0;
		break;
	}
}

914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
void zfcp_scsi_shost_update_port_data(
	struct zfcp_adapter *const adapter,
	const struct fsf_qtcb_bottom_port *const bottom)
{
	struct Scsi_Host *const shost = adapter->scsi_host;

	if (shost == NULL)
		return;

	fc_host_permanent_port_name(shost) = bottom->wwpn;
	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
	fc_host_supported_speeds(shost) =
		zfcp_fsf_convert_portspeed(bottom->supported_speed);
	memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
	       FC_FC4_LIST_SIZE);
	memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
	       FC_FC4_LIST_SIZE);
}

Linus Torvalds's avatar
Linus Torvalds committed
933 934 935 936
struct fc_function_template zfcp_transport_functions = {
	.show_starget_port_id = 1,
	.show_starget_port_name = 1,
	.show_starget_node_name = 1,
937
	.show_rport_supported_classes = 1,
938
	.show_rport_maxframe_size = 1,
939
	.show_rport_dev_loss_tmo = 1,
940 941
	.show_host_node_name = 1,
	.show_host_port_name = 1,
942
	.show_host_permanent_port_name = 1,
943
	.show_host_supported_classes = 1,
944
	.show_host_supported_fc4s = 1,
945
	.show_host_supported_speeds = 1,
946
	.show_host_maxframe_size = 1,
947
	.show_host_serial_number = 1,
948 949 950 951
	.show_host_manufacturer = 1,
	.show_host_model = 1,
	.show_host_hardware_version = 1,
	.show_host_firmware_version = 1,
952 953 954 955
	.get_fc_host_stats = zfcp_scsi_get_fc_host_stats,
	.reset_fc_host_stats = zfcp_scsi_reset_fc_host_stats,
	.set_rport_dev_loss_tmo = zfcp_scsi_set_rport_dev_loss_tmo,
	.get_host_port_state = zfcp_scsi_get_host_port_state,
956
	.terminate_rport_io = zfcp_scsi_terminate_rport_io,
957
	.show_host_port_state = 1,
958
	.show_host_active_fc4s = 1,
959
	.bsg_request = zfcp_fc_exec_bsg_job,
960
	.bsg_timeout = zfcp_fc_timeout_bsg_job,
961 962
	/* no functions registered for following dynamic attributes but
	   directly set by LLDD */
963
	.show_host_port_type = 1,
964
	.show_host_symbolic_name = 1,
965 966
	.show_host_speed = 1,
	.show_host_port_id = 1,
967
	.show_host_fabric_name = 1,
968
	.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
Linus Torvalds's avatar
Linus Torvalds committed
969
};