zfcp_fsf.c revision 4318e08c84e4916ac463002ffb7f9901ddb3c385
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * zfcp device driver
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * Implementation of FSF commands.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt * Copyright IBM Corporation 2002, 2009
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define KMSG_COMPONENT "zfcp"
10ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt
120997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl#include <linux/blktrace_api.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "zfcp_ext.h"
144318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt#include "zfcp_fc.h"
15dcd20e2316cdc333dfdee09649dbe3642eb30e75Christof Schmitt#include "zfcp_dbf.h"
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_request_timeout_handler(unsigned long data)
18287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
19287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
205ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
215ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				"fsrth_1", NULL);
22287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
23287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
24287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req,
25287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt				 unsigned long timeout)
26287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
27287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
28287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.data = (unsigned long) fsf_req->adapter;
29287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.expires = jiffies + timeout;
30287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	add_timer(&fsf_req->timer);
31287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
32287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
33287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_start_erp_timer(struct zfcp_fsf_req *fsf_req)
34287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
35287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	BUG_ON(!fsf_req->erp_action);
36287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.function = zfcp_erp_timeout_handler;
37287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.data = (unsigned long) fsf_req->erp_action;
38287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.expires = jiffies + 30 * HZ;
39287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	add_timer(&fsf_req->timer);
40287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
41287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* association between FSF command and FSF QTCB type */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 fsf_qtcb_type[] = {
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_FCP_CMND] =             FSF_IO_COMMAND,
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_ABORT_FCP_CMND] =       FSF_SUPPORT_COMMAND,
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_OPEN_PORT_WITH_DID] =   FSF_SUPPORT_COMMAND,
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_OPEN_LUN] =             FSF_SUPPORT_COMMAND,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_LUN] =            FSF_SUPPORT_COMMAND,
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_PORT] =           FSF_SUPPORT_COMMAND,
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_PHYSICAL_PORT] =  FSF_SUPPORT_COMMAND,
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_SEND_ELS] =             FSF_SUPPORT_COMMAND,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_SEND_GENERIC] =         FSF_SUPPORT_COMMAND,
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND,
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_EXCHANGE_PORT_DATA] =   FSF_PORT_COMMAND,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_UPLOAD_CONTROL_FILE] =  FSF_SUPPORT_COMMAND
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
60553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
61c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	u16 subtable = table >> 16;
62553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	u16 rule = table & 0xffff;
63ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt	const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
64553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
65ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt	if (subtable && subtable < ARRAY_SIZE(act_type))
66553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt		dev_warn(&adapter->ccw_device->dev,
67ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "Access denied according to ACT rule type %s, "
68ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "rule %d\n", act_type[subtable], rule);
69553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
70553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
71553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
72553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt					struct zfcp_port *port)
73553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
74553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	struct fsf_qtcb_header *header = &req->qtcb->header;
75553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	dev_warn(&req->adapter->ccw_device->dev,
76ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		 "Access denied to port 0x%016Lx\n",
777ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig		 (unsigned long long)port->wwpn);
78553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
79553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
805ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_port_access_denied(port, "fspad_1", req);
81553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
82553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
83553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
84553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
85553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt					struct zfcp_unit *unit)
86553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
87553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	struct fsf_qtcb_header *header = &req->qtcb->header;
88553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	dev_warn(&req->adapter->ccw_device->dev,
89ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		 "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
907ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig		 (unsigned long long)unit->fcp_lun,
917ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig		 (unsigned long long)unit->port->wwpn);
92553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
93553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
945ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_unit_access_denied(unit, "fsuad_1", req);
95553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
96553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
97553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
98553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
99553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
100ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
101ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		"operational because of an unsupported FC class\n");
1025ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1", req);
103553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
104553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
105553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
106c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
107c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_req_free - free memory used by fsf request
108c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_req: pointer to struct zfcp_fsf_req
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
110c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligvoid zfcp_fsf_req_free(struct zfcp_fsf_req *req)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
112c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(req->pool)) {
113a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (likely(req->qtcb))
114a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			mempool_free(req->qtcb, req->adapter->pool.qtcb_pool);
115c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		mempool_free(req, req->pool);
116dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens		return;
117dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens	}
118dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens
119a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(req->qtcb))
120a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb);
121a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	kfree(req);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
124c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
126ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	unsigned long flags;
127c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
128c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
129c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port;
130c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int d_id = sr_buf->d_id & ZFCP_DID_MASK;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
132ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_lock_irqsave(&adapter->port_list_lock, flags);
133ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	list_for_each_entry(port, &adapter->port_list, list)
134c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (port->d_id == d_id) {
1355ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_port_reopen(port, 0, "fssrpc1", req);
136ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig			break;
137c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		}
138ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_unlock_irqrestore(&adapter->port_list_lock, flags);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1415ffd51a5e495a2a002efd523aef0001912b080bdSwen Schilligstatic void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
142c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					 struct fsf_link_down_info *link_down)
143aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin{
144c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
145698ec01635819c5ae60090bb4efcbeffc41642fbMartin Peschke
146c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
147ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin		return;
148ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
149ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
15070932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt
151a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	zfcp_scsi_schedule_rports_block(adapter);
152ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
153c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!link_down)
1542f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann		goto out;
155ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
156aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	switch (link_down->error_code) {
157aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_LIGHT:
158c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
159ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "There is no light signal from the local "
160ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "fibre channel cable\n");
161aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
162aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_WRAP_PLUG:
163c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
164ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "There is a wrap plug instead of a fibre "
165ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "channel cable\n");
166aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
167aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FCP:
168c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
169ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The adjacent fibre channel node does not "
170ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "support FCP\n");
171aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
172aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_FIRMWARE_UPDATE:
173c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
174ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP device is suspended because of a "
175ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "firmware update\n");
176553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt		break;
177aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_INVALID_WWPN:
178c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
179ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP device detected a WWPN that is "
180ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "duplicate or not valid\n");
181aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
182aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
183c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
184ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The fibre channel fabric does not support NPIV\n");
185aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
186aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FCP_RESOURCES:
187c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
188ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP adapter cannot support more NPIV ports\n");
189aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
190aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
191c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
192ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The adjacent switch cannot support "
193ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "more NPIV ports\n");
194aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
195aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
196c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
197ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP adapter could not log in to the "
198ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "fibre channel fabric\n");
199aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
200aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
201c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
202ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The WWPN assignment file on the FCP adapter "
203ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been damaged\n");
204aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
205aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
206c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
207ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The mode table on the FCP adapter "
208ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been damaged\n");
209aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
210aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
211c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
212ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "All NPIV ports on the FCP adapter have "
213ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "been assigned\n");
214aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
215aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	default:
216c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
217ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The link between the FCP adapter and "
218ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "the FC fabric is down\n");
219aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	}
220c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
221c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_erp_adapter_failed(adapter, id, req);
222aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin}
223aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
224c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
226c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
227c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_link_down_info *ldi =
228c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		(struct fsf_link_down_info *) &sr_buf->payload;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
230c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (sr_buf->status_subtype) {
231c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
2325ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
234c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_FDISC_FAILED:
2355ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
237c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
2385ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL);
239c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	};
240c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
242c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
243c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
244c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
245c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
247c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
2485771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf);
249a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_free(sr_buf, adapter->pool.status_read_data);
250c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
252c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2545771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf);
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
256c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (sr_buf->status_type) {
257c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_PORT_CLOSED:
258c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_port_closed(req);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
260c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_INCOMING_ELS:
261c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fc_incoming_els(req);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
263c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
265c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
266ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		dev_warn(&adapter->ccw_device->dev,
267ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The error threshold for checksum statistics "
268ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been exceeded\n");
2695771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_hba_berr(adapter->dbf, req);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
271c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_LINK_DOWN:
272c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_link_down(req);
273c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
274c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_LINK_UP:
275c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_info(&adapter->ccw_device->dev,
276ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The local link has been restored\n");
277c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* All ports should be marked as ready to run again */
2785ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL,
279c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					       ZFCP_STATUS_COMMON_RUNNING,
280c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					       ZFCP_SET);
281c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_erp_adapter_reopen(adapter,
282c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_COMMON_ERP_FAILED,
2845ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					"fssrh_2", req);
285c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
286c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_NOTIFICATION_LOST:
287c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
2885ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
2895ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig							req);
290c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
2919eae07ef6bb5988163d8bb82cd952905db47b721Swen Schillig			queue_work(adapter->work_queue, &adapter->scan_work);
292c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
293c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_CFDC_UPDATED:
2945ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
296c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
297c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->adapter_features = sr_buf->payload.word[0];
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	mempool_free(sr_buf, adapter->pool.status_read_data);
302c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	atomic_inc(&adapter->stat_miss);
3054544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	queue_work(adapter->work_queue, &adapter->stat_work);
306c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
308c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
309c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
310c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status_qual.word[0]) {
311c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_FCP_RSP_AVAILABLE:
312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
313c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_NO_RETRY_POSSIBLE:
314c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
315c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
316c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_COMMAND_ABORTED:
317c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ABORTED;
318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
319c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_NO_RECOM:
320c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
321ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter reported a problem "
322ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"that cannot be recovered\n");
3235ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req);
324c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
325c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
326c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/* all non-return stats set FSFREQ_ERROR*/
327c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
330c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
332c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
333c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
335c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
336c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_UNKNOWN_COMMAND:
337c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
338ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter does not recognize the command 0x%x\n",
339c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->header.fsf_command);
3405ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1", req);
341c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
342c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
344c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_fsfstatus_qual_eval(req);
345c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
346c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
347c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
349c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
350c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
351c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
353c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	union fsf_prot_status_qual *psq = &qtcb->prefix.prot_status_qual;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3555771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_hba_fsf_response(req);
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
357c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
358c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
359c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */
360c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
361c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
363c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->prefix.prot_status) {
364c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_GOOD:
365c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_FSF_STATUS_PRESENTED:
366c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
367c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_QTCB_VERSION_ERROR:
368c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
369ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"QTCB version 0x%x not supported by FCP adapter "
370ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION,
371ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			psq->word[0], psq->word[1]);
3725ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1", req);
373c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
374c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_ERROR_STATE:
375c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_SEQ_NUMB_ERROR:
3765ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req);
377c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_RETRY;
378c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
379c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_UNSUPP_QTCB_TYPE:
380c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
381ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The QTCB type is not supported by the FCP adapter\n");
3825ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3", req);
383c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
384c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_HOST_CONNECTION_INITIALIZING:
385c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
386c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&adapter->status);
387c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
388c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_DUPLICATE_REQUEST_ID:
389c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
390ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%Lx is an ambiguous request identifier\n",
391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			(unsigned long long)qtcb->bottom.support.req_handle);
3925ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
393c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
394c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_LINK_DOWN:
3955ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fspse_5",
3965ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					     &psq->link_down_info);
397c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* FIXME: reopening adapter now? better wait for link up */
3985ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
399c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
400c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_REEST_QUEUE:
401c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* All ports should be marked as ready to run again */
4025ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL,
403c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					       ZFCP_STATUS_COMMON_RUNNING,
404c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					       ZFCP_SET);
405c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_erp_adapter_reopen(adapter,
406c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
4075ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					ZFCP_STATUS_COMMON_ERP_FAILED,
4085ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					"fspse_8", req);
409c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
410c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
411c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
412ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%x is not a valid transfer protocol status\n",
413c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			qtcb->prefix.prot_status);
4145ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req);
415c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
416c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
419c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
420c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_req_complete - process completion of a FSF request
421c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_req: The FSF request that has been completed.
422c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig *
423c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * When a request has been completed either from the FCP adapter,
424c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * or it has been dismissed due to a queue shutdown, this function
425c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * is called to process the completion status and trigger further
426c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * events related to the FSF request.
427c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig */
428bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schilligstatic void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
430c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
431c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_handler(req);
432c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
433c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
435c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	del_timer(&req->timer);
436c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_protstatus_eval(req);
437c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_fsfstatus_eval(req);
438c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler(req);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
440c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->erp_action)
441287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt		zfcp_erp_notify(req->erp_action, 0);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
443c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
444c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
445c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
446058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		complete(&req->completion);
447c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
449bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig/**
450bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
451bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @adapter: pointer to struct zfcp_adapter
452bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig *
453bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Never ever call this without shutting down the adapter first.
454bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Otherwise the adapter would continue using and corrupting s390 storage.
455bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Included BUG_ON() call to ensure this is done.
456bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * ERP is supposed to be the only user of this function.
457bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */
458bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schilligvoid zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
459bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig{
460bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct zfcp_fsf_req *req, *tmp;
461bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	unsigned long flags;
462bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	LIST_HEAD(remove_queue);
463bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	unsigned int i;
464bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
465bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
466bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	spin_lock_irqsave(&adapter->req_list_lock, flags);
467bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	for (i = 0; i < REQUEST_LIST_SIZE; i++)
468bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		list_splice_init(&adapter->req_list[i], &remove_queue);
469bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
470bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
471bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	list_for_each_entry_safe(req, tmp, &remove_queue, list) {
472bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		list_del(&req->list);
473bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
474bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		zfcp_fsf_req_complete(req);
475bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	}
476bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig}
477bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
478c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
479c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
480c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_config *bottom;
481c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
482c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom = &req->qtcb->bottom.config;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
486c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->data)
487c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(req->data, bottom, sizeof(*bottom));
488c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
489c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_node_name(shost) = bottom->nport_serv_param.wwnn;
490c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
491c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
492c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_speed(shost) = bottom->fc_link_speed;
493c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
494c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
495c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->hydra_version = bottom->adapter_type;
496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->timer_ticks = bottom->timer_interval;
497c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
498c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (fc_host_permanent_port_name(shost) == -1)
499c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
500c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
501c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (bottom->fc_topology) {
502c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_P2P:
503c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->peer_wwpn = bottom->plogi_payload.wwpn;
505c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->peer_wwnn = bottom->plogi_payload.wwnn;
506c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
507c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
508c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_FABRIC:
509c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
510c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
511c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_AL:
512c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
513dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
514c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
515c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
516ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"Unknown or unsupported arbitrated loop "
517ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"fibre channel topology detected\n");
5185ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req);
519c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EIO;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
521c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
525c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
526553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
527553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	struct zfcp_adapter *adapter = req->adapter;
528c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
529c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config;
530c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
531553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
532c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
533c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
535c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->fsf_lic_version = bottom->lic_version;
536c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->adapter_features = bottom->adapter_features;
537c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->connection_features = bottom->connection_features;
538c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_wwpn = 0;
539c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_wwnn = 0;
540c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_d_id = 0;
5418a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
542c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->header.fsf_status) {
543c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GOOD:
544c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (zfcp_fsf_exchange_config_evaluate(req))
545c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			return;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
547c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
548c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			dev_err(&adapter->ccw_device->dev,
549ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"FCP adapter maximum QTCB size (%d bytes) "
550ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"is too small\n",
551ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				bottom->max_qtcb_size);
5525ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1", req);
553c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			return;
554c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		}
555c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
556c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&adapter->status);
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
558c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
559c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_node_name(shost) = 0;
560c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_name(shost) = 0;
561c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_id(shost) = 0;
562c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
563c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
564c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->hydra_version = 0;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
566c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
567c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&adapter->status);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5695ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fsecdh2",
570c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			&qtcb->header.fsf_status_qual.link_down_info);
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
572c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
5735ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req);
574c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
575c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
577c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
578c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->hardware_version = bottom->hardware_version;
579c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(fc_host_serial_number(shost), bottom->serial_number,
580c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       min(FC_SERIAL_NUMBER_SIZE, 17));
581c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		EBCASC(fc_host_serial_number(shost),
582c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       min(FC_SERIAL_NUMBER_SIZE, 17));
583c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
585c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
586c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
587ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter only supports newer "
588ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"control block versions\n");
5895ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4", req);
590c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
591c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
592c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
593c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
594ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter only supports older "
595ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"control block versions\n");
5965ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5", req);
597c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
598c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
600c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
601c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
602c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
603c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_port *bottom = &req->qtcb->bottom.port;
604c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
606c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->data)
607c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(req->data, bottom, sizeof(*bottom));
6089eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin
6090282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
610c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = bottom->wwpn;
6110282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
6120282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt	} else
613c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
614c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
615c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_supported_speeds(shost) = bottom->supported_speed;
616c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
618c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
619c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
620c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
621c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
622c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
623c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
624c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
625c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->header.fsf_status) {
626c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GOOD:
627c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_exchange_port_evaluate(req);
628c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
629c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
630c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_exchange_port_evaluate(req);
6315ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fsepdh1",
632c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			&qtcb->header.fsf_status_qual.link_down_info);
633aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
635c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
636d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig
637564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligstatic int zfcp_fsf_sbal_check(struct zfcp_qdio *qdio)
638c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
639564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio_queue *req_q = &qdio->req_q;
640c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
641564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
6427001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann	if (atomic_read(&req_q->count))
6437001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann		return 1;
644564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
6457001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann	return 0;
6467001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann}
6477001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann
648564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligstatic int zfcp_fsf_req_sbal_get(struct zfcp_qdio *qdio)
6497001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann{
650564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
6517001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann	long ret;
652dedbc2b3cb8404c618975bd2811c7605a4ccb51eChristof Schmitt
653564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
654564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	ret = wait_event_interruptible_timeout(qdio->req_q_wq,
655564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig			       zfcp_fsf_sbal_check(qdio), 5 * HZ);
656c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret > 0)
657c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return 0;
658cbf1ed0264da104573458aedc220ebfcd02567f6Christof Schmitt	if (!ret) {
659564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		atomic_inc(&qdio->req_q_full);
660cbf1ed0264da104573458aedc220ebfcd02567f6Christof Schmitt		/* assume hanging outbound queue, try queue recovery */
661cbf1ed0264da104573458aedc220ebfcd02567f6Christof Schmitt		zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
662cbf1ed0264da104573458aedc220ebfcd02567f6Christof Schmitt	}
6637001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann
664564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
665c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return -EIO;
666c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
667c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
668a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligstatic struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
669c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
670c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
671a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
672a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(pool))
673a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		req = mempool_alloc(pool, GFP_ATOMIC);
674a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	else
675a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		req = kmalloc(sizeof(*req), GFP_ATOMIC);
676a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
677a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (unlikely(!req))
678c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
679a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
680c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(req, 0, sizeof(*req));
68188f2a977870af655296a682fe2a58c822cd25bb2Christof Schmitt	req->pool = pool;
682c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
683c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
684c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
685a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligstatic struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
686c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
687a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	struct fsf_qtcb *qtcb;
688c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
689c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(pool))
690c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		qtcb = mempool_alloc(pool, GFP_ATOMIC);
691c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
692a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC);
693a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
694c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!qtcb))
695c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
696c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
697c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(qtcb, 0, sizeof(*qtcb));
698a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	return qtcb;
699c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
700c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
701564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligstatic struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
70209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig						u32 fsf_cmd, mempool_t *pool)
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
70444cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
705564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio_queue *req_q = &qdio->req_q;
706564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
707a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
709c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!req))
7101e9b16430ff4fd09408a74342d6b8338228e2f70Christof Schmitt		return ERR_PTR(-ENOMEM);
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
712c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (adapter->req_no == 0)
713c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->req_no++;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
715c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	INIT_LIST_HEAD(&req->list);
716c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	init_timer(&req->timer);
717058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig	init_completion(&req->completion);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
719c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->adapter = adapter;
720c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->fsf_command = fsf_cmd;
72152bfb558d2803590f86360ec3af1750897a9c010Christof Schmitt	req->req_id = adapter->req_no;
72242428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbal_number = 1;
72342428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbal_first = req_q->first;
72442428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbal_last = req_q->first;
72542428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbale_curr = 1;
726c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
727564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
728c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].addr = (void *) req->req_id;
729c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_COMMAND;
730c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
731a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
732a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (likely(pool))
733a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool);
734a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		else
735a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			req->qtcb = zfcp_qtcb_alloc(NULL);
736a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
737a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (unlikely(!req->qtcb)) {
738a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			zfcp_fsf_req_free(req);
739a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			return ERR_PTR(-ENOMEM);
740a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		}
741a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
742564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
743c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.req_id = req->req_id;
744c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.ulp_info = 26;
745c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command];
746c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION;
747c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->header.req_handle = req->req_id;
748c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->header.fsf_command = req->fsf_command;
749c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->seq_no = adapter->fsf_req_seq_no;
750c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
751c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		sbale[1].addr = (void *) req->qtcb;
752c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		sbale[1].length = sizeof(struct fsf_qtcb);
753c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
754c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
755c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) {
756c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
757c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return ERR_PTR(-EIO);
758c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
759951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt
760c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
763c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
764c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
765c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
766564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
767135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	unsigned long	     flags;
768135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	int		     idx;
769135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	int		     with_qtcb = (req->qtcb != NULL);
770c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
771c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/* put allocated FSF request into hash table */
77245316a86a67934ab499dcfac44c91aa8f39c4c78Heiko Carstens	spin_lock_irqsave(&adapter->req_list_lock, flags);
773c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	idx = zfcp_reqlist_hash(req->req_id);
774c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	list_add_tail(&req->list, &adapter->req_list[idx]);
77545316a86a67934ab499dcfac44c91aa8f39c4c78Heiko Carstens	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
776c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
777564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
778c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->issued = get_clock();
779564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_qdio_send(qdio, &req->queue_req)) {
780c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		del_timer(&req->timer);
7813765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		spin_lock_irqsave(&adapter->req_list_lock, flags);
7823765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		/* lookup request again, list might have changed */
7833765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		if (zfcp_reqlist_find_safe(adapter, req))
7843765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt			zfcp_reqlist_remove(adapter, req);
7853765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		spin_unlock_irqrestore(&adapter->req_list_lock, flags);
7865ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req);
787c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EIO;
788c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
789c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
790c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/* Don't increase for unsolicited status */
791135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	if (with_qtcb)
792c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->fsf_req_seq_no++;
79352bfb558d2803590f86360ec3af1750897a9c010Christof Schmitt	adapter->req_no++;
794c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
795c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return 0;
796c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
797c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
798c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
799c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_status_read - send status read request
800c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @adapter: pointer to struct zfcp_adapter
801c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @req_flags: request flags
802c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, ERROR otherwise
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
804564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_status_read(struct zfcp_qdio *qdio)
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
806564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
807c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
808c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf;
80944cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
810c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
812564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
813564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
814c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
815c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
816564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS,
817a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig				  adapter->pool.status_read_req);
818025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
819c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
820c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
823564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
824c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
82542428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbale_curr = 2;
826c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
827a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
828c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!sr_buf) {
829c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = -ENOMEM;
830c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_buf;
831c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
832c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(sr_buf, 0, sizeof(*sr_buf));
833c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = sr_buf;
834564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_curr(qdio, &req->queue_req);
835c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale->addr = (void *) sr_buf;
836c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale->length = sizeof(*sr_buf);
837059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann
838c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
839c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (retval)
840c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_req_send;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
842c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
843c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
844c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_req_send:
845a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	mempool_free(sr_buf, adapter->pool.status_read_data);
846c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_buf:
847c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
8485771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
849c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
850564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
851c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
852c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
853c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
854c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
855c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
856c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit = req->data;
857c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
858c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
859c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
860c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
861c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
862c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
864c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (fsq->word[0] == fsq->word[1]) {
8655ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_adapter_reopen(unit->port->adapter, 0,
8665ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig						"fsafch1", req);
867c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_HANDLE_NOT_VALID:
871c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (fsq->word[0] == fsq->word[1]) {
8725ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
873c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
877c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
8805ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_boxed(unit->port, "fsafch3", req);
881c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
882c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_BOXED:
8855ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_unit_boxed(unit, "fsafch4", req);
886c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
887c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
890c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		switch (fsq->word[0]) {
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
8926f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig			zfcp_fc_test_link(unit->port);
893dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt			/* fall through */
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
895c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
900c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
906c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_abort_fcp_command - abort running SCSI command
907c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @old_req_id: unsigned long
908c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @unit: pointer to struct zfcp_unit
909c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: pointer to struct zfcp_fsf_req
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
912c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstruct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
91363caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt						struct zfcp_unit *unit)
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
91544cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
916c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
917564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
9188a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
919564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
920564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
921c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
922564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
923564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.scsi_abort);
924633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	if (IS_ERR(req)) {
925633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig		req = NULL;
926c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
927633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	}
9282abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann
929c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!(atomic_read(&unit->status) &
930c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
931c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out_error_free;
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
933564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
934c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
935c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
937c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = unit;
938c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_abort_fcp_command_handler;
939c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.lun_handle = unit->handle;
940c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = unit->port->handle;
941c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.support.req_handle = (u64) old_req_id;
942c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
943c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
944c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!zfcp_fsf_req_send(req))
945c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
946c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
947c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout_error_free:
948c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
949c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req = NULL;
950c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
951564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
952c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
955c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
957c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
958c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_send_ct *send_ct = req->data;
959c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	send_ct->status = -EINVAL;
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
963c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_GOOD:
9685771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_san_ct_response(req);
969c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		send_ct->status = 0;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
972c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_ADAPTER_STATUS_AVAILABLE:
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch (header->fsf_status_qual.word[0]){
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
978c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_PORT_BOXED:
985c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
986c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
988c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_HANDLE_NOT_VALID:
9895ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req);
990dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
991c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GENERIC_COMMAND_REJECTED:
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PAYLOAD_SIZE_MISMATCH:
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_REQUEST_SIZE_TOO_LARGE:
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_RESPONSE_SIZE_TOO_LARGE:
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_SBAL_MISMATCH:
996c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus:
1001c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (send_ct->handler)
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_ct->handler(send_ct->handler_data);
1003c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1005426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmittstatic void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
1006426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt					    struct scatterlist *sg_req,
1007426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt					    struct scatterlist *sg_resp)
1008426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt{
1009426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
1010426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[2].addr   = sg_virt(sg_req);
1011426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[2].length = sg_req->length;
1012426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[3].addr   = sg_virt(sg_resp);
1013426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[3].length = sg_resp->length;
1014426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
1015426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt}
1016426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt
1017426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmittstatic int zfcp_fsf_one_sbal(struct scatterlist *sg)
1018426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt{
1019426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	return sg_is_last(sg) && sg->length <= PAGE_SIZE;
1020426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt}
1021426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt
102239eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmittstatic int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
102339eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt				       struct scatterlist *sg_req,
102439eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt				       struct scatterlist *sg_resp,
102539eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt				       int max_sbals)
1026c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
102742428f747a8a0db9c6de03e105932316defad65dSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
1028564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio,
102942428f747a8a0db9c6de03e105932316defad65dSwen Schillig							       &req->queue_req);
103042428f747a8a0db9c6de03e105932316defad65dSwen Schillig	u32 feat = adapter->adapter_features;
1031c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int bytes;
1032c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
103339eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
1034426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
103539eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt			return -EOPNOTSUPP;
103639eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt
1037426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
1038426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		return 0;
1039426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	}
1040426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt
1041426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	/* use single, unchained SBAL if it can hold the request */
1042426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) {
1043426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
104439eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt		return 0;
104539eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt	}
104639eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt
1047564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
104842428f747a8a0db9c6de03e105932316defad65dSwen Schillig					SBAL_FLAGS0_TYPE_WRITE_READ,
1049c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					sg_req, max_sbals);
1050c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (bytes <= 0)
10519072df4dc6e8fd569d583815edb0198af4b688b8Christof Schmitt		return -EIO;
1052c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.support.req_buf_length = bytes;
105342428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
1054c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1055564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
105642428f747a8a0db9c6de03e105932316defad65dSwen Schillig					SBAL_FLAGS0_TYPE_WRITE_READ,
1057c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					sg_resp, max_sbals);
1058b1a58985853574346f1518531bdd82069501b317Christof Schmitt	req->qtcb->bottom.support.resp_buf_length = bytes;
1059c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (bytes <= 0)
10609072df4dc6e8fd569d583815edb0198af4b688b8Christof Schmitt		return -EIO;
106198fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt
1062b1a58985853574346f1518531bdd82069501b317Christof Schmitt	return 0;
1063b1a58985853574346f1518531bdd82069501b317Christof Schmitt}
1064b1a58985853574346f1518531bdd82069501b317Christof Schmitt
1065b1a58985853574346f1518531bdd82069501b317Christof Schmittstatic int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
1066b1a58985853574346f1518531bdd82069501b317Christof Schmitt				 struct scatterlist *sg_req,
1067b1a58985853574346f1518531bdd82069501b317Christof Schmitt				 struct scatterlist *sg_resp,
1068b1a58985853574346f1518531bdd82069501b317Christof Schmitt				 int max_sbals)
1069b1a58985853574346f1518531bdd82069501b317Christof Schmitt{
1070b1a58985853574346f1518531bdd82069501b317Christof Schmitt	int ret;
1071b1a58985853574346f1518531bdd82069501b317Christof Schmitt
1072b1a58985853574346f1518531bdd82069501b317Christof Schmitt	ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals);
1073b1a58985853574346f1518531bdd82069501b317Christof Schmitt	if (ret)
1074b1a58985853574346f1518531bdd82069501b317Christof Schmitt		return ret;
1075b1a58985853574346f1518531bdd82069501b317Christof Schmitt
107698fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	/* common settings for ct/gs and els requests */
107798fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
107898fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
10799d38500de156fb28ffa8741acb90c4dc90a9fb4bChristof Schmitt	zfcp_fsf_start_timer(req, (2 * R_A_TOV + 10) * HZ);
1080c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1081c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return 0;
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1085c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS)
1086c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @ct: pointer to struct zfcp_send_ct with data for request
1087c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1089799b76d09aeee558d18c1f5b93e63f58f1d1fc11Christof Schmittint zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10915ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_wka_port *wka_port = ct->wka_port;
1092564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1093c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1094c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int ret = -EIO;
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1096564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1097564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1098c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1100564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, pool);
110109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1102025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1103c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		ret = PTR_ERR(req);
1104c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
11053f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt	}
11063f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt
110709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1108b1a58985853574346f1518531bdd82069501b317Christof Schmitt	ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp,
1109b1a58985853574346f1518531bdd82069501b317Christof Schmitt				    FSF_MAX_SBALS_PER_REQ);
1110553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (ret)
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto failed_send;
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1113c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_ct_handler;
11145ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->qtcb->header.port_handle = wka_port->handle;
1115c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = ct;
1116c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
11175771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_san_ct_request(req);
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1119c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	ret = zfcp_fsf_req_send(req);
1120c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1121c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1123c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1125c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_send:
1126c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1127c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1128564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1129c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ret;
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1132c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1134c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_send_els *send_els = req->data;
1135c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = send_els->port;
1136c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1138c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	send_els->status = -EINVAL;
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1140c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
11455771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_san_els_response(req);
1146c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		send_els->status = 0;
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
1149c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]){
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
115464b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann			if (port && (send_els->ls_code != ZFCP_LS_ADISC))
11556f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig				zfcp_fc_test_link(port);
1156c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/*fall through */
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_RETRY_IF_POSSIBLE:
1159c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ELS_COMMAND_REJECTED:
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PAYLOAD_SIZE_MISMATCH:
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_REQUEST_SIZE_TOO_LARGE:
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_RESPONSE_SIZE_TOO_LARGE:
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1169dc577d554a274b79a6ad05e9e1ac20c320200599Christof Schmitt		if (port)
1170dc577d554a274b79a6ad05e9e1ac20c320200599Christof Schmitt			zfcp_fsf_access_denied_port(req, port);
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1172c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SBAL_MISMATCH:
1173c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* should never occure, avoided in zfcp_fsf_send_els */
1174c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1176c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus:
1180aa551daf5cc6fb6c6e09bb993737f9cd46dc7145Heiko Carstens	if (send_els->handler)
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_els->handler(send_els->handler_data);
1182c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1184c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1185c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
1186c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @els: pointer to struct zfcp_send_els with data for the command
1187c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig */
1188c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_send_els(struct zfcp_send_els *els)
1189c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
1190c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1191564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = els->adapter->qdio;
1192c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int ret = -EIO;
1193c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1194564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1195564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1196c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
119709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1198564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, NULL);
119909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1200025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1201c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		ret = PTR_ERR(req);
1202c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1203c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
1204c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
120509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1206b1a58985853574346f1518531bdd82069501b317Christof Schmitt	ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, 2);
120744cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig
1208c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1209c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
1210c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
121198fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	req->qtcb->bottom.support.d_id = els->d_id;
1212c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_els_handler;
1213c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = els;
1214c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
12155771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_san_els_request(req);
1216c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1217c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	ret = zfcp_fsf_req_send(req);
1218c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1219c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
1220c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1221c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
1222c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1223c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_send:
1224c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1225c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1226564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1227c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ret;
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1230c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
123244cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1233c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1234564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1235c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1236c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1237564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1238564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1239c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
124009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1241564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
1242564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
124309a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1244025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1245c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
124909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1250564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
125152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
125252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1254c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.config.feature_selection =
1255aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_CFDC |
1256aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_LUN_SHARING |
12579eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin			FSF_FEATURE_NOTIFICATION_LOST |
1258aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_UPDATE_ALERT;
1259c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1260c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_config_data_handler;
1261c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1263287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1264c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1266c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1269c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1270564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
127152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	return retval;
127252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig}
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1274564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
1275c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				       struct fsf_qtcb_bottom_config *data)
127652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{
127744cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
1279c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1280c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1281564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1282564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1283ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
1284c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1285564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, NULL);
128609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1287025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1288c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1289ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
129052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	}
129152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1292564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
129352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
129452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
1295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_config_data_handler;
129652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1297c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.config.feature_selection =
129852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_CFDC |
129952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_LUN_SHARING |
130052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_NOTIFICATION_LOST |
130152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_UPDATE_ALERT;
130252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
130352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	if (data)
1304c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->data = data;
130552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1306c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
1307c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
1308564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1309553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (!retval)
1310058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
131152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1313ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt	return retval;
131452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1315ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmittout_unlock:
1316564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data - request information about local port
1322aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin * @erp_action: ERP action for the adapter for which port data is requested
1323c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1325c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1327564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
132844cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1329c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1330c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1332564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
133352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig		return -EOPNOTSUPP;
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1335564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1336564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1337c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
133809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1339564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
1340564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
134109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1342025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1344c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1345aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	}
1346aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
134709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1348564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
134952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
135052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_port_data_handler;
1353c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1354c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
135552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1356287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1357c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1359c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
136052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig		erp_action->fsf_req = NULL;
136152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	}
1362c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1363564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
136452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	return retval;
136552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig}
136652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
136752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig/**
136852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig * zfcp_fsf_exchange_port_data_sync - request information about local port
1369564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig * @qdio: pointer to struct zfcp_qdio
1370c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @data: pointer to struct fsf_qtcb_bottom_port
1371c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
137252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig */
1373564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
1374c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				     struct fsf_qtcb_bottom_port *data)
137552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{
137644cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1377c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
1378c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
137952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1380564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
138152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig		return -EOPNOTSUPP;
138252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1383564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1384564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1385ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
1386c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1387564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, NULL);
138809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1389025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1390c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1391ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	if (data)
1395c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->data = data;
139652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1397564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
139852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
139952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
140052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1401c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_port_data_handler;
1402c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
1403c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
1404564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1405ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt
1406553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (!retval)
1407058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
1408058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig
1409c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
1412ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt
1413ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmittout_unlock:
1414564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1415ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt	return retval;
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1418c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1420c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
1421c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct fsf_plogi *plogi;
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1424c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1425a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann		goto out;
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_ALREADY_OPEN:
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1431c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_access_denied_port(req, port);
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
1434c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
1435ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "Not enough FCP adapter resources to open "
14367ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 "remote port 0x%016Lx\n",
14377ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 (unsigned long long)port->wwpn);
14385ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_failed(port, "fsoph_1", req);
1439c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_NO_RETRY_POSSIBLE:
1446c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		port->handle = header->port_handle;
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1454d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1455d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
1456d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		                  &port->status);
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* check whether D_ID has changed during open */
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * FIXME: This check is not airtight, as the FCP channel does
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * not monitor closures of target port connections caused on
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the remote side. Thus, they might miss out on invalidating
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * locally cached WWPNs (and other N_Port parameters) of gone
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * target ports. So, our heroic attempt to make things safe
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * could be undermined by 'open port' response data tagged with
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * obsolete WWPNs. Another reason to monitor potential
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * connection closures ourself at least (by interpreting
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * incoming ELS' and unsolicited status). It just crosses my
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * mind that one should be able to cross-check by means of
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * another GID_PN straight after a port has been opened.
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Alternately, an ADISC/PDISC ELS should suffice, as well.
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1472c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
147339eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt		if (req->qtcb->bottom.support.els1_length >=
147439eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt		    FSF_PLOGI_MIN_LEN) {
147510d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt			if (plogi->serv_param.wwpn != port->wwpn) {
1476b98478d71b0fea6d35f96069612d92b76013589fChristof Schmitt				port->d_id = 0;
147710d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt				dev_warn(&port->adapter->ccw_device->dev,
147810d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt					 "A port opened with WWPN 0x%016Lx "
147910d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt					 "returned data that identifies it as "
148010d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt					 "WWPN 0x%016Lx\n",
148110d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt					 (unsigned long long) port->wwpn,
148210d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt					 (unsigned long long)
148310d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt					  plogi->serv_param.wwpn);
148410d00f78e67223ef429fa5f4abfc9ea4ad740490Christof Schmitt			} else {
1485c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				port->wwnn = plogi->serv_param.wwnn;
1486c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				zfcp_fc_plogi_evaluate(port, plogi);
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_UNKNOWN_OP_SUBTYPE:
1491c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1494a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann
1495a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermannout:
1496f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	put_device(&port->sysfs_device);
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1499c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1500c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_open_port - create and send open port request
1501c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1502c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
150644cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1507564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1508a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	struct zfcp_port *port = erp_action->port;
1509564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_fsf_req *req;
1510c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1511c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1512564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1513564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1514c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1515c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1516564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1517564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
151809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1519025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1520c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
1522c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
152409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1525564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1529c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_open_port_handler;
1530a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	req->qtcb->bottom.support.d_id = port->d_id;
1531a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	req->data = port;
1532c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1533c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
1534f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	get_device(&port->sysfs_device);
1535c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1536287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1537c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1539c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
1541f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		put_device(&port->sysfs_device);
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1543c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1544564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1548c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1550c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1552c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
155344cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1555c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
15575ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req);
1558c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
15635ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_modify_port_status(port, "fscph_2", req,
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    ZFCP_STATUS_COMMON_OPEN,
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    ZFCP_CLEAR);
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1570c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1571c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_port - create and send close port request
1572c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1573c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1575c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
157744cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1578564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1579c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1580c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1581c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1582564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1583564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1584c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1585c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1586564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1587564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
158809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1589025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1590c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
1592c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
159409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1595564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1599c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_close_port_handler;
1600c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->port;
1601c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1602c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1603c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
1604c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1605287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1606c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1608c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1611c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1612564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16165ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligstatic void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
16175ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
16185ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_wka_port *wka_port = req->data;
16195ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
16205ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16215ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
16225ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
16235ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16245ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16255ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16265ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	switch (header->fsf_status) {
16275ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
16285ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		dev_warn(&req->adapter->ccw_device->dev,
16295ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig			 "Opening WKA port 0x%x failed\n", wka_port->d_id);
1630dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
16315ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
16325ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1633dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
16345ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_ACCESS_DENIED:
16355ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
16365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		break;
16375ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_GOOD:
16385ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->handle = header->port_handle;
163927f492ccec94b6acd8440c83bfe0515ce4db0af0Swen Schillig		/* fall through */
164027f492ccec94b6acd8440c83bfe0515ce4db0af0Swen Schillig	case FSF_PORT_ALREADY_OPEN:
16415ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->status = ZFCP_WKA_PORT_ONLINE;
16425ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16435ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
16445ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	wake_up(&wka_port->completion_wq);
16455ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
16465ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16475ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig/**
16485ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * zfcp_fsf_open_wka_port - create and send open wka-port request
16495ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * @wka_port: pointer to struct zfcp_wka_port
16505ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * Returns: 0 on success, error otherwise
16515ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig */
16525ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligint zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
16535ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
16545ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct qdio_buffer_element *sbale;
1655564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
16565ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_fsf_req *req;
16575ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	int retval = -EIO;
16585ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1659564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1660564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
16615ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16625ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1663564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1664564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
166509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
16665ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (unlikely(IS_ERR(req))) {
16675ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		retval = PTR_ERR(req);
16685ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16695ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16705ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
167109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1672564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
16735ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
16745ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
16755ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16765ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->handler = zfcp_fsf_open_wka_port_handler;
16775ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->qtcb->bottom.support.d_id = wka_port->d_id;
16785ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->data = wka_port;
16795ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16805ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
16815ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	retval = zfcp_fsf_req_send(req);
16825ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (retval)
16835ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		zfcp_fsf_req_free(req);
16845ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
1685564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
16865ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	return retval;
16875ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
16885ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16895ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligstatic void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
16905ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
16915ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_wka_port *wka_port = req->data;
16925ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16935ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
16945ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
16955ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req);
16965ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16975ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16985ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	wka_port->status = ZFCP_WKA_PORT_OFFLINE;
16995ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	wake_up(&wka_port->completion_wq);
17005ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
17015ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
17025ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig/**
17035ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * zfcp_fsf_close_wka_port - create and send close wka port request
17045ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * @erp_action: pointer to struct zfcp_erp_action
17055ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * Returns: 0 on success, error otherwise
17065ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig */
17075ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligint zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
17085ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
17095ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct qdio_buffer_element *sbale;
1710564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
17115ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_fsf_req *req;
17125ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	int retval = -EIO;
17135ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1714564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1715564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
17165ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
17175ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1718564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1719564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
172009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
17215ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (unlikely(IS_ERR(req))) {
17225ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		retval = PTR_ERR(req);
17235ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
17245ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
17255ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
172609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1727564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
17285ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
17295ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
17305ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
17315ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->handler = zfcp_fsf_close_wka_port_handler;
17325ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->data = wka_port;
17335ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->qtcb->header.port_handle = wka_port->handle;
17345ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
17355ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
17365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	retval = zfcp_fsf_req_send(req);
17375ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (retval)
17385ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		zfcp_fsf_req_free(req);
17395ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
1740564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
17415ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	return retval;
17425ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
17435ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1744c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1746c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
1747c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zfcp_unit *unit;
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1750c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1751a5b11dda12ed7e3a79180b10ad6209a40a02989fChristof Schmitt		return;
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
17555ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req);
1756c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1759c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_access_denied_port(req, port);
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
17625c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		/* can't use generic zfcp_erp_modify_port_status because
17635c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
17645c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1765ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig		read_lock(&port->unit_list_lock);
1766ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig		list_for_each_entry(unit, &port->unit_list, list)
17675c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
17685c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt					  &unit->status);
1769ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig		read_unlock(&port->unit_list_lock);
1770dfb3cf00e402686f671db697adbd8b9f4c219268Swen Schillig		zfcp_erp_port_boxed(port, "fscpph2", req);
1771dfb3cf00e402686f671db697adbd8b9f4c219268Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
1772dfb3cf00e402686f671db697adbd8b9f4c219268Swen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
1773dfb3cf00e402686f671db697adbd8b9f4c219268Swen Schillig
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1778c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
1780c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* can't use generic zfcp_erp_modify_port_status because
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1789ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig		read_lock(&port->unit_list_lock);
1790ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig		list_for_each_entry(unit, &port->unit_list, list)
1791c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1792c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					  &unit->status);
1793ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig		read_unlock(&port->unit_list_lock);
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1798c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1799c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_physical_port - close physical port
1800c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1801c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1803c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
180544cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1806564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1807c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1808c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1809c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1810564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1811564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1814564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
1815564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
181609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1817025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1818c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1819c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1820c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
182209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1823564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1824c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
1825c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1827c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->port;
1828c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1829c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1830c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_close_physical_port_handler;
1831c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
1832c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1833287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1834c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1836c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1839c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1840564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1844c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1846c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
1847c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit = req->data;
1848c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
1849c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
1850c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_queue_designator *queue_designator =
1851c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&header->fsf_status_qual.fsf_queue_designator;
1852aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	int exclusive, readwrite;
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1854c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
185544cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1858b64ddf96456cde17be22bf74cafed381a29d58baHeiko Carstens			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  ZFCP_STATUS_UNIT_SHARED |
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  ZFCP_STATUS_UNIT_READONLY,
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  &unit->status);
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
18665ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req);
1867c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_ALREADY_OPEN:
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1871c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_access_denied_unit(req, unit);
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
1873553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
18765ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
1877c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
1878c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_SHARING_VIOLATION:
1881c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (header->fsf_status_qual.word[0])
1882553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt			dev_warn(&adapter->ccw_device->dev,
1883ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				 "LUN 0x%Lx on port 0x%Lx is already in "
1884ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				 "use by CSS%d, MIF Image ID %x\n",
18857ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig				 (unsigned long long)unit->fcp_lun,
18867ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig				 (unsigned long long)unit->port->wwpn,
1887ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				 queue_designator->cssid,
1888ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				 queue_designator->hla);
1889c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		else
1890553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt			zfcp_act_eval_err(adapter,
1891553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt					  header->fsf_status_qual.word[2]);
18925ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_unit_access_denied(unit, "fsouh_3", req);
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
1895c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
1898c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&adapter->ccw_device->dev,
1899ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "No handle is available for LUN "
1900ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "0x%016Lx on port 0x%016Lx\n",
19017ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 (unsigned long long)unit->fcp_lun,
19027ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 (unsigned long long)unit->port->wwpn);
19035ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_unit_failed(unit, "fsouh_4", req);
1904c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
1905c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_INVALID_COMMAND_OPTION:
1906c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
19116f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig			zfcp_fc_test_link(unit->port);
1912c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
1914c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unit->handle = header->lun_handle;
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
1922aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
1923aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
1924aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		    (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
19256fcf41d1d8796f41b893754324704e23971c2ea1Christof Schmitt		    !zfcp_ccw_priv_sch(adapter)) {
1926aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			exclusive = (bottom->lun_access_info &
1927aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin					FSF_UNIT_ACCESS_EXCLUSIVE);
1928aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			readwrite = (bottom->lun_access_info &
1929aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin					FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
1930aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!exclusive)
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		                atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&unit->status);
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!readwrite) {
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                		atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&unit->status);
1938c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				dev_info(&adapter->ccw_device->dev,
1939ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					 "SCSI device at LUN 0x%016Lx on port "
1940ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					 "0x%016Lx opened read-only\n",
19417ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					 (unsigned long long)unit->fcp_lun,
19427ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					 (unsigned long long)unit->port->wwpn);
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		}
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		if (exclusive && !readwrite) {
1946c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				dev_err(&adapter->ccw_device->dev,
1947ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"Exclusive read-only access not "
1948ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"supported (unit 0x%016Lx, "
1949ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"port 0x%016Lx)\n",
19507ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					(unsigned long long)unit->fcp_lun,
19517ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					(unsigned long long)unit->port->wwpn);
19525ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				zfcp_erp_unit_failed(unit, "fsouh_5", req);
1953c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
19545ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req);
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		} else if (!exclusive && readwrite) {
1956c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				dev_err(&adapter->ccw_device->dev,
1957ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"Shared read-write access not "
1958ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"supported (unit 0x%016Lx, port "
195927c3f0a6e4521ba0ff6e76da54969f0bf430f53aChristof Schmitt					"0x%016Lx)\n",
19607ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					(unsigned long long)unit->fcp_lun,
19617ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					(unsigned long long)unit->port->wwpn);
19625ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				zfcp_erp_unit_failed(unit, "fsouh_7", req);
1963c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
19645ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req);
19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		}
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1972c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_open_unit - open unit
1973c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1974c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1976c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
197844cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1979c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = erp_action->adapter;
1980564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
1981c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1982c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1983c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1984564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1985564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1988564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1989a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig				  adapter->pool.erp_req);
199009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1991025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1992c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1993c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1994c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
1995c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
199609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1997564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
2002c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
2003c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_open_unit_handler;
2004c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->unit;
2005c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
2006c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
2007c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2008c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE))
2009c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING;
2010c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2011287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
2012c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
2014c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2017c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2018564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2022c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2024c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit = req->data;
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2026c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
202744cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2029c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
20315ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req);
2032c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_HANDLE_NOT_VALID:
20355ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req);
2036c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
20395ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
2040c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
2041c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
2044c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		switch (req->qtcb->header.fsf_status_qual.word[0]) {
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
20466f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig			zfcp_fc_test_link(unit->port);
2047c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
2049c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2060c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_unit - close zfcp unit
2061c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_unit
2062c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2064c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
206644cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
2067564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
2068c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
2069c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
2072564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
207409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2075564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
2076564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
207709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2078025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
2079c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
2080c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2081c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
208309a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
2084564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
2085c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2088c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
2089c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.lun_handle = erp_action->unit->handle;
2090c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_close_unit_handler;
2091c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->unit;
2092c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
2093c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
2094fdf234527a070f6fc89f3ec5ee4ae1b263e59939Christof Schmitt
2095287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
2096c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
2097c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (retval) {
2098c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
2099c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		erp_action->fsf_req = NULL;
2100c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2101c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2102564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
2103c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2106c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmittstatic void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
2107c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt{
2108c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	lat_rec->sum += lat;
2109c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	lat_rec->min = min(lat_rec->min, lat);
2110c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	lat_rec->max = max(lat_rec->max, lat);
2111c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt}
2112c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
2113d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmittstatic void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
2114c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt{
2115d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	struct fsf_qual_latency_info *lat_in;
2116d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	struct latency_cont *lat = NULL;
2117c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit = req->unit;
2118d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	struct zfcp_blk_drv_data blktrc;
2119d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	int ticks = req->adapter->timer_ticks;
2120c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
2121d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	lat_in = &req->qtcb->prefix.prot_status_qual.latency_info;
2122c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
2123d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	blktrc.flags = 0;
2124d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
2125d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
2126d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		blktrc.flags |= ZFCP_BLK_REQ_ERROR;
2127d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	blktrc.inb_usage = req->queue_req.qdio_inb_usage;
2128d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	blktrc.outb_usage = req->queue_req.qdio_outb_usage;
2129d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt
2130d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
2131d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		blktrc.flags |= ZFCP_BLK_LAT_VALID;
2132d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		blktrc.channel_lat = lat_in->channel_lat * ticks;
2133d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		blktrc.fabric_lat = lat_in->fabric_lat * ticks;
2134d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt
2135d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		switch (req->qtcb->bottom.io.data_direction) {
2136d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		case FSF_DATADIR_READ:
2137d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			lat = &unit->latencies.read;
2138d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			break;
2139d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		case FSF_DATADIR_WRITE:
2140d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			lat = &unit->latencies.write;
2141d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			break;
2142d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		case FSF_DATADIR_CMND:
2143d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			lat = &unit->latencies.cmd;
2144d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			break;
2145d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		}
21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2147d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		if (lat) {
2148d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			spin_lock(&unit->latencies.lock);
2149d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
2150d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
2151d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			lat->counter++;
2152d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			spin_unlock(&unit->latencies.lock);
2153d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		}
21540997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	}
21550997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
2156d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	blk_add_driver_data(scsi->request->q, scsi->request, &blktrc,
2157d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			    sizeof(blktrc));
21580997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl}
21590997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
2160c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21620ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig	struct scsi_cmnd *scpnt;
21634318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	struct fcp_resp_with_ext *fcp_rsp;
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2166c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	read_lock_irqsave(&req->adapter->abort_lock, flags);
2167c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
21680ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig	scpnt = req->data;
21690ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig	if (unlikely(!scpnt)) {
21700ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig		read_unlock_irqrestore(&req->adapter->abort_lock, flags);
21710ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig		return;
21720ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig	}
21730ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig
2174c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) {
2175feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann		set_host_byte(scpnt, DID_SOFT_ERROR);
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2179c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2180feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann		set_host_byte(scpnt, DID_ERROR);
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21844318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
21854318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt);
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2187d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	zfcp_fsf_req_trace(req, scpnt);
21880997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
2189c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligskip_fsfstatus:
21908a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin	if (scpnt->result != 0)
21915771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req);
21928a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin	else if (scpnt->retries > 0)
21935771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_scsi_result("retr", 4, req->adapter->dbf, scpnt, req);
21948a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin	else
21955771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_scsi_result("norm", 6, req->adapter->dbf, scpnt, req);
21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scpnt->host_scribble = NULL;
21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(scpnt->scsi_done) (scpnt);
21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We must hold this lock until scsi_done has been called.
22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Otherwise we may call scsi_done after abort regarding this
22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * command has completed.
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Note: scsi_done must not block!
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2205c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2208c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22104318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	struct fcp_resp_with_ext *fcp_rsp;
22114318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	struct fcp_resp_rsp_info *rsp_info;
22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22134318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
22144318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
22154318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt
22164318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
2217c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
2218c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
2219c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
2220c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2221c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2222c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
2223c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
2224c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit;
2225c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
2226c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2227c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
2228c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		unit = req->data;
2229c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
2230c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		unit = req->unit;
2231c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2232c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2235c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (header->fsf_status) {
2236c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_HANDLE_MISMATCH:
2237c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_HANDLE_NOT_VALID:
22385ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
2239c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2240c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2241c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_FCPLUN_NOT_VALID:
2242c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_LUN_HANDLE_NOT_VALID:
22435ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
2244c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
2247c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2249c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ACCESS_DENIED:
2250c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_access_denied_unit(req, unit);
2251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2252c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_DIRECTION_INDICATOR_NOT_VALID:
2253c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
2254ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"Incorrect direction %d, unit 0x%016Lx on port "
2255ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%016Lx closed\n",
2256c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->bottom.io.data_direction,
22577ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(unsigned long long)unit->fcp_lun,
22587ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(unsigned long long)unit->port->wwpn);
22595ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
22605ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					  req);
2261c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2262c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2263c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_CMND_LENGTH_NOT_VALID:
2264c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
2265ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"Incorrect CDB length %d, unit 0x%016Lx on "
2266ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"port 0x%016Lx closed\n",
2267c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->bottom.io.fcp_cmnd_length,
22687ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(unsigned long long)unit->fcp_lun,
22697ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(unsigned long long)unit->port->wwpn);
22705ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
22715ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					  req);
2272c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2273c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2274c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_BOXED:
22755ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_boxed(unit->port, "fssfch5", req);
2276c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
2277c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
2278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2279c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_LUN_BOXED:
22805ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_unit_boxed(unit, "fssfch6", req);
2281c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
2282c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
2283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2284c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
2285c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (header->fsf_status_qual.word[0] ==
2286c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
22876f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig			zfcp_fc_test_link(unit->port);
2288c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2291c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligskip_fsfstatus:
2292c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
2293c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_send_fcp_ctm_handler(req);
2294c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else {
2295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_send_fcp_command_task_handler(req);
2296c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->unit = NULL;
2297f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig		put_device(&unit->sysfs_device);
2298c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2301c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
2302c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
2303c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @unit: unit where command is sent to
2304c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @scsi_cmnd: scsi command to be sent
23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
230663caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmittint zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
230763caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt				   struct scsi_cmnd *scsi_cmnd)
23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2309c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
23104318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	struct fcp_cmnd *fcp_cmnd;
2311bc90c8632f63cd94246e3fb6f1b6d7ecba48f1a0Christof Schmitt	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
2312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int real_bytes, retval = -EIO;
231363caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	struct zfcp_adapter *adapter = unit->port->adapter;
2314564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2316c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!(atomic_read(&unit->status) &
2317c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
2318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EBUSY;
23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2320564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock(&qdio->req_q_lock);
2321564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (atomic_read(&qdio->req_q.count) <= 0) {
2322564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		atomic_inc(&qdio->req_q_full);
2323c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
23248fdf30d5429605a4c30cc515c73e5eab140035deChristof Schmitt	}
232509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2326564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2327a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig				  adapter->pool.scsi_req);
232809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2329025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
2330c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
2331c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2332c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2333c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
233409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
2335f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	get_device(&unit->sysfs_device);
2336c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->unit = unit;
2337c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = scsi_cmnd;
2338c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_fcp_command_handler;
2339c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.lun_handle = unit->handle;
2340c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = unit->port->handle;
2341c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
23424318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
2343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2344c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	scsi_cmnd->host_scribble = (unsigned char *) req->req_id;
2345c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2346c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/*
2347c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 * set depending on data direction:
2348c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 *      data direction bits in SBALE (SB Type)
2349c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 *      data direction bits in QTCB
2350c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 */
2351c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (scsi_cmnd->sc_data_direction) {
2352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case DMA_NONE:
2353c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2355c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case DMA_FROM_DEVICE:
2356c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
2357c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2358c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case DMA_TO_DEVICE:
2359c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
2360c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		sbtype = SBAL_FLAGS0_TYPE_WRITE;
23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2362c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case DMA_BIDIRECTIONAL:
2363c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_scsi_cmnd;
23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23664318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
23674318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2369564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype,
2370c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					     scsi_sglist(scsi_cmnd),
2371c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					     FSF_MAX_SBALS_PER_REQ);
2372c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(real_bytes < 0)) {
237342428f747a8a0db9c6de03e105932316defad65dSwen Schillig		if (req->queue_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) {
2374c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			dev_err(&adapter->ccw_device->dev,
2375ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"Oversize data package, unit 0x%016Lx "
2376ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"on port 0x%016Lx closed\n",
23777ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig				(unsigned long long)unit->fcp_lun,
23787ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig				(unsigned long long)unit->port->wwpn);
23795ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_unit_shutdown(unit, 0, "fssfct1", req);
2380c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			retval = -EINVAL;
2381c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		}
2382c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_scsi_cmnd;
23831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2385c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
2386c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(retval))
2387c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_scsi_cmnd;
23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2389c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_scsi_cmnd:
2392f3450c7b917201bb49d67032e9f60d5125675d6aSwen Schillig	put_device(&unit->sysfs_device);
2393c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
2394c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	scsi_cmnd->host_scribble = NULL;
2395c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2396564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock(&qdio->req_q_lock);
2397c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2401c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_fcp_ctm - send SCSI task management command
2402c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @unit: pointer to struct zfcp_unit
2403c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @tm_flags: unsigned byte for task management flags
2404c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: on success pointer to struct fsf_req, NULL otherwise
24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
240663caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmittstruct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
240844cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
2409c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
24104318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	struct fcp_cmnd *fcp_cmnd;
2411564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2413c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!(atomic_read(&unit->status) &
2414c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
2415c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2417564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
2418564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
2419c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
242009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2421564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2422564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.scsi_req);
242309a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2424633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	if (IS_ERR(req)) {
2425633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig		req = NULL;
2426c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2427633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	}
24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2429c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
2430c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = unit;
2431c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_fcp_command_handler;
2432c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.lun_handle = unit->handle;
2433c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = unit->port->handle;
2434c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
2435c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
24364318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
2437c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2438564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
2439c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
2440c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24424318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
24434318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	zfcp_fc_fcp_tm(fcp_cmnd, unit->device, tm_flags);
24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2445c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
2446c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!zfcp_fsf_req_send(req))
2447c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2449c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
2450c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req = NULL;
2451c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2452564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
2453c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
2454c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2456c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
2457c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2460c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
2461c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_control_file - control file upload/download
2462c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @adapter: pointer to struct zfcp_adapter
2463c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_cfdc: pointer to struct zfcp_fsf_cfdc
2464c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: on success pointer to struct zfcp_fsf_req, NULL otherwise
24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2466c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstruct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
2467c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					   struct zfcp_fsf_cfdc *fsf_cfdc)
24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
246944cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
2470564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
2471c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
2472c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_support *bottom;
2473c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int direction, retval = -EIO, bytes;
2474c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2475c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
2476c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return ERR_PTR(-EOPNOTSUPP);
2477c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2478c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (fsf_cfdc->command) {
2479c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
2480c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		direction = SBAL_FLAGS0_TYPE_WRITE;
2481c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2482c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_QTCB_UPLOAD_CONTROL_FILE:
2483c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		direction = SBAL_FLAGS0_TYPE_READ;
2484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2485c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
2486c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return ERR_PTR(-EINVAL);
2487c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2489564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
2490564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
2491c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2493564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, NULL);
2494025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
2495c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = -EPERM;
2496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2497c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2499c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_control_file_handler;
25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2501564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
2502c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= direction;
25038a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
2504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom = &req->qtcb->bottom.support;
2505c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
2506c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom->option = fsf_cfdc->option;
25078a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
2508564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req,
2509564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig					direction, fsf_cfdc->sg,
2510564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig					FSF_MAX_SBALS_PER_REQ);
2511c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (bytes != ZFCP_CFDC_MAX_SIZE) {
2512c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
2513c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2514c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2516c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
2517c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
2518c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2519564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
25208a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
2521c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!retval) {
2522058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
2523c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return req;
25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2525c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ERR_PTR(retval);
25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2527bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2528bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig/**
2529bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO
2530bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @adapter: pointer to struct zfcp_adapter
2531bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @sbal_idx: response queue index of SBAL to be processed
2532bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */
2533564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligvoid zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2534bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig{
2535564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
2536564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx];
2537bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct qdio_buffer_element *sbale;
2538bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct zfcp_fsf_req *fsf_req;
2539bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	unsigned long flags, req_id;
2540bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	int idx;
2541bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2542bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
2543bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2544bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		sbale = &sbal->element[idx];
2545bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		req_id = (unsigned long) sbale->addr;
2546bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		spin_lock_irqsave(&adapter->req_list_lock, flags);
2547bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		fsf_req = zfcp_reqlist_find(adapter, req_id);
2548bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2549bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		if (!fsf_req)
2550bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			/*
2551bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 * Unknown request means that we have potentially memory
2552bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 * corruption and must stop the machine immediately.
2553bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 */
2554bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			panic("error: unknown req_id (%lx) on adapter %s.\n",
2555bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			      req_id, dev_name(&adapter->ccw_device->dev));
2556bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2557bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		list_del(&fsf_req->list);
2558bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		spin_unlock_irqrestore(&adapter->req_list_lock, flags);
2559bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
256042428f747a8a0db9c6de03e105932316defad65dSwen Schillig		fsf_req->queue_req.sbal_response = sbal_idx;
256142428f747a8a0db9c6de03e105932316defad65dSwen Schillig		fsf_req->queue_req.qdio_inb_usage =
2562564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig			atomic_read(&qdio->resp_q.count);
2563bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		zfcp_fsf_req_complete(fsf_req);
2564bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2565bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
2566bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			break;
2567bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	}
2568bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig}
2569