141fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig/*
2553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * zfcp device driver
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * Interface to Linux SCSI midlayer.
541fa2adabc0a750a40d6fe86d5ce2f75fb3ad287Swen Schillig *
6615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt * Copyright IBM Corporation 2002, 2010
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define KMSG_COMPONENT "zfcp"
10ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt
123a4c5d5964ed43a5524f6d289fb4cd37d39f3f1aHeiko Carstens#include <linux/module.h>
134318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt#include <linux/types.h>
145a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
154318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt#include <scsi/fc/fc_fcp.h>
16ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck#include <scsi/scsi_eh.h>
1760063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h>
18dcd20e2316cdc333dfdee09649dbe3642eb30e75Christof Schmitt#include "zfcp_ext.h"
19dcd20e2316cdc333dfdee09649dbe3642eb30e75Christof Schmitt#include "zfcp_dbf.h"
207c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt#include "zfcp_fc.h"
21b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt#include "zfcp_reqlist.h"
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof Schmittstatic unsigned int default_depth = 32;
24a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof Schmittmodule_param_named(queue_depth, default_depth, uint, 0600);
25a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof SchmittMODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices");
26a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof Schmitt
27ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beckstatic bool enable_dif;
28cc405acee244310cc87ddc5e3f4bc61342ec8161Steffen Maiermodule_param_named(dif, enable_dif, bool, 0400);
29ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix BeckMODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support");
30ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
310d81b4e8dcc4177726f30a1ac8df1f726d2a7c0cChristof Schmittstatic bool allow_lun_scan = 1;
320d81b4e8dcc4177726f30a1ac8df1f726d2a7c0cChristof Schmittmodule_param(allow_lun_scan, bool, 0600);
330d81b4e8dcc4177726f30a1ac8df1f726d2a7c0cChristof SchmittMODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs");
340d81b4e8dcc4177726f30a1ac8df1f726d2a7c0cChristof Schmitt
35e881a172dac4d9ea3b2a1540041d872963c269bdMike Christiestatic int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
36e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie					int reason)
37a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof Schmitt{
3842e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt	switch (reason) {
3942e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt	case SCSI_QDEPTH_DEFAULT:
4042e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
4142e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt		break;
4242e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt	case SCSI_QDEPTH_QFULL:
4342e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt		scsi_track_queue_full(sdev, depth);
4442e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt		break;
4542e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt	case SCSI_QDEPTH_RAMP_UP:
4642e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
4742e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt		break;
4842e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt	default:
49e881a172dac4d9ea3b2a1540041d872963c269bdMike Christie		return -EOPNOTSUPP;
5042e62a74377bcbb526565a31aa18da8f712b93eeChristof Schmitt	}
51a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof Schmitt	return sdev->queue_depth;
52a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof Schmitt}
53a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof Schmitt
54b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstatic void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
56b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
57b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt
5844f747fff6e9f027a4866c1a6864e26ae7c510c8Steffen Maier	/* if previous slave_alloc returned early, there is nothing to do */
5944f747fff6e9f027a4866c1a6864e26ae7c510c8Steffen Maier	if (!zfcp_sdev->port)
6044f747fff6e9f027a4866c1a6864e26ae7c510c8Steffen Maier		return;
6144f747fff6e9f027a4866c1a6864e26ae7c510c8Steffen Maier
62b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_erp_lun_shutdown_wait(sdev, "scssd_1");
63b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	put_device(&zfcp_sdev->port->dev);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
66f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermannstatic int zfcp_scsi_slave_configure(struct scsi_device *sdp)
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sdp->tagged_supported)
69a40a1bafe7da0afe61b1c20fc50e18c07ce724f9Christof Schmitt		scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, default_depth);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scsi_adjust_queue_depth(sdp, 0, 1);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
75f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermannstatic void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
77feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann	set_host_byte(scpnt, result);
78250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig	zfcp_dbf_scsi_fail_send(scpnt);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scpnt->scsi_done(scpnt);
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
82e55f87531c2c1eb071a296df7eb67f83d5f0b5dfChristof Schmittstatic
83e55f87531c2c1eb071a296df7eb67f83d5f0b5dfChristof Schmittint zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
85b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
86a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
87b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	int    status, scsi_result, ret;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* reset the status for this request */
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scpnt->result = 0;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scpnt->host_scribble = NULL;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
93a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	scsi_result = fc_remote_port_chkready(rport);
94a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	if (unlikely(scsi_result)) {
95a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		scpnt->result = scsi_result;
96250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig		zfcp_dbf_scsi_fail_send(scpnt);
97a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		scpnt->scsi_done(scpnt);
98a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		return 0;
99a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	}
100a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
101b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	status = atomic_read(&zfcp_sdev->status);
1028830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt	if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) &&
103b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		     !(atomic_read(&zfcp_sdev->port->status) &
1048830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt		       ZFCP_STATUS_COMMON_ERP_FAILED)) {
105b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		/* only LUN access denied, but port is good
1068830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt		 * not covered by FC transport, have to fail here */
107f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		zfcp_scsi_command_fail(scpnt, DID_ERROR);
108a419aef8b858a2bdb98df60336063d28df4b272fJoe Perches		return 0;
109f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	}
110f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
1118830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt	if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
1128830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt		/* This could be either
113b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		 * open LUN pending: this is temporary, will result in
114b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		 *	open LUN or ERP_FAILED, so retry command
1158830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt		 * call to rport_delete pending: mimic retry from
1168830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt		 * 	fc_remote_port_chkready until rport is BLOCKED
1178830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt		 */
1188830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt		zfcp_scsi_command_fail(scpnt, DID_IMM_RETRY);
1198830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt		return 0;
1208830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt	}
1218830271c4819d86d8e87202a1fe8da0bb58912a2Christof Schmitt
122b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	ret = zfcp_fsf_fcp_cmnd(scpnt);
123f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	if (unlikely(ret == -EBUSY))
124f7a65e92e4bef3ccf9e008ed8cd52d914b6a4adbSwen Schillig		return SCSI_MLQUEUE_DEVICE_BUSY;
125f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	else if (unlikely(ret < 0))
126f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		return SCSI_MLQUEUE_HOST_BUSY;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
128f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	return ret;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstatic int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
133b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
134b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_adapter *adapter =
135b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		(struct zfcp_adapter *) sdev->host->hostdata[0];
136b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zfcp_port *port;
138f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	struct zfcp_unit *unit;
1390d81b4e8dcc4177726f30a1ac8df1f726d2a7c0cChristof Schmitt	int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
142b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	if (!port)
143b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		return -ENXIO;
144f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
145b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
146b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	if (unit)
147b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		put_device(&unit->dev);
148f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
1490d81b4e8dcc4177726f30a1ac8df1f726d2a7c0cChristof Schmitt	if (!unit && !(allow_lun_scan && npiv)) {
150b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		put_device(&port->dev);
151b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		return -ENXIO;
152f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	}
153f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
154b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_sdev->port = port;
155b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF;
156b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF;
157b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF;
158b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF;
159b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF;
160b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF;
161b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	spin_lock_init(&zfcp_sdev->latencies.lock);
162f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
163edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig	zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
164ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig	zfcp_erp_lun_reopen(sdev, 0, "scsla_1");
165b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	zfcp_erp_wait(port->adapter);
166b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt
167b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	return 0;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1702b67fc46061b2171fb8fbb55d1ac717abd533569Heiko Carstensstatic int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17263caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	struct Scsi_Host *scsi_host = scpnt->device->host;
17363caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	struct zfcp_adapter *adapter =
17463caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		(struct zfcp_adapter *) scsi_host->hostdata[0];
17563caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	struct zfcp_fsf_req *old_req, *abrt_req;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
177a11a52be115889a5d1f738ed2e154807bceed4eeChristof Schmitt	unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
178a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt	int retval = SUCCESS, ret;
17963caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	int retry = 3;
180a11a52be115889a5d1f738ed2e154807bceed4eeChristof Schmitt	char *dbf_tag;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
182059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann	/* avoid race condition between late normal completion and abort */
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	write_lock_irqsave(&adapter->abort_lock, flags);
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
185b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt	old_req = zfcp_reqlist_find(adapter->req_list, old_reqid);
18663caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	if (!old_req) {
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		write_unlock_irqrestore(&adapter->abort_lock, flags);
188250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig		zfcp_dbf_scsi_abort("abrt_or", scpnt, NULL);
189c6936e7f34383db2f5038dfa2f0c168ebc2920e5Christof Schmitt		return FAILED; /* completion could be in progress */
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19163caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	old_req->data = NULL;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1934eff4a36516d72e4f6ede901141214a7e05607e7Andreas Herrmann	/* don't access old fsf_req after releasing the abort_lock */
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	write_unlock_irqrestore(&adapter->abort_lock, flags);
1954eff4a36516d72e4f6ede901141214a7e05607e7Andreas Herrmann
19663caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	while (retry--) {
197b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt);
19863caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		if (abrt_req)
19963caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt			break;
20063caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt
20163caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		zfcp_erp_wait(adapter);
202a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt		ret = fc_block_scsi_eh(scpnt);
203250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig		if (ret) {
204250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig			zfcp_dbf_scsi_abort("abrt_bl", scpnt, NULL);
205a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt			return ret;
206250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig		}
20763caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		if (!(atomic_read(&adapter->status) &
20863caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		      ZFCP_STATUS_COMMON_RUNNING)) {
209250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig			zfcp_dbf_scsi_abort("abrt_ru", scpnt, NULL);
21063caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt			return SUCCESS;
21163caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		}
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
213250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig	if (!abrt_req) {
214250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig		zfcp_dbf_scsi_abort("abrt_ar", scpnt, NULL);
21563caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		return FAILED;
216250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig	}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
218058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig	wait_for_completion(&abrt_req->completion);
219059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann
22063caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
221250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig		dbf_tag = "abrt_ok";
22263caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED)
223250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig		dbf_tag = "abrt_nn";
22463caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	else {
225250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig		dbf_tag = "abrt_fa";
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = FAILED;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
228250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig	zfcp_dbf_scsi_abort(dbf_tag, scpnt, abrt_req);
22963caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	zfcp_fsf_req_free(abrt_req);
230f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	return retval;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23363caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmittstatic int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
235b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
236b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
237564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_fsf_req *fsf_req = NULL;
238a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt	int retval = SUCCESS, ret;
23963caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	int retry = 3;
24063caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt
24163caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	while (retry--) {
242b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags);
24363caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		if (fsf_req)
24463caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt			break;
24563caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt
24663caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		zfcp_erp_wait(adapter);
247a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt		ret = fc_block_scsi_eh(scpnt);
248a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt		if (ret)
249a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt			return ret;
250a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt
25163caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		if (!(atomic_read(&adapter->status) &
25263caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		      ZFCP_STATUS_COMMON_RUNNING)) {
253b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags);
25463caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt			return SUCCESS;
25563caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		}
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25763caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	if (!fsf_req)
25863caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt		return FAILED;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
260058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig	wait_for_completion(&fsf_req->completion);
26177eb1699c76177af2f3d65c8ae7934cf304e0254Andreas Herrmann
2628a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin	if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
263b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
264f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		retval = FAILED;
2658a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin	} else
266b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
26777eb1699c76177af2f3d65c8ae7934cf304e0254Andreas Herrmann
26877eb1699c76177af2f3d65c8ae7934cf304e0254Andreas Herrmann	zfcp_fsf_req_free(fsf_req);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
272f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermannstatic int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
273f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann{
2744318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	return zfcp_task_mgmt_function(scpnt, FCP_TMF_LUN_RESET);
275f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann}
276f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
277f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermannstatic int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
278f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann{
2794318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	return zfcp_task_mgmt_function(scpnt, FCP_TMF_TGT_RESET);
280f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann}
281f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
2822b67fc46061b2171fb8fbb55d1ac717abd533569Heiko Carstensstatic int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
284b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
285b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
286a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt	int ret;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
288ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig	zfcp_erp_adapter_reopen(adapter, 0, "schrh_1");
2898165428610446ea9e6aa9dfa5485ab78e58cc9fcAndreas Herrmann	zfcp_erp_wait(adapter);
290a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt	ret = fc_block_scsi_eh(scpnt);
291a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt	if (ret)
292a1dbfddd02d2b3e75f8750c68563e1d6eec16260Christof Schmitt		return ret;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
294810f1e3ea5cc0a812816af97020a27c73441f8e9Andreas Herrmann	return SUCCESS;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmittstruct scsi_transport_template *zfcp_scsi_transport_template;
2981947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt
2991947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmittstatic struct scsi_host_template zfcp_scsi_host_template = {
3001947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.module			 = THIS_MODULE,
3011947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.name			 = "zfcp",
3021947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.queuecommand		 = zfcp_scsi_queuecommand,
3031947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.eh_abort_handler	 = zfcp_scsi_eh_abort_handler,
3041947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
3051947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
3061947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.eh_host_reset_handler	 = zfcp_scsi_eh_host_reset_handler,
3071947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.slave_alloc		 = zfcp_scsi_slave_alloc,
3081947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.slave_configure	 = zfcp_scsi_slave_configure,
3091947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.slave_destroy		 = zfcp_scsi_slave_destroy,
3101947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.change_queue_depth	 = zfcp_scsi_change_queue_depth,
3111947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.proc_name		 = "zfcp",
3121947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.can_queue		 = 4096,
3131947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.this_id		 = -1,
31486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	.sg_tablesize		 = 1, /* adjusted later */
31586a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	.max_sectors		 = 8, /* adjusted later */
3161947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.dma_boundary		 = ZFCP_QDIO_SBALE_LEN - 1,
3171947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.cmd_per_lun		 = 1,
3181947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.use_clustering		 = 1,
3191947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.shost_attrs		 = zfcp_sysfs_shost_attrs,
3201947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	.sdev_attrs		 = zfcp_sysfs_sdev_attrs,
3211947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt};
3221947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt
3231947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt/**
3241947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt * zfcp_scsi_adapter_register - Register SCSI and FC host with SCSI midlayer
3251947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt * @adapter: The zfcp adapter to register with the SCSI midlayer
3261947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt */
3271947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmittint zfcp_scsi_adapter_register(struct zfcp_adapter *adapter)
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
329f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	struct ccw_dev_id dev_id;
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3319f28745a6b554fdd6b0dbc9856077701a55f9569Michael Loehr	if (adapter->scsi_host)
332f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		return 0;
3339f28745a6b554fdd6b0dbc9856077701a55f9569Michael Loehr
334f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	ccw_device_get_id(adapter->ccw_device, &dev_id);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* register adapter as SCSI host with mid layer of SCSI stack */
3361947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	adapter->scsi_host = scsi_host_alloc(&zfcp_scsi_host_template,
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     sizeof (struct zfcp_adapter *));
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!adapter->scsi_host) {
339553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt		dev_err(&adapter->ccw_device->dev,
340ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"Registering the FCP device with the "
341ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"SCSI stack failed\n");
342f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		return -EIO;
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* tell the SCSI stack some characteristics of this adapter */
346f8210e34887e1feb977a9b6b8caa086855af40c9Christof Schmitt	adapter->scsi_host->max_id = 511;
347f8210e34887e1feb977a9b6b8caa086855af40c9Christof Schmitt	adapter->scsi_host->max_lun = 0xFFFFFFFF;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->scsi_host->max_channel = 0;
349f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	adapter->scsi_host->unique_id = dev_id.devno;
3504318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
3511947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt	adapter->scsi_host->transportt = zfcp_scsi_transport_template;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->scsi_host->hostdata[0] = (unsigned long) adapter;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (scsi_add_host(adapter->scsi_host, &adapter->ccw_device->dev)) {
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scsi_host_put(adapter->scsi_host);
357f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		return -EIO;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
359f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
360f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	return 0;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3631947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt/**
3641947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt * zfcp_scsi_adapter_unregister - Unregister SCSI and FC host from SCSI midlayer
3651947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt * @adapter: The zfcp adapter to unregister.
3661947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmitt */
3671947c72a122a8c367fdfc650c39a98ba76cc573aChristof Schmittvoid zfcp_scsi_adapter_unregister(struct zfcp_adapter *adapter)
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Scsi_Host *shost;
37013e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann	struct zfcp_port *port;
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	shost = adapter->scsi_host;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!shost)
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
375f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
376ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_lock_irq(&adapter->port_list_lock);
377ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	list_for_each_entry(port, &adapter->port_list, list)
378f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		port->rport = NULL;
379ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_unlock_irq(&adapter->port_list_lock);
380f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann
3813859f6a248cbdfbe7b41663f3a2b51f48e30b281Andreas Herrmann	fc_remove_host(shost);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_remove_host(shost);
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scsi_host_put(shost);
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adapter->scsi_host = NULL;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
387f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmannstatic struct fc_host_statistics*
388f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmannzfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
390f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	struct fc_host_statistics *fc_stats;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
392f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	if (!adapter->fc_stats) {
393f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
394f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		if (!fc_stats)
395f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann			return NULL;
396f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		adapter->fc_stats = fc_stats; /* freed in adapter_release */
397f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	}
398f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
399f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	return adapter->fc_stats;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
402f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermannstatic void zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
403f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann				      struct fsf_qtcb_bottom_port *data,
404f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann				      struct fsf_qtcb_bottom_port *old)
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
406f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	fc_stats->seconds_since_last_reset =
407f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		data->seconds_since_last_reset - old->seconds_since_last_reset;
408f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->tx_frames = data->tx_frames - old->tx_frames;
409f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->tx_words = data->tx_words - old->tx_words;
410f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->rx_frames = data->rx_frames - old->rx_frames;
411f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->rx_words = data->rx_words - old->rx_words;
412f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->lip_count = data->lip - old->lip;
413f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->nos_count = data->nos - old->nos;
414f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->error_frames = data->error_frames - old->error_frames;
415f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;
416f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->link_failure_count = data->link_failure - old->link_failure;
417f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;
418f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	fc_stats->loss_of_signal_count =
419f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		data->loss_of_signal - old->loss_of_signal;
420f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	fc_stats->prim_seq_protocol_err_count =
421f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		data->psp_error_counts - old->psp_error_counts;
422f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	fc_stats->invalid_tx_word_count =
423f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		data->invalid_tx_words - old->invalid_tx_words;
424f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;
425f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	fc_stats->fcp_input_requests =
426f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		data->input_requests - old->input_requests;
427f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	fc_stats->fcp_output_requests =
428f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		data->output_requests - old->output_requests;
429f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	fc_stats->fcp_control_requests =
430f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		data->control_requests - old->control_requests;
431f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;
432f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
433f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann}
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
435f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermannstatic void zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
436f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann				   struct fsf_qtcb_bottom_port *data)
437f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann{
438f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
439f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->tx_frames = data->tx_frames;
440f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->tx_words = data->tx_words;
441f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->rx_frames = data->rx_frames;
442f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->rx_words = data->rx_words;
443f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->lip_count = data->lip;
444f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->nos_count = data->nos;
445f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->error_frames = data->error_frames;
446f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->dumped_frames = data->dumped_frames;
447f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->link_failure_count = data->link_failure;
448f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->loss_of_sync_count = data->loss_of_sync;
449f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->loss_of_signal_count = data->loss_of_signal;
450f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;
451f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->invalid_tx_word_count = data->invalid_tx_words;
452f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->invalid_crc_count = data->invalid_crcs;
453f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->fcp_input_requests = data->input_requests;
454f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->fcp_output_requests = data->output_requests;
455f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->fcp_control_requests = data->control_requests;
456f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->fcp_input_megabytes = data->input_mb;
457f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats->fcp_output_megabytes = data->output_mb;
458f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann}
459f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann
460f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermannstatic struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host)
461f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann{
462f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	struct zfcp_adapter *adapter;
463f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	struct fc_host_statistics *fc_stats;
464f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	struct fsf_qtcb_bottom_port *data;
465f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	int ret;
466f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann
467f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	adapter = (struct zfcp_adapter *)host->hostdata[0];
468f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	fc_stats = zfcp_init_fc_host_stats(adapter);
469f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	if (!fc_stats)
470f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		return NULL;
471f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann
472ec4081c6ba4fba6a8bc12a0e93db8817ba63ce47Andreas Herrmann	data = kzalloc(sizeof(*data), GFP_KERNEL);
473f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	if (!data)
474f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		return NULL;
475f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann
476564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
477f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	if (ret) {
478f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		kfree(data);
479f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		return NULL;
480f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	}
481f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann
482f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	if (adapter->stats_reset &&
483f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	    ((jiffies/HZ - adapter->stats_reset) <
484f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	     data->seconds_since_last_reset))
485f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		zfcp_adjust_fc_host_stats(fc_stats, data,
486f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann					  adapter->stats_reset_data);
487f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	else
488f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		zfcp_set_fc_host_stats(fc_stats, data);
489f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann
490f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	kfree(data);
491f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	return fc_stats;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
494f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermannstatic void zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
496f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	struct zfcp_adapter *adapter;
497f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	struct fsf_qtcb_bottom_port *data;
498f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	int ret;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
500f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	adapter = (struct zfcp_adapter *)shost->hostdata[0];
501ec4081c6ba4fba6a8bc12a0e93db8817ba63ce47Andreas Herrmann	data = kzalloc(sizeof(*data), GFP_KERNEL);
502f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	if (!data)
503f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		return;
504f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann
505564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
506f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	if (ret)
50783f6d6d7258974a99cbf465878bc11eb4d494c61Heiko Carstens		kfree(data);
508f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	else {
509f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		adapter->stats_reset = jiffies/HZ;
510f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann		kfree(adapter->stats_reset_data);
511f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann		adapter->stats_reset_data = data; /* finally freed in
512f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig						     adapter_release */
513f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	}
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51685a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetzstatic void zfcp_get_host_port_state(struct Scsi_Host *shost)
51785a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz{
51885a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	struct zfcp_adapter *adapter =
51985a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz		(struct zfcp_adapter *)shost->hostdata[0];
52085a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	int status = atomic_read(&adapter->status);
52185a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz
52285a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	if ((status & ZFCP_STATUS_COMMON_RUNNING) &&
52385a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	    !(status & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED))
52485a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
52585a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	else if (status & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
52685a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
52785a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	else if (status & ZFCP_STATUS_COMMON_ERP_FAILED)
52885a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz		fc_host_port_state(shost) = FC_PORTSTATE_ERROR;
52985a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	else
53085a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
53185a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz}
53285a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz
533338151e066084d92d89f44311e5521ef847a50b9Andreas Herrmannstatic void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
534338151e066084d92d89f44311e5521ef847a50b9Andreas Herrmann{
535338151e066084d92d89f44311e5521ef847a50b9Andreas Herrmann	rport->dev_loss_tmo = timeout;
536338151e066084d92d89f44311e5521ef847a50b9Andreas Herrmann}
537338151e066084d92d89f44311e5521ef847a50b9Andreas Herrmann
538a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt/**
539a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport
540a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt * @rport: The FC rport where to teminate I/O
541a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt *
542a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt * Abort all pending SCSI commands for a port by closing the
543835dc29887073eec7817559a07558f955383d099Christof Schmitt * port. Using a reopen avoids a conflict with a shutdown
544835dc29887073eec7817559a07558f955383d099Christof Schmitt * overwriting a reopen. The "forced" ensures that a disappeared port
545835dc29887073eec7817559a07558f955383d099Christof Schmitt * is not opened again as valid due to the cached plogi data in
546835dc29887073eec7817559a07558f955383d099Christof Schmitt * non-NPIV mode.
547a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt */
548a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmittstatic void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
549a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt{
55070932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt	struct zfcp_port *port;
551ea945ff84c2ce1089edb7914ffdd998c24c25903Swen Schillig	struct Scsi_Host *shost = rport_to_shost(rport);
552ea945ff84c2ce1089edb7914ffdd998c24c25903Swen Schillig	struct zfcp_adapter *adapter =
553ea945ff84c2ce1089edb7914ffdd998c24c25903Swen Schillig		(struct zfcp_adapter *)shost->hostdata[0];
55470932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt
555ea945ff84c2ce1089edb7914ffdd998c24c25903Swen Schillig	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
556a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
55770932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt	if (port) {
558ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_port_forced_reopen(port, 0, "sctrpi1");
559615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt		put_device(&port->dev);
56070932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt	}
561a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt}
562a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
563a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmittstatic void zfcp_scsi_rport_register(struct zfcp_port *port)
564a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt{
565a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	struct fc_rport_identifiers ids;
566a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	struct fc_rport *rport;
567a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
568379d6bf6573ee6541a38bbe9140c1f0b94e3feaeChristof Schmitt	if (port->rport)
569379d6bf6573ee6541a38bbe9140c1f0b94e3feaeChristof Schmitt		return;
570379d6bf6573ee6541a38bbe9140c1f0b94e3feaeChristof Schmitt
571a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	ids.node_name = port->wwnn;
572a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	ids.port_name = port->wwpn;
573a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	ids.port_id = port->d_id;
574a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	ids.roles = FC_RPORT_ROLE_FCP_TARGET;
575a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
576a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
577a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	if (!rport) {
578a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		dev_err(&port->adapter->ccw_device->dev,
579a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt			"Registering port 0x%016Lx failed\n",
580a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt			(unsigned long long)port->wwpn);
581a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		return;
582a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	}
583a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
584a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	rport->maxframe_size = port->maxframe_size;
585a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	rport->supported_classes = port->supported_classes;
586a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	port->rport = rport;
5871bf3ff02ca6247b2d7c9ebda93002392bf60a61dChristof Schmitt	port->starget_id = rport->scsi_target_id;
5885a7de559b4e0169ff4cfca654b4e4f0014996e57Christof Schmitt
5891daa4eb50fa5cd4c8f9c55452606e786fd42053bChristof Schmitt	zfcp_unit_queue_scsi_scan(port);
590a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt}
591a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
592a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmittstatic void zfcp_scsi_rport_block(struct zfcp_port *port)
593a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt{
59470932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt	struct fc_rport *rport = port->rport;
59570932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt
596379d6bf6573ee6541a38bbe9140c1f0b94e3feaeChristof Schmitt	if (rport) {
59770932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt		fc_remote_port_delete(rport);
598379d6bf6573ee6541a38bbe9140c1f0b94e3feaeChristof Schmitt		port->rport = NULL;
599379d6bf6573ee6541a38bbe9140c1f0b94e3feaeChristof Schmitt	}
600a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt}
601a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
602a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmittvoid zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
603a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt{
604615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	get_device(&port->dev);
605a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	port->rport_task = RPORT_ADD;
606a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
6074544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	if (!queue_work(port->adapter->work_queue, &port->rport_work))
608615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt		put_device(&port->dev);
609a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt}
610a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
611a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmittvoid zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
612a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt{
613615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	get_device(&port->dev);
614a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	port->rport_task = RPORT_DEL;
615a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
6164544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	if (port->rport && queue_work(port->adapter->work_queue,
6174544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig				      &port->rport_work))
618a67417ab7eeff45bba55666c0e1083260f3624eeSwen Schillig		return;
619a67417ab7eeff45bba55666c0e1083260f3624eeSwen Schillig
620615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	put_device(&port->dev);
621a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt}
622a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
623a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmittvoid zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
624a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt{
625ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	unsigned long flags;
626a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	struct zfcp_port *port;
627a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
628ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_lock_irqsave(&adapter->port_list_lock, flags);
629ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	list_for_each_entry(port, &adapter->port_list, list)
630a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		zfcp_scsi_schedule_rport_block(port);
631ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_unlock_irqrestore(&adapter->port_list_lock, flags);
632a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt}
633a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
634a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmittvoid zfcp_scsi_rport_work(struct work_struct *work)
635a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt{
636a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	struct zfcp_port *port = container_of(work, struct zfcp_port,
637a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt					      rport_work);
638a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
639a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	while (port->rport_task) {
640a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		if (port->rport_task == RPORT_ADD) {
641a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt			port->rport_task = RPORT_NONE;
642a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt			zfcp_scsi_rport_register(port);
643a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		} else {
644a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt			port->rport_task = RPORT_NONE;
645a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt			zfcp_scsi_rport_block(port);
646a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt		}
647a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	}
648a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
649615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	put_device(&port->dev);
650a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt}
651a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt
6525a7de559b4e0169ff4cfca654b4e4f0014996e57Christof Schmitt/**
653ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host
654ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck * @adapter: The adapter where to configure DIF/DIX for the SCSI host
655ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck */
656ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beckvoid zfcp_scsi_set_prot(struct zfcp_adapter *adapter)
657ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck{
658ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	unsigned int mask = 0;
659ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	unsigned int data_div;
660ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	struct Scsi_Host *shost = adapter->scsi_host;
661ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
662ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	data_div = atomic_read(&adapter->status) &
663ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		   ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED;
664ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
665ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	if (enable_dif &&
666ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	    adapter->adapter_features & FSF_FEATURE_DIF_PROT_TYPE1)
667ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		mask |= SHOST_DIF_TYPE1_PROTECTION;
668ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
669ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	if (enable_dif && data_div &&
670ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	    adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
671ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		mask |= SHOST_DIX_TYPE1_PROTECTION;
672ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
67386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		shost->sg_prot_tablesize = adapter->qdio->max_sbale_per_req / 2;
67486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		shost->sg_tablesize = adapter->qdio->max_sbale_per_req / 2;
67586a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		shost->max_sectors = shost->sg_tablesize * 8;
676ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	}
677ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
678ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	scsi_host_set_prot(shost, mask);
679ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck}
680ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
681ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck/**
682ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck * zfcp_scsi_dif_sense_error - Report DIF/DIX error as driver sense error
683ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck * @scmd: The SCSI command to report the error for
684ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck * @ascq: The ASCQ to put in the sense buffer
685ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck *
686ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck * See the error handling in sd_done for the sense codes used here.
687ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck * Set DID_SOFT_ERROR to retry the request, if possible.
688ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck */
689ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beckvoid zfcp_scsi_dif_sense_error(struct scsi_cmnd *scmd, int ascq)
690ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck{
691ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	scsi_build_sense_buffer(1, scmd->sense_buffer,
692ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck				ILLEGAL_REQUEST, 0x10, ascq);
693ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	set_driver_byte(scmd, DRIVER_SENSE);
694ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	scmd->result |= SAM_STAT_CHECK_CONDITION;
695ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	set_host_byte(scmd, DID_SOFT_ERROR);
696ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck}
697ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct fc_function_template zfcp_transport_functions = {
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.show_starget_port_id = 1,
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.show_starget_port_name = 1,
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.show_starget_node_name = 1,
7023859f6a248cbdfbe7b41663f3a2b51f48e30b281Andreas Herrmann	.show_rport_supported_classes = 1,
70375bfc2837bbcc329193d51e8b7115184b78beae0Ralph Wuerthner	.show_rport_maxframe_size = 1,
704338151e066084d92d89f44311e5521ef847a50b9Andreas Herrmann	.show_rport_dev_loss_tmo = 1,
7053859f6a248cbdfbe7b41663f3a2b51f48e30b281Andreas Herrmann	.show_host_node_name = 1,
7063859f6a248cbdfbe7b41663f3a2b51f48e30b281Andreas Herrmann	.show_host_port_name = 1,
707ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann	.show_host_permanent_port_name = 1,
7083859f6a248cbdfbe7b41663f3a2b51f48e30b281Andreas Herrmann	.show_host_supported_classes = 1,
7090fdd21330a9d7bc6790eae0aed768052c315ae44Christof Schmitt	.show_host_supported_fc4s = 1,
710ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann	.show_host_supported_speeds = 1,
71113e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann	.show_host_maxframe_size = 1,
7123859f6a248cbdfbe7b41663f3a2b51f48e30b281Andreas Herrmann	.show_host_serial_number = 1,
713f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	.get_fc_host_stats = zfcp_get_fc_host_stats,
714f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	.reset_fc_host_stats = zfcp_reset_fc_host_stats,
715338151e066084d92d89f44311e5521ef847a50b9Andreas Herrmann	.set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
71685a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	.get_host_port_state = zfcp_get_host_port_state,
717a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	.terminate_rport_io = zfcp_scsi_terminate_rport_io,
71885a82392fe6fe7620d8fe0eb694f926cefe62e1fSven Schuetz	.show_host_port_state = 1,
7190fdd21330a9d7bc6790eae0aed768052c315ae44Christof Schmitt	.show_host_active_fc4s = 1,
7207c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt	.bsg_request = zfcp_fc_exec_bsg_job,
721491ca4426ba153f79e72d1ca2a30c926484282b7Swen Schillig	.bsg_timeout = zfcp_fc_timeout_bsg_job,
722f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	/* no functions registered for following dynamic attributes but
723f6cd94b126aa78ebaa21075df3b9577fbf995968Andreas Herrmann	   directly set by LLDD */
724ad757cdfd2a40c9d5310d00f24427525788341cdAndreas Herrmann	.show_host_port_type = 1,
725038d9446a9e601d7972926ca69fee10eeda6f3c7Christof Schmitt	.show_host_symbolic_name = 1,
72613e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann	.show_host_speed = 1,
72713e1e1f08c1c098c7574c1fa72bd8c67792dc89bAndreas Herrmann	.show_host_port_id = 1,
7287c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt	.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
730