zfcp_fsf.c revision 98fc4d5c8cd9bd1a412cca922feecb54c1c22d8e
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"
14dcd20e2316cdc333dfdee09649dbe3642eb30e75Christof Schmitt#include "zfcp_dbf.h"
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_request_timeout_handler(unsigned long data)
17287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
18287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
195ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
205ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				"fsrth_1", NULL);
21287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
22287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
23287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req,
24287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt				 unsigned long timeout)
25287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
26287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
27287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.data = (unsigned long) fsf_req->adapter;
28287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.expires = jiffies + timeout;
29287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	add_timer(&fsf_req->timer);
30287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
31287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
32287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_start_erp_timer(struct zfcp_fsf_req *fsf_req)
33287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
34287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	BUG_ON(!fsf_req->erp_action);
35287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.function = zfcp_erp_timeout_handler;
36287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.data = (unsigned long) fsf_req->erp_action;
37287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.expires = jiffies + 30 * HZ;
38287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	add_timer(&fsf_req->timer);
39287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
40287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* association between FSF command and FSF QTCB type */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 fsf_qtcb_type[] = {
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_FCP_CMND] =             FSF_IO_COMMAND,
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_ABORT_FCP_CMND] =       FSF_SUPPORT_COMMAND,
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_OPEN_PORT_WITH_DID] =   FSF_SUPPORT_COMMAND,
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_OPEN_LUN] =             FSF_SUPPORT_COMMAND,
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_LUN] =            FSF_SUPPORT_COMMAND,
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_PORT] =           FSF_SUPPORT_COMMAND,
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_PHYSICAL_PORT] =  FSF_SUPPORT_COMMAND,
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_SEND_ELS] =             FSF_SUPPORT_COMMAND,
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_SEND_GENERIC] =         FSF_SUPPORT_COMMAND,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND,
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_EXCHANGE_PORT_DATA] =   FSF_PORT_COMMAND,
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_UPLOAD_CONTROL_FILE] =  FSF_SUPPORT_COMMAND
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
58553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
59553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
60c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	u16 subtable = table >> 16;
61553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	u16 rule = table & 0xffff;
62ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt	const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
63553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
64ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt	if (subtable && subtable < ARRAY_SIZE(act_type))
65553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt		dev_warn(&adapter->ccw_device->dev,
66ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "Access denied according to ACT rule type %s, "
67ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "rule %d\n", act_type[subtable], rule);
68553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
69553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
70553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
71553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt					struct zfcp_port *port)
72553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
73553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	struct fsf_qtcb_header *header = &req->qtcb->header;
74553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	dev_warn(&req->adapter->ccw_device->dev,
75ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		 "Access denied to port 0x%016Lx\n",
767ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig		 (unsigned long long)port->wwpn);
77553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
78553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
795ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_port_access_denied(port, "fspad_1", req);
80553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
81553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
82553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
83553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
84553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt					struct zfcp_unit *unit)
85553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
86553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	struct fsf_qtcb_header *header = &req->qtcb->header;
87553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	dev_warn(&req->adapter->ccw_device->dev,
88ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		 "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
897ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig		 (unsigned long long)unit->fcp_lun,
907ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig		 (unsigned long long)unit->port->wwpn);
91553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
92553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
935ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_unit_access_denied(unit, "fsuad_1", req);
94553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
95553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
96553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
97553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
98553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
99ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
100ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		"operational because of an unsupported FC class\n");
1015ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1", req);
102553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
103553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
104553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
105c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
106c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_req_free - free memory used by fsf request
107c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_req: pointer to struct zfcp_fsf_req
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
109c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligvoid zfcp_fsf_req_free(struct zfcp_fsf_req *req)
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
111c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(req->pool)) {
112a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (likely(req->qtcb))
113a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			mempool_free(req->qtcb, req->adapter->pool.qtcb_pool);
114c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		mempool_free(req, req->pool);
115dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens		return;
116dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens	}
117dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens
118a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(req->qtcb))
119a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb);
120a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	kfree(req);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
123c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
125c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
126c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
127c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port;
128c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int d_id = sr_buf->d_id & ZFCP_DID_MASK;
129c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	unsigned long flags;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	read_lock_irqsave(&zfcp_data.config_lock, flags);
132c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	list_for_each_entry(port, &adapter->port_list_head, list)
133c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (port->d_id == d_id) {
134c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1355ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_port_reopen(port, 0, "fssrpc1", req);
136c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			return;
137c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		}
138c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	read_unlock_irqrestore(&zfcp_data.config_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;
14570932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt	unsigned long flags;
146698ec01635819c5ae60090bb4efcbeffc41642fbMartin Peschke
147c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
148ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin		return;
149ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
150ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
15170932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt
15270932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt	read_lock_irqsave(&zfcp_data.config_lock, flags);
153a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	zfcp_scsi_schedule_rports_block(adapter);
15470932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
155ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
156c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!link_down)
1572f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann		goto out;
158ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
159aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	switch (link_down->error_code) {
160aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_LIGHT:
161c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
162ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "There is no light signal from the local "
163ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "fibre channel cable\n");
164aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
165aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_WRAP_PLUG:
166c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
167ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "There is a wrap plug instead of a fibre "
168ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "channel cable\n");
169aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
170aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FCP:
171c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
172ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The adjacent fibre channel node does not "
173ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "support FCP\n");
174aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
175aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_FIRMWARE_UPDATE:
176c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
177ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP device is suspended because of a "
178ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "firmware update\n");
179553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt		break;
180aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_INVALID_WWPN:
181c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
182ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP device detected a WWPN that is "
183ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "duplicate or not valid\n");
184aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
185aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
186c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
187ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The fibre channel fabric does not support NPIV\n");
188aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
189aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FCP_RESOURCES:
190c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
191ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP adapter cannot support more NPIV ports\n");
192aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
193aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
194c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
195ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The adjacent switch cannot support "
196ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "more NPIV ports\n");
197aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
198aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
199c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
200ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP adapter could not log in to the "
201ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "fibre channel fabric\n");
202aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
203aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
204c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
205ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The WWPN assignment file on the FCP adapter "
206ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been damaged\n");
207aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
208aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
209c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
210ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The mode table on the FCP adapter "
211ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been damaged\n");
212aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
213aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
214c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
215ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "All NPIV ports on the FCP adapter have "
216ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "been assigned\n");
217aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
218aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	default:
219c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
220ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The link between the FCP adapter and "
221ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "the FC fabric is down\n");
222aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	}
223c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
224c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_erp_adapter_failed(adapter, id, req);
225aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin}
226aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
227c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
229c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
230c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_link_down_info *ldi =
231c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		(struct fsf_link_down_info *) &sr_buf->payload;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
233c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (sr_buf->status_subtype) {
234c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
2355ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
237c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_FDISC_FAILED:
2385ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
240c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
2415ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL);
242c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	};
243c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
245c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
247c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
248c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
250c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
2515771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf);
252a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		mempool_free(sr_buf, adapter->pool.status_read_data);
253c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
254c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
255c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2575771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
259c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (sr_buf->status_type) {
260c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_PORT_CLOSED:
261c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_port_closed(req);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
263c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_INCOMING_ELS:
264c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fc_incoming_els(req);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
266c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
268c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
269ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		dev_warn(&adapter->ccw_device->dev,
270ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The error threshold for checksum statistics "
271ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been exceeded\n");
2725771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_hba_berr(adapter->dbf, req);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
274c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_LINK_DOWN:
275c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_link_down(req);
276c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
277c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_LINK_UP:
278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_info(&adapter->ccw_device->dev,
279ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The local link has been restored\n");
280c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* All ports should be marked as ready to run again */
2815ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL,
282c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					       ZFCP_STATUS_COMMON_RUNNING,
283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					       ZFCP_SET);
284c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_erp_adapter_reopen(adapter,
285c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
286c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_COMMON_ERP_FAILED,
2875ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					"fssrh_2", req);
288c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
289c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_NOTIFICATION_LOST:
290c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
2915ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
2925ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig							req);
293c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
294c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			schedule_work(&adapter->scan_work);
295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
296c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_CFDC_UPDATED:
2975ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
298c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
299c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
300c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->adapter_features = sr_buf->payload.word[0];
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	mempool_free(sr_buf, adapter->pool.status_read_data);
305c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
307c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	atomic_inc(&adapter->stat_miss);
3084544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	queue_work(adapter->work_queue, &adapter->stat_work);
309c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
313c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status_qual.word[0]) {
314c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_FCP_RSP_AVAILABLE:
315c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
316c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_NO_RETRY_POSSIBLE:
317c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
319c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_COMMAND_ABORTED:
320c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ABORTED;
321c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
322c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_NO_RECOM:
323c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
324ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter reported a problem "
325ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"that cannot be recovered\n");
3265ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req);
327c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
328c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
329c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/* all non-return stats set FSFREQ_ERROR*/
330c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
333c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
335c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
336c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
338c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
339c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_UNKNOWN_COMMAND:
340c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
341ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter does not recognize the command 0x%x\n",
342c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->header.fsf_command);
3435ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1", req);
344c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
345c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
346c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
347c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_fsfstatus_qual_eval(req);
348c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
349c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
350c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
353c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
354c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
355c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
356c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	union fsf_prot_status_qual *psq = &qtcb->prefix.prot_status_qual;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3585771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_hba_fsf_response(req);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
360c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
361c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
362c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */
363c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
364c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
366c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->prefix.prot_status) {
367c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_GOOD:
368c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_FSF_STATUS_PRESENTED:
369c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
370c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_QTCB_VERSION_ERROR:
371c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
372ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"QTCB version 0x%x not supported by FCP adapter "
373ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION,
374ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			psq->word[0], psq->word[1]);
3755ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1", req);
376c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
377c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_ERROR_STATE:
378c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_SEQ_NUMB_ERROR:
3795ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req);
380c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_RETRY;
381c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
382c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_UNSUPP_QTCB_TYPE:
383c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
384ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The QTCB type is not supported by the FCP adapter\n");
3855ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3", req);
386c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
387c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_HOST_CONNECTION_INITIALIZING:
388c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
389c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&adapter->status);
390c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_DUPLICATE_REQUEST_ID:
392c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
393ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%Lx is an ambiguous request identifier\n",
394c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			(unsigned long long)qtcb->bottom.support.req_handle);
3955ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
396c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
397c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_LINK_DOWN:
3985ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fspse_5",
3995ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					     &psq->link_down_info);
400c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* FIXME: reopening adapter now? better wait for link up */
4015ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
402c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
403c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_REEST_QUEUE:
404c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* All ports should be marked as ready to run again */
4055ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL,
406c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					       ZFCP_STATUS_COMMON_RUNNING,
407c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					       ZFCP_SET);
408c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_erp_adapter_reopen(adapter,
409c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
4105ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					ZFCP_STATUS_COMMON_ERP_FAILED,
4115ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					"fspse_8", req);
412c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
413c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
414c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
415ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%x is not a valid transfer protocol status\n",
416c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			qtcb->prefix.prot_status);
4175ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req);
418c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
419c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
422c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
423c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_req_complete - process completion of a FSF request
424c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_req: The FSF request that has been completed.
425c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig *
426c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * When a request has been completed either from the FCP adapter,
427c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * or it has been dismissed due to a queue shutdown, this function
428c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * is called to process the completion status and trigger further
429c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * events related to the FSF request.
430c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig */
431bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schilligstatic void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
433c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
434c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_handler(req);
435c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
436c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
438c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	del_timer(&req->timer);
439c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_protstatus_eval(req);
440c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_fsfstatus_eval(req);
441c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler(req);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
443c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->erp_action)
444287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt		zfcp_erp_notify(req->erp_action, 0);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
446c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
447c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
448c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
449058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		complete(&req->completion);
450c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
452bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig/**
453bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
454bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @adapter: pointer to struct zfcp_adapter
455bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig *
456bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Never ever call this without shutting down the adapter first.
457bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Otherwise the adapter would continue using and corrupting s390 storage.
458bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Included BUG_ON() call to ensure this is done.
459bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * ERP is supposed to be the only user of this function.
460bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */
461bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schilligvoid zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
462bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig{
463bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct zfcp_fsf_req *req, *tmp;
464bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	unsigned long flags;
465bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	LIST_HEAD(remove_queue);
466bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	unsigned int i;
467bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
468bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
469bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	spin_lock_irqsave(&adapter->req_list_lock, flags);
470bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	for (i = 0; i < REQUEST_LIST_SIZE; i++)
471bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		list_splice_init(&adapter->req_list[i], &remove_queue);
472bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
473bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
474bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	list_for_each_entry_safe(req, tmp, &remove_queue, list) {
475bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		list_del(&req->list);
476bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
477bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		zfcp_fsf_req_complete(req);
478bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	}
479bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig}
480bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
481c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
482c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
483c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_config *bottom;
484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
485c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
487c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom = &req->qtcb->bottom.config;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
489c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->data)
490c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(req->data, bottom, sizeof(*bottom));
491c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
492c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_node_name(shost) = bottom->nport_serv_param.wwnn;
493c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
494c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
495c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_speed(shost) = bottom->fc_link_speed;
496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
497c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
498c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->hydra_version = bottom->adapter_type;
499c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->timer_ticks = bottom->timer_interval;
500c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
501c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (fc_host_permanent_port_name(shost) == -1)
502c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
503c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (bottom->fc_topology) {
505c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_P2P:
506c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
507c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->peer_wwpn = bottom->plogi_payload.wwpn;
508c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->peer_wwnn = bottom->plogi_payload.wwnn;
509c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
510c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
511c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_FABRIC:
512c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
513c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
514c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_AL:
515c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
516dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
517c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
518c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
519ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"Unknown or unsupported arbitrated loop "
520ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"fibre channel topology detected\n");
5215ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req);
522c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EIO;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
524c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
528c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
529553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
530553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	struct zfcp_adapter *adapter = req->adapter;
531c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
532c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config;
533c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
534553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
535c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
536c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
538c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->fsf_lic_version = bottom->lic_version;
539c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->adapter_features = bottom->adapter_features;
540c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->connection_features = bottom->connection_features;
541c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_wwpn = 0;
542c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_wwnn = 0;
543c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_d_id = 0;
5448a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
545c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->header.fsf_status) {
546c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GOOD:
547c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (zfcp_fsf_exchange_config_evaluate(req))
548c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			return;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
550c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
551c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			dev_err(&adapter->ccw_device->dev,
552ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"FCP adapter maximum QTCB size (%d bytes) "
553ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"is too small\n",
554ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				bottom->max_qtcb_size);
5555ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1", req);
556c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			return;
557c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		}
558c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
559c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&adapter->status);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
561c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
562c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_node_name(shost) = 0;
563c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_name(shost) = 0;
564c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_id(shost) = 0;
565c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
566c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
567c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->hydra_version = 0;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
569c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
570c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&adapter->status);
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5725ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fsecdh2",
573c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			&qtcb->header.fsf_status_qual.link_down_info);
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
575c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
5765ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req);
577c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
578c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
580c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
581c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->hardware_version = bottom->hardware_version;
582c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(fc_host_serial_number(shost), bottom->serial_number,
583c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       min(FC_SERIAL_NUMBER_SIZE, 17));
584c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		EBCASC(fc_host_serial_number(shost),
585c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       min(FC_SERIAL_NUMBER_SIZE, 17));
586c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
588c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
589c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
590ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter only supports newer "
591ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"control block versions\n");
5925ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4", req);
593c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
594c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
595c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
596c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
597ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter only supports older "
598ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"control block versions\n");
5995ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5", req);
600c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
601c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
603c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
604c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
605c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
606c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_port *bottom = &req->qtcb->bottom.port;
607c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
609c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->data)
610c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(req->data, bottom, sizeof(*bottom));
6119eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin
6120282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
613c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = bottom->wwpn;
6140282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
6150282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt	} else
616c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
617c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
618c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_supported_speeds(shost) = bottom->supported_speed;
619c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
622c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
623c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
624c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
625c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
626c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
627c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
628c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->header.fsf_status) {
629c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GOOD:
630c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_exchange_port_evaluate(req);
631c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
632c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
633c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_exchange_port_evaluate(req);
6345ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_fsf_link_down_info_eval(req, "fsepdh1",
635c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			&qtcb->header.fsf_status_qual.link_down_info);
636aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
638c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
639d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig
640564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligstatic int zfcp_fsf_sbal_check(struct zfcp_qdio *qdio)
641c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
642564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio_queue *req_q = &qdio->req_q;
643c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
644564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
6457001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann	if (atomic_read(&req_q->count))
6467001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann		return 1;
647564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
6487001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann	return 0;
6497001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann}
6507001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann
651564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligstatic int zfcp_fsf_req_sbal_get(struct zfcp_qdio *qdio)
6527001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann{
653564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
6547001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann	long ret;
655dedbc2b3cb8404c618975bd2811c7605a4ccb51eChristof Schmitt
656564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
657564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	ret = wait_event_interruptible_timeout(qdio->req_q_wq,
658564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig			       zfcp_fsf_sbal_check(qdio), 5 * HZ);
659c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret > 0)
660c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return 0;
661cbf1ed0264da104573458aedc220ebfcd02567f6Christof Schmitt	if (!ret) {
662564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		atomic_inc(&qdio->req_q_full);
663cbf1ed0264da104573458aedc220ebfcd02567f6Christof Schmitt		/* assume hanging outbound queue, try queue recovery */
664cbf1ed0264da104573458aedc220ebfcd02567f6Christof Schmitt		zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
665cbf1ed0264da104573458aedc220ebfcd02567f6Christof Schmitt	}
6667001f0c4863230dd1560425fa0f5aad9e21716b8Martin Petermann
667564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
668c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return -EIO;
669c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
670c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
671a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligstatic struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
672c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
673c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
674a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
675a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(pool))
676a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		req = mempool_alloc(pool, GFP_ATOMIC);
677a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	else
678a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		req = kmalloc(sizeof(*req), GFP_ATOMIC);
679a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
680a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (unlikely(!req))
681c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
682a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
683c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(req, 0, sizeof(*req));
68488f2a977870af655296a682fe2a58c822cd25bb2Christof Schmitt	req->pool = pool;
685c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
686c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
687c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
688a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligstatic struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
689c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
690a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	struct fsf_qtcb *qtcb;
691c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
692c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(pool))
693c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		qtcb = mempool_alloc(pool, GFP_ATOMIC);
694c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
695a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC);
696a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
697c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!qtcb))
698c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
699c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
700c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(qtcb, 0, sizeof(*qtcb));
701a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	return qtcb;
702c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
703c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
704564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligstatic struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
70509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig						u32 fsf_cmd, mempool_t *pool)
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
70744cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
708564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio_queue *req_q = &qdio->req_q;
709564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
710a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
712c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!req))
7131e9b16430ff4fd09408a74342d6b8338228e2f70Christof Schmitt		return ERR_PTR(-ENOMEM);
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
715c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (adapter->req_no == 0)
716c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->req_no++;
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
718c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	INIT_LIST_HEAD(&req->list);
719c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	init_timer(&req->timer);
720058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig	init_completion(&req->completion);
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
722c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->adapter = adapter;
723c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->fsf_command = fsf_cmd;
72452bfb558d2803590f86360ec3af1750897a9c010Christof Schmitt	req->req_id = adapter->req_no;
72542428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbal_number = 1;
72642428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbal_first = req_q->first;
72742428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbal_last = req_q->first;
72842428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbale_curr = 1;
729c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
730564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
731c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].addr = (void *) req->req_id;
732c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_COMMAND;
733c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
734a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
735a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (likely(pool))
736a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool);
737a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		else
738a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			req->qtcb = zfcp_qtcb_alloc(NULL);
739a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
740a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (unlikely(!req->qtcb)) {
741a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			zfcp_fsf_req_free(req);
742a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			return ERR_PTR(-ENOMEM);
743a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		}
744a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
745564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
746c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.req_id = req->req_id;
747c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.ulp_info = 26;
748c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command];
749c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION;
750c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->header.req_handle = req->req_id;
751c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->header.fsf_command = req->fsf_command;
752c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->seq_no = adapter->fsf_req_seq_no;
753c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
754c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		sbale[1].addr = (void *) req->qtcb;
755c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		sbale[1].length = sizeof(struct fsf_qtcb);
756c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
757c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
758c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) {
759c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
760c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return ERR_PTR(-EIO);
761c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
762951f746fece2e24a26853b3872d16e9013b6fe0bChristof Schmitt
763c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
766c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
767c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
768c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
769564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
770135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	unsigned long	     flags;
771135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	int		     idx;
772135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	int		     with_qtcb = (req->qtcb != NULL);
773c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
774c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/* put allocated FSF request into hash table */
77545316a86a67934ab499dcfac44c91aa8f39c4c78Heiko Carstens	spin_lock_irqsave(&adapter->req_list_lock, flags);
776c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	idx = zfcp_reqlist_hash(req->req_id);
777c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	list_add_tail(&req->list, &adapter->req_list[idx]);
77845316a86a67934ab499dcfac44c91aa8f39c4c78Heiko Carstens	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
779c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
780564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
781c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->issued = get_clock();
782564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_qdio_send(qdio, &req->queue_req)) {
783c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		del_timer(&req->timer);
7843765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		spin_lock_irqsave(&adapter->req_list_lock, flags);
7853765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		/* lookup request again, list might have changed */
7863765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		if (zfcp_reqlist_find_safe(adapter, req))
7873765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt			zfcp_reqlist_remove(adapter, req);
7883765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		spin_unlock_irqrestore(&adapter->req_list_lock, flags);
7895ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req);
790c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EIO;
791c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
792c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
793c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/* Don't increase for unsolicited status */
794135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	if (with_qtcb)
795c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->fsf_req_seq_no++;
79652bfb558d2803590f86360ec3af1750897a9c010Christof Schmitt	adapter->req_no++;
797c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
798c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return 0;
799c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
800c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
801c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
802c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_status_read - send status read request
803c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @adapter: pointer to struct zfcp_adapter
804c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @req_flags: request flags
805c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, ERROR otherwise
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
807564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_status_read(struct zfcp_qdio *qdio)
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
809564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
810c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
811c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf;
81244cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
813c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
815564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
816564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
817c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
818c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
819564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS,
820a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig				  adapter->pool.status_read_req);
821025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
822c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
823c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
826564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
827c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
82842428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbale_curr = 2;
829c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
830a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
831c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!sr_buf) {
832c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = -ENOMEM;
833c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_buf;
834c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
835c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(sr_buf, 0, sizeof(*sr_buf));
836c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = sr_buf;
837564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_curr(qdio, &req->queue_req);
838c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale->addr = (void *) sr_buf;
839c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale->length = sizeof(*sr_buf);
840059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann
841c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
842c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (retval)
843c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_req_send;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
845c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
846c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
847c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_req_send:
848a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	mempool_free(sr_buf, adapter->pool.status_read_data);
849c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_buf:
850c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
8515771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
852c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
853564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
854c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
855c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
856c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
857c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
858c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
859c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit = req->data;
860c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
861c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
862c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
863c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
864c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
865c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
867c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (fsq->word[0] == fsq->word[1]) {
8685ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_adapter_reopen(unit->port->adapter, 0,
8695ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig						"fsafch1", req);
870c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_HANDLE_NOT_VALID:
874c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (fsq->word[0] == fsq->word[1]) {
8755ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
876c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
880c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
8835ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_boxed(unit->port, "fsafch3", req);
884c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
885c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_BOXED:
8885ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_unit_boxed(unit, "fsafch4", req);
889c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
890c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
893c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		switch (fsq->word[0]) {
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
8956f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig			zfcp_fc_test_link(unit->port);
896dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt			/* fall through */
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
898c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
903c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
909c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_abort_fcp_command - abort running SCSI command
910c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @old_req_id: unsigned long
911c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @unit: pointer to struct zfcp_unit
912c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: pointer to struct zfcp_fsf_req
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
915c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstruct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
91663caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt						struct zfcp_unit *unit)
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
91844cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
919c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
920564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
9218a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
922564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
923564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
924c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
925564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
926564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.scsi_abort);
927633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	if (IS_ERR(req)) {
928633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig		req = NULL;
929c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
930633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	}
9312abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann
932c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!(atomic_read(&unit->status) &
933c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
934c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out_error_free;
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
936564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
937c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
938c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
940c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = unit;
941c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_abort_fcp_command_handler;
942c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.lun_handle = unit->handle;
943c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = unit->port->handle;
944c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.support.req_handle = (u64) old_req_id;
945c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
946c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
947c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!zfcp_fsf_req_send(req))
948c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
949c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
950c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout_error_free:
951c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
952c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req = NULL;
953c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
954564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
955c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
958c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
960c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
961c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_send_ct *send_ct = req->data;
962c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
964c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	send_ct->status = -EINVAL;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
966c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_GOOD:
9715771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_san_ct_response(req);
972c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		send_ct->status = 0;
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
975c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_ADAPTER_STATUS_AVAILABLE:
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch (header->fsf_status_qual.word[0]){
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
981c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_PORT_BOXED:
988c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
989c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
991c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_HANDLE_NOT_VALID:
9925ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req);
993dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
994c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GENERIC_COMMAND_REJECTED:
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PAYLOAD_SIZE_MISMATCH:
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_REQUEST_SIZE_TOO_LARGE:
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_RESPONSE_SIZE_TOO_LARGE:
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_SBAL_MISMATCH:
999c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus:
1004c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (send_ct->handler)
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_ct->handler(send_ct->handler_data);
1006c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1008426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmittstatic void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
1009426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt					    struct scatterlist *sg_req,
1010426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt					    struct scatterlist *sg_resp)
1011426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt{
1012426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
1013426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[2].addr   = sg_virt(sg_req);
1014426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[2].length = sg_req->length;
1015426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[3].addr   = sg_virt(sg_resp);
1016426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[3].length = sg_resp->length;
1017426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
1018426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt}
1019426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt
1020426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmittstatic int zfcp_fsf_one_sbal(struct scatterlist *sg)
1021426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt{
1022426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	return sg_is_last(sg) && sg->length <= PAGE_SIZE;
1023426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt}
1024426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt
102539eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmittstatic int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
102639eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt				       struct scatterlist *sg_req,
102739eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt				       struct scatterlist *sg_resp,
102839eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt				       int max_sbals)
1029c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
103042428f747a8a0db9c6de03e105932316defad65dSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
1031564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio,
103242428f747a8a0db9c6de03e105932316defad65dSwen Schillig							       &req->queue_req);
103342428f747a8a0db9c6de03e105932316defad65dSwen Schillig	u32 feat = adapter->adapter_features;
1034c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int bytes;
1035c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
103639eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
1037426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
103839eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt			return -EOPNOTSUPP;
103939eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt
1040426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
1041426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		return 0;
1042426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	}
1043426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt
1044426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	/* use single, unchained SBAL if it can hold the request */
1045426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) {
1046426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
104739eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt		return 0;
104839eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt	}
104939eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt
1050564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
105142428f747a8a0db9c6de03e105932316defad65dSwen Schillig					SBAL_FLAGS0_TYPE_WRITE_READ,
1052c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					sg_req, max_sbals);
1053c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (bytes <= 0)
10549072df4dc6e8fd569d583815edb0198af4b688b8Christof Schmitt		return -EIO;
1055c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.support.req_buf_length = bytes;
105642428f747a8a0db9c6de03e105932316defad65dSwen Schillig	req->queue_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
1057c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1058564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
105942428f747a8a0db9c6de03e105932316defad65dSwen Schillig					SBAL_FLAGS0_TYPE_WRITE_READ,
1060c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					sg_resp, max_sbals);
1061c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (bytes <= 0)
10629072df4dc6e8fd569d583815edb0198af4b688b8Christof Schmitt		return -EIO;
106398fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt
106498fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	/* common settings for ct/gs and els requests */
1065c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.support.resp_buf_length = bytes;
106698fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
106798fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
106898fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10);
1069c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1070c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return 0;
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1074c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS)
1075c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @ct: pointer to struct zfcp_send_ct with data for request
1076c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1078799b76d09aeee558d18c1f5b93e63f58f1d1fc11Christof Schmittint zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10805ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_wka_port *wka_port = ct->wka_port;
1081564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1082c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1083c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int ret = -EIO;
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1085564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1086564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1087c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1089564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, pool);
109009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1091025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1092c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		ret = PTR_ERR(req);
1093c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
10943f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt	}
10953f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt
109609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
109739eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt	ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp,
109839eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt					  FSF_MAX_SBALS_PER_REQ);
1099553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (ret)
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto failed_send;
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1102c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_ct_handler;
11035ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->qtcb->header.port_handle = wka_port->handle;
1104c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = ct;
1105c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
11065771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_san_ct_request(req);
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1108c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	ret = zfcp_fsf_req_send(req);
1109c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1110c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1112c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1114c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_send:
1115c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1116c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1117564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1118c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ret;
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1123c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_send_els *send_els = req->data;
1124c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = send_els->port;
1125c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1127c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	send_els->status = -EINVAL;
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1129c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
11345771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_san_els_response(req);
1135c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		send_els->status = 0;
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
1138c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]){
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
114364b29a130901d5b8578e9f602cf2dae56aaff224Andreas Herrmann			if (port && (send_els->ls_code != ZFCP_LS_ADISC))
11446f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig				zfcp_fc_test_link(port);
1145c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/*fall through */
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_RETRY_IF_POSSIBLE:
1148c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ELS_COMMAND_REJECTED:
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PAYLOAD_SIZE_MISMATCH:
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_REQUEST_SIZE_TOO_LARGE:
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_RESPONSE_SIZE_TOO_LARGE:
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1158dc577d554a274b79a6ad05e9e1ac20c320200599Christof Schmitt		if (port)
1159dc577d554a274b79a6ad05e9e1ac20c320200599Christof Schmitt			zfcp_fsf_access_denied_port(req, port);
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1161c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SBAL_MISMATCH:
1162c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* should never occure, avoided in zfcp_fsf_send_els */
1163c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1165c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus:
1169aa551daf5cc6fb6c6e09bb993737f9cd46dc7145Heiko Carstens	if (send_els->handler)
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_els->handler(send_els->handler_data);
1171c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1173c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1174c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
1175c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @els: pointer to struct zfcp_send_els with data for the command
1176c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig */
1177c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_send_els(struct zfcp_send_els *els)
1178c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
1179c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1180564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = els->adapter->qdio;
1181c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int ret = -EIO;
1182c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1183564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1184564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1185c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
118609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1187564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, NULL);
118809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1189025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1190c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		ret = PTR_ERR(req);
1191c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1192c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
1193c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
119409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
119539eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt	ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
119644cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig
1197c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1198c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
1199c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
120098fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	req->qtcb->bottom.support.d_id = els->d_id;
1201c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_els_handler;
1202c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = els;
1203c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
12045771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_san_els_request(req);
1205c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1206c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	ret = zfcp_fsf_req_send(req);
1207c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1208c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
1209c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1210c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
1211c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1212c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_send:
1213c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1214c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1215564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1216c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ret;
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1219c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
122144cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1222c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1223564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1224c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1225c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1226564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1227564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1228c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
122909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1230564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
1231564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
123209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1233025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1234c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1235c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
123809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1239564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
124052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
124152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1243c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.config.feature_selection =
1244aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_CFDC |
1245aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_LUN_SHARING |
12469eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin			FSF_FEATURE_NOTIFICATION_LOST |
1247aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_UPDATE_ALERT;
1248c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1249c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_config_data_handler;
1250c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1252287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1253c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1255c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1258c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1259564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
126052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	return retval;
126152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig}
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1263564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
1264c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				       struct fsf_qtcb_bottom_config *data)
126552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{
126644cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1267c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
1268c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1269c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1270564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1271564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1272ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
1273c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1274564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, NULL);
127509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1276025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1277c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1278ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
127952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	}
128052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1281564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
128252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
128352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
1284c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_config_data_handler;
128552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1286c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.config.feature_selection =
128752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_CFDC |
128852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_LUN_SHARING |
128952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_NOTIFICATION_LOST |
129052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_UPDATE_ALERT;
129152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
129252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	if (data)
1293c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->data = data;
129452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
1296c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
1297564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1298553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (!retval)
1299058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
130052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1301c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1302ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt	return retval;
130352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1304ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmittout_unlock:
1305564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data - request information about local port
1311aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin * @erp_action: ERP action for the adapter for which port data is requested
1312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1314c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1316564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
131744cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1319c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
132252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig		return -EOPNOTSUPP;
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1324564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1325564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1326c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
132709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1328564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
1329564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
133009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1331025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1332c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1333c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1334aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	}
1335aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
133609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1337564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
133852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
133952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1341c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_port_data_handler;
1342c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
134452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1345287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1346c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1348c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
134952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig		erp_action->fsf_req = NULL;
135052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	}
1351c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1352564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
135352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	return retval;
135452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig}
135552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
135652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig/**
135752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig * zfcp_fsf_exchange_port_data_sync - request information about local port
1358564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig * @qdio: pointer to struct zfcp_qdio
1359c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @data: pointer to struct fsf_qtcb_bottom_port
1360c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
136152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig */
1362564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
1363c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				     struct fsf_qtcb_bottom_port *data)
136452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{
136544cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1366c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
1367c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
136852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1369564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
137052ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig		return -EOPNOTSUPP;
137152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1372564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1373564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1374ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
1375c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1376564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, NULL);
137709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1378025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1379c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1380ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
138352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	if (data)
1384c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->data = data;
138552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1386564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
138752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
138852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
138952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1390c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_port_data_handler;
1391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
1392c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
1393564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1394ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt
1395553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (!retval)
1396058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
1397058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig
1398c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
1401ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt
1402ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmittout_unlock:
1403564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
1404ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt	return retval;
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1407c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1409c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
1410c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct fsf_plogi *plogi;
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1413c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1414a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann		goto out;
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_ALREADY_OPEN:
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1420c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_access_denied_port(req, port);
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
1423c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
1424ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "Not enough FCP adapter resources to open "
14257ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 "remote port 0x%016Lx\n",
14267ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 (unsigned long long)port->wwpn);
14275ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_failed(port, "fsoph_1", req);
1428c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_NO_RETRY_POSSIBLE:
1435c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		port->handle = header->port_handle;
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1443d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1444d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
1445d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		                  &port->status);
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* check whether D_ID has changed during open */
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * FIXME: This check is not airtight, as the FCP channel does
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * not monitor closures of target port connections caused on
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the remote side. Thus, they might miss out on invalidating
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * locally cached WWPNs (and other N_Port parameters) of gone
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * target ports. So, our heroic attempt to make things safe
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * could be undermined by 'open port' response data tagged with
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * obsolete WWPNs. Another reason to monitor potential
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * connection closures ourself at least (by interpreting
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * incoming ELS' and unsolicited status). It just crosses my
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * mind that one should be able to cross-check by means of
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * another GID_PN straight after a port has been opened.
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Alternately, an ADISC/PDISC ELS should suffice, as well.
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1461c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
146239eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt		if (req->qtcb->bottom.support.els1_length >=
146339eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt		    FSF_PLOGI_MIN_LEN) {
1464c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			if (plogi->serv_param.wwpn != port->wwpn)
1465b98478d71b0fea6d35f96069612d92b76013589fChristof Schmitt				port->d_id = 0;
1466c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			else {
1467c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				port->wwnn = plogi->serv_param.wwnn;
1468c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				zfcp_fc_plogi_evaluate(port, plogi);
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_UNKNOWN_OP_SUBTYPE:
1473c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1476a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann
1477a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermannout:
1478a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	zfcp_port_put(port);
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1482c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_open_port - create and send open port request
1483c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1486c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
148844cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1489564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1490a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	struct zfcp_port *port = erp_action->port;
1491564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_fsf_req *req;
1492c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1493c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1494564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1495564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1497c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1498564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1499564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
150009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1501025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1502c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
1504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
150609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1507564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_open_port_handler;
1512a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	req->qtcb->bottom.support.d_id = port->d_id;
1513a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	req->data = port;
1514c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1515c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
1516a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	zfcp_port_get(port);
1517c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1518287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1519c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1521c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
1523a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann		zfcp_port_put(port);
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1525c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1526564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1530c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1532c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1534c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
153544cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1537c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
15395ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req);
1540c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
15455ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_modify_port_status(port, "fscph_2", req,
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    ZFCP_STATUS_COMMON_OPEN,
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    ZFCP_CLEAR);
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1552c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1553c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_port - create and send close port request
1554c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1555c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1557c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
155944cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1560564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1561c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1562c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1563c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1564564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1565564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
1566c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1567c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1568564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1569564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
157009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1571025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1572c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
1574c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
157609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1577564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_close_port_handler;
1582c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->port;
1583c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1584c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1585c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
1586c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1587287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1588c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1590c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1593c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1594564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15985ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligstatic void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
15995ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
16005ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_wka_port *wka_port = req->data;
16015ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
16025ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16035ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
16045ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
16055ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16065ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16075ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16085ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	switch (header->fsf_status) {
16095ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
16105ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		dev_warn(&req->adapter->ccw_device->dev,
16115ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig			 "Opening WKA port 0x%x failed\n", wka_port->d_id);
1612dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
16135ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
16145ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1615dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
16165ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_ACCESS_DENIED:
16175ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
16185ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		break;
16195ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_GOOD:
16205ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->handle = header->port_handle;
162127f492ccec94b6acd8440c83bfe0515ce4db0af0Swen Schillig		/* fall through */
162227f492ccec94b6acd8440c83bfe0515ce4db0af0Swen Schillig	case FSF_PORT_ALREADY_OPEN:
16235ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->status = ZFCP_WKA_PORT_ONLINE;
16245ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16255ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
16265ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	wake_up(&wka_port->completion_wq);
16275ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
16285ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16295ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig/**
16305ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * zfcp_fsf_open_wka_port - create and send open wka-port request
16315ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * @wka_port: pointer to struct zfcp_wka_port
16325ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * Returns: 0 on success, error otherwise
16335ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig */
16345ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligint zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
16355ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
16365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct qdio_buffer_element *sbale;
1637564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
16385ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_fsf_req *req;
16395ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	int retval = -EIO;
16405ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1641564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1642564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
16435ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16445ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1645564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1646564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
164709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
16485ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (unlikely(IS_ERR(req))) {
16495ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		retval = PTR_ERR(req);
16505ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16515ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16525ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
165309a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1654564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
16555ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
16565ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
16575ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16585ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->handler = zfcp_fsf_open_wka_port_handler;
16595ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->qtcb->bottom.support.d_id = wka_port->d_id;
16605ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->data = wka_port;
16615ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16625ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
16635ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	retval = zfcp_fsf_req_send(req);
16645ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (retval)
16655ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		zfcp_fsf_req_free(req);
16665ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
1667564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
16685ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	return retval;
16695ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
16705ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16715ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligstatic void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
16725ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
16735ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_wka_port *wka_port = req->data;
16745ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16755ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
16765ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
16775ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req);
16785ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16795ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16805ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	wka_port->status = ZFCP_WKA_PORT_OFFLINE;
16815ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	wake_up(&wka_port->completion_wq);
16825ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
16835ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16845ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig/**
16855ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * zfcp_fsf_close_wka_port - create and send close wka port request
16865ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * @erp_action: pointer to struct zfcp_erp_action
16875ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * Returns: 0 on success, error otherwise
16885ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig */
16895ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligint zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
16905ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
16915ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct qdio_buffer_element *sbale;
1692564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
16935ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_fsf_req *req;
16945ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	int retval = -EIO;
16955ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1696564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1697564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
16985ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16995ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1700564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1701564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
170209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
17035ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (unlikely(IS_ERR(req))) {
17045ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		retval = PTR_ERR(req);
17055ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
17065ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
17075ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
170809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1709564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
17105ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
17115ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
17125ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
17135ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->handler = zfcp_fsf_close_wka_port_handler;
17145ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->data = wka_port;
17155ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->qtcb->header.port_handle = wka_port->handle;
17165ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
17175ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
17185ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	retval = zfcp_fsf_req_send(req);
17195ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (retval)
17205ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		zfcp_fsf_req_free(req);
17215ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
1722564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
17235ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	return retval;
17245ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
17255ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1726c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1728c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
1729c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zfcp_unit *unit;
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1732c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1733a5b11dda12ed7e3a79180b10ad6209a40a02989fChristof Schmitt		return;
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
17375ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req);
1738c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1741c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_access_denied_port(req, port);
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
17445c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		/* can't use generic zfcp_erp_modify_port_status because
17455c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
17465c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
17475c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		list_for_each_entry(unit, &port->unit_list_head, list)
17485c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
17495c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt					  &unit->status);
1750dfb3cf00e402686f671db697adbd8b9f4c219268Swen Schillig		zfcp_erp_port_boxed(port, "fscpph2", req);
1751dfb3cf00e402686f671db697adbd8b9f4c219268Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
1752dfb3cf00e402686f671db697adbd8b9f4c219268Swen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
1753dfb3cf00e402686f671db697adbd8b9f4c219268Swen Schillig
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1758c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
1760c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* can't use generic zfcp_erp_modify_port_status because
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		list_for_each_entry(unit, &port->unit_list_head, list)
1770c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1771c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					  &unit->status);
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1776c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1777c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_physical_port - close physical port
1778c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1779c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1781c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
178344cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1784564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1785c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1786c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1787c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1788564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1789564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1792564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
1793564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
179409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1795025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1796c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1797c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1798c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
180009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1801564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1802c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
1803c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1805c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->port;
1806c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1807c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1808c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_close_physical_port_handler;
1809c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
1810c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1811287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1812c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1814c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1817c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1818564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1822c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1824c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
1825c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit = req->data;
1826c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
1827c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
1828c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_queue_designator *queue_designator =
1829c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&header->fsf_status_qual.fsf_queue_designator;
1830aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	int exclusive, readwrite;
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1832c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
183344cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1836b64ddf96456cde17be22bf74cafed381a29d58baHeiko Carstens			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  ZFCP_STATUS_UNIT_SHARED |
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  ZFCP_STATUS_UNIT_READONLY,
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  &unit->status);
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
18445ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req);
1845c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_ALREADY_OPEN:
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1849c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_access_denied_unit(req, unit);
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
1851553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
18545ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
1855c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
1856c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_SHARING_VIOLATION:
1859c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (header->fsf_status_qual.word[0])
1860553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt			dev_warn(&adapter->ccw_device->dev,
1861ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				 "LUN 0x%Lx on port 0x%Lx is already in "
1862ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				 "use by CSS%d, MIF Image ID %x\n",
18637ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig				 (unsigned long long)unit->fcp_lun,
18647ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig				 (unsigned long long)unit->port->wwpn,
1865ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				 queue_designator->cssid,
1866ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				 queue_designator->hla);
1867c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		else
1868553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt			zfcp_act_eval_err(adapter,
1869553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt					  header->fsf_status_qual.word[2]);
18705ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_unit_access_denied(unit, "fsouh_3", req);
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
1873c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
1876c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&adapter->ccw_device->dev,
1877ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "No handle is available for LUN "
1878ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "0x%016Lx on port 0x%016Lx\n",
18797ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 (unsigned long long)unit->fcp_lun,
18807ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 (unsigned long long)unit->port->wwpn);
18815ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_unit_failed(unit, "fsouh_4", req);
1882c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
1883c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_INVALID_COMMAND_OPTION:
1884c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
18896f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig			zfcp_fc_test_link(unit->port);
1890c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
1892c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unit->handle = header->lun_handle;
18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
1900aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
1901aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
1902aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		    (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
19036fcf41d1d8796f41b893754324704e23971c2ea1Christof Schmitt		    !zfcp_ccw_priv_sch(adapter)) {
1904aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			exclusive = (bottom->lun_access_info &
1905aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin					FSF_UNIT_ACCESS_EXCLUSIVE);
1906aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			readwrite = (bottom->lun_access_info &
1907aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin					FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
1908aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!exclusive)
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		                atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&unit->status);
19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!readwrite) {
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                		atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						&unit->status);
1916c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				dev_info(&adapter->ccw_device->dev,
1917ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					 "SCSI device at LUN 0x%016Lx on port "
1918ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					 "0x%016Lx opened read-only\n",
19197ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					 (unsigned long long)unit->fcp_lun,
19207ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					 (unsigned long long)unit->port->wwpn);
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		}
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		if (exclusive && !readwrite) {
1924c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				dev_err(&adapter->ccw_device->dev,
1925ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"Exclusive read-only access not "
1926ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"supported (unit 0x%016Lx, "
1927ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"port 0x%016Lx)\n",
19287ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					(unsigned long long)unit->fcp_lun,
19297ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					(unsigned long long)unit->port->wwpn);
19305ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				zfcp_erp_unit_failed(unit, "fsouh_5", req);
1931c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
19325ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req);
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		} else if (!exclusive && readwrite) {
1934c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				dev_err(&adapter->ccw_device->dev,
1935ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"Shared read-write access not "
1936ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt					"supported (unit 0x%016Lx, port "
193727c3f0a6e4521ba0ff6e76da54969f0bf430f53aChristof Schmitt					"0x%016Lx)\n",
19387ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					(unsigned long long)unit->fcp_lun,
19397ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig					(unsigned long long)unit->port->wwpn);
19405ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				zfcp_erp_unit_failed(unit, "fsouh_7", req);
1941c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
19425ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig				zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req);
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		}
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1949c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1950c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_open_unit - open unit
1951c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1952c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1954c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
195644cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
1957c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = erp_action->adapter;
1958564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
1959c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1960c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1961c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1962564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
1963564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1966564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1967a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig				  adapter->pool.erp_req);
196809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1969025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1970c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1971c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1972c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
1973c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
197409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1975564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1979c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1980c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
1981c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_open_unit_handler;
1982c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->unit;
1983c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1984c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
1985c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1986c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE))
1987c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING;
1988c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1989287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1990c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1992c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		erp_action->fsf_req = NULL;
19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1995c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
1996564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2000c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2002c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit = req->data;
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2004c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
200544cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2007c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
20095ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req);
2010c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_HANDLE_NOT_VALID:
20135ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req);
2014c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
20175ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
2018c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
2019c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
2022c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		switch (req->qtcb->header.fsf_status_qual.word[0]) {
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
20246f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig			zfcp_fc_test_link(unit->port);
2025c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
2027c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2038c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_unit - close zfcp unit
2039c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_unit
2040c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2042c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
204444cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
2045564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
2046c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
2047c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2049564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
2050564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
205209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2053564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
2054564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
205509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2056025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
2057c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
2058c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2059c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
206109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
2062564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
2063c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2066c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
2067c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.lun_handle = erp_action->unit->handle;
2068c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_close_unit_handler;
2069c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->unit;
2070c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
2071c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	erp_action->fsf_req = req;
2072fdf234527a070f6fc89f3ec5ee4ae1b263e59939Christof Schmitt
2073287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
2074c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
2075c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (retval) {
2076c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
2077c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		erp_action->fsf_req = NULL;
2078c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2079c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2080564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
2081c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2084c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmittstatic void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
2085c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt{
2086c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	lat_rec->sum += lat;
2087c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	lat_rec->min = min(lat_rec->min, lat);
2088c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	lat_rec->max = max(lat_rec->max, lat);
2089c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt}
2090c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
2091c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_req_latency(struct zfcp_fsf_req *req)
2092c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt{
2093c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	struct fsf_qual_latency_info *lat_inf;
2094c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	struct latency_cont *lat;
2095c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit = req->unit;
2096c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
2097c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	lat_inf = &req->qtcb->prefix.prot_status_qual.latency_info;
2098c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
2099c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->bottom.io.data_direction) {
2100c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	case FSF_DATADIR_READ:
2101c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt		lat = &unit->latencies.read;
2102c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt		break;
2103c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	case FSF_DATADIR_WRITE:
2104c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt		lat = &unit->latencies.write;
2105c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt		break;
2106c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	case FSF_DATADIR_CMND:
2107c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt		lat = &unit->latencies.cmd;
2108c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt		break;
2109c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	default:
2110c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt		return;
2111c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	}
2112c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
211349f0f01c9966639f8fd7ce784a412e22057d9f2aChristof Schmitt	spin_lock(&unit->latencies.lock);
2114c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	zfcp_fsf_update_lat(&lat->channel, lat_inf->channel_lat);
2115c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	zfcp_fsf_update_lat(&lat->fabric, lat_inf->fabric_lat);
2116c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	lat->counter++;
211749f0f01c9966639f8fd7ce784a412e22057d9f2aChristof Schmitt	spin_unlock(&unit->latencies.lock);
21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21200997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl#ifdef CONFIG_BLK_DEV_IO_TRACE
21210997f1c5fec0b540784611036d458a84a1f7029aStefan Rasplstatic void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
21220997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl{
21230997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	struct fsf_qual_latency_info *lat_inf;
21240997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	struct scsi_cmnd *scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
21250997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	struct request *req = scsi_cmnd->request;
21260997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	struct zfcp_blk_drv_data trace;
21270997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	int ticks = fsf_req->adapter->timer_ticks;
21280997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
21290997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	trace.flags = 0;
21300997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	trace.magic = ZFCP_BLK_DRV_DATA_MAGIC;
21310997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	if (fsf_req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
21320997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl		trace.flags |= ZFCP_BLK_LAT_VALID;
21330997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl		lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
21340997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl		trace.channel_lat = lat_inf->channel_lat * ticks;
21350997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl		trace.fabric_lat = lat_inf->fabric_lat * ticks;
21360997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	}
21370997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
21380997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl		trace.flags |= ZFCP_BLK_REQ_ERROR;
213942428f747a8a0db9c6de03e105932316defad65dSwen Schillig	trace.inb_usage = fsf_req->queue_req.qdio_inb_usage;
214042428f747a8a0db9c6de03e105932316defad65dSwen Schillig	trace.outb_usage = fsf_req->queue_req.qdio_outb_usage;
21410997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
21420997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	blk_add_driver_data(req->q, req, &trace, sizeof(trace));
21430997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl}
21440997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl#else
21450997f1c5fec0b540784611036d458a84a1f7029aStefan Rasplstatic inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
21460997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl{
21470997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl}
21480997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl#endif
21490997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
2150c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21520ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig	struct scsi_cmnd *scpnt;
21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
2154c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	    &(req->qtcb->bottom.io.fcp_rsp);
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 sns_len;
2156f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2159c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	read_lock_irqsave(&req->adapter->abort_lock, flags);
2160c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
21610ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig	scpnt = req->data;
21620ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig	if (unlikely(!scpnt)) {
21630ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig		read_unlock_irqrestore(&req->adapter->abort_lock, flags);
21640ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig		return;
21650ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig	}
21660ac55aa90f2c3bd08e57e52a513b82b18ce0a5bcSwen Schillig
2167c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) {
2168feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann		set_host_byte(scpnt, DID_SOFT_ERROR);
21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2172c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2173feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann		set_host_byte(scpnt, DID_ERROR);
21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2177feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann	set_msg_byte(scpnt, COMMAND_COMPLETE);
21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scpnt->result |= fcp_rsp_iu->scsi_status;
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
2182c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_latency(req);
2183c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
21840997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	zfcp_fsf_trace_latency(req);
21850997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
2187c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (fcp_rsp_info[3] == RSP_CODE_GOOD)
2188feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann			set_host_byte(scpnt, DID_OK);
2189c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		else {
2190feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann			set_host_byte(scpnt, DID_ERROR);
21916f71d9bc025b02a8cbc2be83b0226a7043a507a5<jejb@titanic.il.steeleye.com>			goto skip_fsfstatus;
21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) {
2196c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		sns_len = FSF_FCP_RSP_SIZE - sizeof(struct fcp_rsp_iu) +
2197c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			  fcp_rsp_iu->fcp_rsp_len;
21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE);
21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len);
22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22019d058ecfd444d247b7448e0ef44647514d91a4f2FUJITA Tomonori		memcpy(scpnt->sense_buffer,
22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len);
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) {
22067936a892e72498a05b9a7fb1fec6506d65c8e435FUJITA Tomonori		scsi_set_resid(scpnt, fcp_rsp_iu->fcp_resid);
22077936a892e72498a05b9a7fb1fec6506d65c8e435FUJITA Tomonori		if (scsi_bufflen(scpnt) - scsi_get_resid(scpnt) <
22087936a892e72498a05b9a7fb1fec6506d65c8e435FUJITA Tomonori		    scpnt->underflow)
2209feac6a07c4a3578bffd6769bb4927e8a7e1f3ffeMartin Petermann			set_host_byte(scpnt, DID_ERROR);
22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2211c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligskip_fsfstatus:
22128a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin	if (scpnt->result != 0)
22135771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req);
22148a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin	else if (scpnt->retries > 0)
22155771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_scsi_result("retr", 4, req->adapter->dbf, scpnt, req);
22168a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin	else
22175771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig		zfcp_dbf_scsi_result("norm", 6, req->adapter->dbf, scpnt, req);
22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scpnt->host_scribble = NULL;
22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(scpnt->scsi_done) (scpnt);
22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We must hold this lock until scsi_done has been called.
22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Otherwise we may call scsi_done after abort regarding this
22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * command has completed.
22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Note: scsi_done must not block!
22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2227c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2230c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
2233c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	    &(req->qtcb->bottom.io.fcp_rsp);
2234f76af7d7e36373179be7a9e09f6b0aae330549b7Martin Petermann	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2236c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if ((fcp_rsp_info[3] != RSP_CODE_GOOD) ||
2237c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
2238c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
2239c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
2240c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2241c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2242c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
2243c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
2244c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_unit *unit;
2245c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
2246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2247c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
2248c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		unit = req->data;
2249c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
2250c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		unit = req->unit;
2251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2252c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2255c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (header->fsf_status) {
2256c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_HANDLE_MISMATCH:
2257c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_HANDLE_NOT_VALID:
22585ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
2259c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2260c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2261c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_FCPLUN_NOT_VALID:
2262c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_LUN_HANDLE_NOT_VALID:
22635ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
2264c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2266c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
2267c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2269c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ACCESS_DENIED:
2270c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_access_denied_unit(req, unit);
2271c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2272c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_DIRECTION_INDICATOR_NOT_VALID:
2273c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
2274ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"Incorrect direction %d, unit 0x%016Lx on port "
2275ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%016Lx closed\n",
2276c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->bottom.io.data_direction,
22777ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(unsigned long long)unit->fcp_lun,
22787ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(unsigned long long)unit->port->wwpn);
22795ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
22805ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					  req);
2281c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2282c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_CMND_LENGTH_NOT_VALID:
2284c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
2285ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"Incorrect CDB length %d, unit 0x%016Lx on "
2286ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"port 0x%016Lx closed\n",
2287c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->bottom.io.fcp_cmnd_length,
22887ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(unsigned long long)unit->fcp_lun,
22897ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(unsigned long long)unit->port->wwpn);
22905ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
22915ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					  req);
2292c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2293c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2294c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_BOXED:
22955ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_port_boxed(unit->port, "fssfch5", req);
2296c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
2297c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
2298c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2299c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_LUN_BOXED:
23005ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig		zfcp_erp_unit_boxed(unit, "fssfch6", req);
2301c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
2302c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			       ZFCP_STATUS_FSFREQ_RETRY;
2303c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2304c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
2305c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (header->fsf_status_qual.word[0] ==
2306c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
23076f53a2d2ecaefa3ffff8864f51a3ae38737e1152Swen Schillig			zfcp_fc_test_link(unit->port);
2308c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
23091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2311c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligskip_fsfstatus:
2312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
2313c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_send_fcp_ctm_handler(req);
2314c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else {
2315c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_send_fcp_command_task_handler(req);
2316c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->unit = NULL;
2317c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_unit_put(unit);
2318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23217ba58c9cc16d296290fe645acb11db2b01276544Swen Schilligstatic void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
23227ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig{
23237ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig	u32 *fcp_dl_ptr;
23247ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig
23257ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig	/*
23267ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig	 * fcp_dl_addr = start address of fcp_cmnd structure +
23277ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig	 * size of fixed part + size of dynamically sized add_dcp_cdb field
23287ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig	 * SEE FCP-2 documentation
23297ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig	 */
23307ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig	fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] +
23317ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			(fcp_cmd->add_fcp_cdb_length << 2));
23327ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig	*fcp_dl_ptr = fcp_dl;
23337ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig}
23347ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig
2335c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
2336c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
2337c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @unit: unit where command is sent to
2338c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @scsi_cmnd: scsi command to be sent
23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
234063caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmittint zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
234163caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt				   struct scsi_cmnd *scsi_cmnd)
23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
2344c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fcp_cmnd_iu *fcp_cmnd_iu;
2345bc90c8632f63cd94246e3fb6f1b6d7ecba48f1a0Christof Schmitt	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
2346c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int real_bytes, retval = -EIO;
234763caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmitt	struct zfcp_adapter *adapter = unit->port->adapter;
2348564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2350c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!(atomic_read(&unit->status) &
2351c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
2352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EBUSY;
23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2354564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock(&qdio->req_q_lock);
2355564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (atomic_read(&qdio->req_q.count) <= 0) {
2356564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		atomic_inc(&qdio->req_q_full);
2357c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
23588fdf30d5429605a4c30cc515c73e5eab140035deChristof Schmitt	}
235909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2360564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2361a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig				  adapter->pool.scsi_req);
236209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2363025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
2364c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
2365c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2366c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2367c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
236809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
2369c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_unit_get(unit);
2370c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->unit = unit;
2371c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = scsi_cmnd;
2372c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_fcp_command_handler;
2373c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.lun_handle = unit->handle;
2374c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = unit->port->handle;
2375c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
2376c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2377c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	scsi_cmnd->host_scribble = (unsigned char *) req->req_id;
2378c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2379c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fcp_cmnd_iu = (struct fcp_cmnd_iu *) &(req->qtcb->bottom.io.fcp_cmnd);
2380c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
2381c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/*
2382c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 * set depending on data direction:
2383c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 *      data direction bits in SBALE (SB Type)
2384c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 *      data direction bits in QTCB
2385c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 *      data direction bits in FCP_CMND IU
2386c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	 */
2387c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (scsi_cmnd->sc_data_direction) {
2388c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case DMA_NONE:
2389c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case DMA_FROM_DEVICE:
2392c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
2393c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fcp_cmnd_iu->rddata = 1;
2394c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2395c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case DMA_TO_DEVICE:
2396c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
2397c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		sbtype = SBAL_FLAGS0_TYPE_WRITE;
2398c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fcp_cmnd_iu->wddata = 1;
23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2400c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case DMA_BIDIRECTIONAL:
2401c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_scsi_cmnd;
24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2404c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely((scsi_cmnd->device->simple_tags) ||
2405c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		   ((atomic_read(&unit->status) & ZFCP_STATUS_UNIT_READONLY) &&
2406c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		    (atomic_read(&unit->status) & ZFCP_STATUS_UNIT_SHARED))))
2407c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fcp_cmnd_iu->task_attribute = SIMPLE_Q;
2408c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
2409c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fcp_cmnd_iu->task_attribute = UNTAGGED;
24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH))
2412c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fcp_cmnd_iu->add_fcp_cdb_length =
2413c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			(scsi_cmnd->cmd_len - FCP_CDB_LENGTH) >> 2;
24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2415c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
241645633fdc9615f9fd2a0ae18e301562298b15abf3Christof Schmitt
2417c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
24187ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig		fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2420564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype,
2421c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					     scsi_sglist(scsi_cmnd),
2422c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					     FSF_MAX_SBALS_PER_REQ);
2423c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(real_bytes < 0)) {
242442428f747a8a0db9c6de03e105932316defad65dSwen Schillig		if (req->queue_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) {
2425c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			dev_err(&adapter->ccw_device->dev,
2426ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"Oversize data package, unit 0x%016Lx "
2427ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"on port 0x%016Lx closed\n",
24287ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig				(unsigned long long)unit->fcp_lun,
24297ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig				(unsigned long long)unit->port->wwpn);
24305ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig			zfcp_erp_unit_shutdown(unit, 0, "fssfct1", req);
2431c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			retval = -EINVAL;
2432c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		}
2433c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_scsi_cmnd;
24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2436c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes);
24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2438c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
2439c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(retval))
2440c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_scsi_cmnd;
24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2442c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2444c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_scsi_cmnd:
2445c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_unit_put(unit);
2446c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
2447c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	scsi_cmnd->host_scribble = NULL;
2448c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2449564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock(&qdio->req_q_lock);
2450c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2454c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_fcp_ctm - send SCSI task management command
2455c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @unit: pointer to struct zfcp_unit
2456c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @tm_flags: unsigned byte for task management flags
2457c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: on success pointer to struct fsf_req, NULL otherwise
24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
245963caf367e1c92e0667a344d9b687c04e6ef054b5Christof Schmittstruct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
246144cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
2462c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
2463c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fcp_cmnd_iu *fcp_cmnd_iu;
2464564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2466c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!(atomic_read(&unit->status) &
2467c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
2468c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2470564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
2471564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
2472c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
247309a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2474564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2475564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.scsi_req);
247609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2477633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	if (IS_ERR(req)) {
2478633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig		req = NULL;
2479c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2480633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	}
24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2482c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
2483c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = unit;
2484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_fcp_command_handler;
2485c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.lun_handle = unit->handle;
2486c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = unit->port->handle;
2487c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
2488c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
2489c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.fcp_cmnd_length = 	sizeof(struct fcp_cmnd_iu) +
24907ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig						sizeof(u32);
2491c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2492564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
2493c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
2494c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fcp_cmnd_iu = (struct fcp_cmnd_iu *) &req->qtcb->bottom.io.fcp_cmnd;
2497c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
2498c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fcp_cmnd_iu->task_management_flags = tm_flags;
24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2500c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
2501c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!zfcp_fsf_req_send(req))
2502c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
2505c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req = NULL;
2506c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2507564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
2508c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
2509c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
2512c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2515c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
2516c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_control_file - control file upload/download
2517c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @adapter: pointer to struct zfcp_adapter
2518c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_cfdc: pointer to struct zfcp_fsf_cfdc
2519c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: on success pointer to struct zfcp_fsf_req, NULL otherwise
25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2521c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstruct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
2522c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					   struct zfcp_fsf_cfdc *fsf_cfdc)
25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
252444cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig	struct qdio_buffer_element *sbale;
2525564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
2526c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
2527c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_support *bottom;
2528c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int direction, retval = -EIO, bytes;
2529c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2530c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
2531c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return ERR_PTR(-EOPNOTSUPP);
2532c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2533c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (fsf_cfdc->command) {
2534c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
2535c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		direction = SBAL_FLAGS0_TYPE_WRITE;
2536c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2537c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_QTCB_UPLOAD_CONTROL_FILE:
2538c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		direction = SBAL_FLAGS0_TYPE_READ;
2539c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2540c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
2541c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return ERR_PTR(-EINVAL);
2542c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2544564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_lock_bh(&qdio->req_q_lock);
2545564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (zfcp_fsf_req_sbal_get(qdio))
2546c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2548564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, NULL);
2549025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
2550c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = -EPERM;
2551c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2552c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2554c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_control_file_handler;
25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2556564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
2557c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	sbale[0].flags |= direction;
25588a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
2559c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom = &req->qtcb->bottom.support;
2560c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
2561c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom->option = fsf_cfdc->option;
25628a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
2563564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req,
2564564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig					direction, fsf_cfdc->sg,
2565564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig					FSF_MAX_SBALS_PER_REQ);
2566c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (bytes != ZFCP_CFDC_MAX_SIZE) {
2567c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
2568c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2569c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
2572c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
2573c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2574564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	spin_unlock_bh(&qdio->req_q_lock);
25758a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
2576c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!retval) {
2577058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
2578c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return req;
25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2580c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ERR_PTR(retval);
25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2582bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2583bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig/**
2584bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO
2585bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @adapter: pointer to struct zfcp_adapter
2586bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @sbal_idx: response queue index of SBAL to be processed
2587bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */
2588564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligvoid zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2589bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig{
2590564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
2591564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx];
2592bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct qdio_buffer_element *sbale;
2593bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct zfcp_fsf_req *fsf_req;
2594bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	unsigned long flags, req_id;
2595bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	int idx;
2596bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2597bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
2598bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2599bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		sbale = &sbal->element[idx];
2600bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		req_id = (unsigned long) sbale->addr;
2601bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		spin_lock_irqsave(&adapter->req_list_lock, flags);
2602bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		fsf_req = zfcp_reqlist_find(adapter, req_id);
2603bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2604bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		if (!fsf_req)
2605bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			/*
2606bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 * Unknown request means that we have potentially memory
2607bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 * corruption and must stop the machine immediately.
2608bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 */
2609bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			panic("error: unknown req_id (%lx) on adapter %s.\n",
2610bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			      req_id, dev_name(&adapter->ccw_device->dev));
2611bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2612bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		list_del(&fsf_req->list);
2613bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		spin_unlock_irqrestore(&adapter->req_list_lock, flags);
2614bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
261542428f747a8a0db9c6de03e105932316defad65dSwen Schillig		fsf_req->queue_req.sbal_response = sbal_idx;
261642428f747a8a0db9c6de03e105932316defad65dSwen Schillig		fsf_req->queue_req.qdio_inb_usage =
2617564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig			atomic_read(&qdio->resp_q.count);
2618bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		zfcp_fsf_req_complete(fsf_req);
2619bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2620bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
2621bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			break;
2622bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	}
2623bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig}
2624