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