11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * zfcp device driver
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt * Implementation of FSF commands.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt * Copyright IBM Corporation 2002, 2010
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define KMSG_COMPONENT "zfcp"
10ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11ecf39d42129767c0b4b4a6cf4997c1219c860934Christof Schmitt
120997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl#include <linux/blktrace_api.h>
135a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
149d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt#include <scsi/fc/fc_els.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "zfcp_ext.h"
164318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt#include "zfcp_fc.h"
17dcd20e2316cdc333dfdee09649dbe3642eb30e75Christof Schmitt#include "zfcp_dbf.h"
1834c2b712992540ca436e97432ffc57c84c8f8c18Christof Schmitt#include "zfcp_qdio.h"
19b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt#include "zfcp_reqlist.h"
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmittstruct kmem_cache *zfcp_fsf_qtcb_cache;
22259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt
23287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_request_timeout_handler(unsigned long data)
24287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
25287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
26339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt	zfcp_qdio_siosl(adapter);
275ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
28ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				"fsrth_1");
29287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
30287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
31287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req,
32287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt				 unsigned long timeout)
33287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
34287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
35287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.data = (unsigned long) fsf_req->adapter;
36287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.expires = jiffies + timeout;
37287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	add_timer(&fsf_req->timer);
38287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
39287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
40287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmittstatic void zfcp_fsf_start_erp_timer(struct zfcp_fsf_req *fsf_req)
41287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt{
42287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	BUG_ON(!fsf_req->erp_action);
43287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.function = zfcp_erp_timeout_handler;
44287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.data = (unsigned long) fsf_req->erp_action;
45287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	fsf_req->timer.expires = jiffies + 30 * HZ;
46287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	add_timer(&fsf_req->timer);
47287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt}
48287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* association between FSF command and FSF QTCB type */
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 fsf_qtcb_type[] = {
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_FCP_CMND] =             FSF_IO_COMMAND,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_ABORT_FCP_CMND] =       FSF_SUPPORT_COMMAND,
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_OPEN_PORT_WITH_DID] =   FSF_SUPPORT_COMMAND,
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_OPEN_LUN] =             FSF_SUPPORT_COMMAND,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_LUN] =            FSF_SUPPORT_COMMAND,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_PORT] =           FSF_SUPPORT_COMMAND,
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_CLOSE_PHYSICAL_PORT] =  FSF_SUPPORT_COMMAND,
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_SEND_ELS] =             FSF_SUPPORT_COMMAND,
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_SEND_GENERIC] =         FSF_SUPPORT_COMMAND,
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND,
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_EXCHANGE_PORT_DATA] =   FSF_PORT_COMMAND,
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND,
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	[FSF_QTCB_UPLOAD_CONTROL_FILE] =  FSF_SUPPORT_COMMAND
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
66553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmittstatic void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
67553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
68ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
69ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		"operational because of an unsupported FC class\n");
70ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig	zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1");
71553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
72553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt}
73553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
74c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
75c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_req_free - free memory used by fsf request
76c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_req: pointer to struct zfcp_fsf_req
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
78c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligvoid zfcp_fsf_req_free(struct zfcp_fsf_req *req)
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
80c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(req->pool)) {
81a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (likely(req->qtcb))
82a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			mempool_free(req->qtcb, req->adapter->pool.qtcb_pool);
83c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		mempool_free(req, req->pool);
84dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens		return;
85dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens	}
86dd52e0eaf891cd85bf2ca057c15ed6bfd76db4e6Heiko Carstens
87a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(req->qtcb))
88259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt		kmem_cache_free(zfcp_fsf_qtcb_cache, req->qtcb);
89a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	kfree(req);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
92c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
94ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	unsigned long flags;
95c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
96c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
97c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port;
98800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt	int d_id = ntoh24(sr_buf->d_id);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
100ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_lock_irqsave(&adapter->port_list_lock, flags);
101ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	list_for_each_entry(port, &adapter->port_list, list)
102c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (port->d_id == d_id) {
103ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig			zfcp_erp_port_reopen(port, 0, "fssrpc1");
104ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig			break;
105c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		}
106ecf0c7721b104c0ce9c8ca534c911f6310cf92a8Swen Schillig	read_unlock_irqrestore(&adapter->port_list_lock, flags);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
109edaed859e63aac174fcc3fed81886b91bb124661Swen Schilligstatic void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req,
110c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					 struct fsf_link_down_info *link_down)
111aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin{
112c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
113698ec01635819c5ae60090bb4efcbeffc41642fbMartin Peschke
114c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
115ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin		return;
116ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
117ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
11870932935b61ee3dcc5a419ec4c367feb2ff808e4Christof Schmitt
119a2fa0aede07c9488239dcac1eae58233181c355aChristof Schmitt	zfcp_scsi_schedule_rports_block(adapter);
120ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
121c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!link_down)
1222f8f3ed5fc566700cf45d422f4cf1624bd123d93Andreas Herrmann		goto out;
123ee69ab7af3cd68423e389272e1276718d4cd8ebcMaxim Shchetynin
124aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	switch (link_down->error_code) {
125aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_LIGHT:
126c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
127ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "There is no light signal from the local "
128ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "fibre channel cable\n");
129aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
130aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_WRAP_PLUG:
131c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
132ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "There is a wrap plug instead of a fibre "
133ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "channel cable\n");
134aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
135aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FCP:
136c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
137ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The adjacent fibre channel node does not "
138ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "support FCP\n");
139aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
140aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_FIRMWARE_UPDATE:
141c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
142ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP device is suspended because of a "
143ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "firmware update\n");
144553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt		break;
145aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_INVALID_WWPN:
146c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
147ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP device detected a WWPN that is "
148ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "duplicate or not valid\n");
149aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
150aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
151c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
152ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The fibre channel fabric does not support NPIV\n");
153aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
154aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FCP_RESOURCES:
155c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
156ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP adapter cannot support more NPIV ports\n");
157aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
158aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
159c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
160ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The adjacent switch cannot support "
161ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "more NPIV ports\n");
162aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
163aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
164c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
165ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The FCP adapter could not log in to the "
166ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "fibre channel fabric\n");
167aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
168aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
169c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
170ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The WWPN assignment file on the FCP adapter "
171ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been damaged\n");
172aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
173aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
174c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
175ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The mode table on the FCP adapter "
176ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been damaged\n");
177aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
178aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
179c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
180ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "All NPIV ports on the FCP adapter have "
181ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "been assigned\n");
182aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
183aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	default:
184c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
185ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The link between the FCP adapter and "
186ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "the FC fabric is down\n");
187aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	}
188c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
189edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
190aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin}
191aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
192c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
194c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
195c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_link_down_info *ldi =
196c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		(struct fsf_link_down_info *) &sr_buf->payload;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
198c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (sr_buf->status_subtype) {
199c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
200edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_fsf_link_down_info_eval(req, ldi);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
202c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_FDISC_FAILED:
203edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_fsf_link_down_info_eval(req, ldi);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
205c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
206edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_fsf_link_down_info_eval(req, NULL);
207c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	};
208c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
210c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
211c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
212c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
213c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf = req->data;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
215c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
216a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig		zfcp_dbf_hba_fsf_uss("fssrh_1", req);
217c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt		mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
218c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
219c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
220c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
222a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig	zfcp_dbf_hba_fsf_uss("fssrh_2", req);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
224c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (sr_buf->status_type) {
225c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_PORT_CLOSED:
226c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_port_closed(req);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
228c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_INCOMING_ELS:
229c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fc_incoming_els(req);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
231c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
233c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
234ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt		dev_warn(&adapter->ccw_device->dev,
235ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The error threshold for checksum statistics "
236ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "has been exceeded\n");
237a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig		zfcp_dbf_hba_bit_err("fssrh_3", req);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
239c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_LINK_DOWN:
240c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_link_down(req);
2412d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz		zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKDOWN, 0);
242c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
243c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_LINK_UP:
244c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_info(&adapter->ccw_device->dev,
245ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "The local link has been restored\n");
246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* All ports should be marked as ready to run again */
247edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_adapter_status(adapter,
248edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig					    ZFCP_STATUS_COMMON_RUNNING);
249c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_erp_adapter_reopen(adapter,
250c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_COMMON_ERP_FAILED,
252ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig					"fssrh_2");
2532d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz		zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0);
2542d1e547f7523514d1da449bcf08645fe13579378Sven Schuetz
255c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
256c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_NOTIFICATION_LOST:
257c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
258a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt			zfcp_cfdc_adapter_access_changed(adapter);
259c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
2609eae07ef6bb5988163d8bb82cd952905db47b721Swen Schillig			queue_work(adapter->work_queue, &adapter->scan_work);
261c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
262c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_CFDC_UPDATED:
263a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		zfcp_cfdc_adapter_access_changed(adapter);
264c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
265c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
266c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->adapter_features = sr_buf->payload.word[0];
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
270c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
271c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
273c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	atomic_inc(&adapter->stat_miss);
2744544683a4b1d4e65ccca8c736bac56a195a5206bSwen Schillig	queue_work(adapter->work_queue, &adapter->stat_work);
275c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
277c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
279c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status_qual.word[0]) {
280c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_FCP_RSP_AVAILABLE:
281c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
282c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_NO_RETRY_POSSIBLE:
283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
284c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
285c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_COMMAND_ABORTED:
286c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
287c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SQ_NO_RECOM:
288c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
289ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter reported a problem "
290ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"that cannot be recovered\n");
291339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt		zfcp_qdio_siosl(req->adapter);
292ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1");
293c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
294c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/* all non-return stats set FSFREQ_ERROR*/
296c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
299c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
301c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
302c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
305c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_UNKNOWN_COMMAND:
306c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
307ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter does not recognize the command 0x%x\n",
308c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->header.fsf_command);
309ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1");
310c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
311c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
313c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_fsfstatus_qual_eval(req);
314c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
315c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
316c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
319c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
320c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
321c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
322c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	union fsf_prot_status_qual *psq = &qtcb->prefix.prot_status_qual;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3245771710bd5edfafcb8656f49b93690a6fae5a4d2Swen Schillig	zfcp_dbf_hba_fsf_response(req);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
326c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
3274c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
328c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
329c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->prefix.prot_status) {
332c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_GOOD:
333c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_FSF_STATUS_PRESENTED:
334c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
335c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_QTCB_VERSION_ERROR:
336c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
337ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"QTCB version 0x%x not supported by FCP adapter "
338ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION,
339ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			psq->word[0], psq->word[1]);
340ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1");
341c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
342c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_ERROR_STATE:
343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_SEQ_NUMB_ERROR:
344ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2");
3454c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
346c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
347c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_UNSUPP_QTCB_TYPE:
348c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
349ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The QTCB type is not supported by the FCP adapter\n");
350ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3");
351c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_HOST_CONNECTION_INITIALIZING:
353c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
354c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&adapter->status);
355c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
356c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_DUPLICATE_REQUEST_ID:
357c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
358ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%Lx is an ambiguous request identifier\n",
359c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			(unsigned long long)qtcb->bottom.support.req_handle);
360ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4");
361c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
362c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_LINK_DOWN:
363edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_fsf_link_down_info_eval(req, &psq->link_down_info);
364452b505c5ada345103bdfdb39dc550df3ffe9eeaChristof Schmitt		/* go through reopen to flush pending requests */
365ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6");
366c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
367c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PROT_REEST_QUEUE:
368c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* All ports should be marked as ready to run again */
369edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_adapter_status(adapter,
370edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig					    ZFCP_STATUS_COMMON_RUNNING);
371c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_erp_adapter_reopen(adapter,
372c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
3735ffd51a5e495a2a002efd523aef0001912b080bdSwen Schillig					ZFCP_STATUS_COMMON_ERP_FAILED,
374ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig					"fspse_8");
375c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
376c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
377c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
378ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%x is not a valid transfer protocol status\n",
379c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			qtcb->prefix.prot_status);
380339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt		zfcp_qdio_siosl(adapter);
381ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9");
382c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
383c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
386c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
387c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_req_complete - process completion of a FSF request
388c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_req: The FSF request that has been completed.
389c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig *
390c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * When a request has been completed either from the FCP adapter,
391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * or it has been dismissed due to a queue shutdown, this function
392c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * is called to process the completion status and trigger further
393c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * events related to the FSF request.
394c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig */
395bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schilligstatic void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
397c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
398c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_status_read_handler(req);
399c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
400c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
402c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	del_timer(&req->timer);
403c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_protstatus_eval(req);
404c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_fsfstatus_eval(req);
405c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler(req);
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
407c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->erp_action)
408287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt		zfcp_erp_notify(req->erp_action, 0);
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
410c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
411c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
412c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
413058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		complete(&req->completion);
414c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
416bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig/**
417bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
418bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @adapter: pointer to struct zfcp_adapter
419bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig *
420bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Never ever call this without shutting down the adapter first.
421bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Otherwise the adapter would continue using and corrupting s390 storage.
422bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * Included BUG_ON() call to ensure this is done.
423bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * ERP is supposed to be the only user of this function.
424bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */
425bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schilligvoid zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
426bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig{
427bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct zfcp_fsf_req *req, *tmp;
428bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	LIST_HEAD(remove_queue);
429bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
430bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
431b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt	zfcp_reqlist_move(adapter->req_list, &remove_queue);
432bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
433bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	list_for_each_entry_safe(req, tmp, &remove_queue, list) {
434bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		list_del(&req->list);
435bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
436bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		zfcp_fsf_req_complete(req);
437bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	}
438bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig}
439bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
440c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
441c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
4429d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
443c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
444c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
4459d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt	struct fc_els_flogi *nsp, *plogi;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4479d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt	/* adjust pointers for missing command code */
4489d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt	nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param
4499d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt					- sizeof(u32));
4509d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt	plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload
4519d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt					- sizeof(u32));
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
453c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->data)
454c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(req->data, bottom, sizeof(*bottom));
455c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
4569d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt	fc_host_port_name(shost) = nsp->fl_wwpn;
4579d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt	fc_host_node_name(shost) = nsp->fl_wwnn;
458800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt	fc_host_port_id(shost) = ntoh24(bottom->s_id);
459c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_speed(shost) = bottom->fc_link_speed;
460c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
461c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
462c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->hydra_version = bottom->adapter_type;
463faf4cd854203b26527d81e7e13d66e78774dad44Christof Schmitt	adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK;
4648d88cf3f3b9af4713642caeb221b6d6a42019001Christof Schmitt	adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
4658d88cf3f3b9af4713642caeb221b6d6a42019001Christof Schmitt					 (u16)FSF_STATUS_READS_RECOM);
466c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
467c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (fc_host_permanent_port_name(shost) == -1)
468c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
469c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
470c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (bottom->fc_topology) {
471c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_P2P:
472800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt		adapter->peer_d_id = ntoh24(bottom->peer_d_id);
4739d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt		adapter->peer_wwpn = plogi->fl_wwpn;
4749d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt		adapter->peer_wwnn = plogi->fl_wwnn;
475c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
476c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
477c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_FABRIC:
478c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
479c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
480c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_TOPO_AL:
481c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
482dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
483c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
485ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"Unknown or unsupported arbitrated loop "
486ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"fibre channel topology detected\n");
487ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1");
488c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EIO;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
490c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
491ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	zfcp_scsi_set_prot(adapter);
492ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
497553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt{
498553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	struct zfcp_adapter *adapter = req->adapter;
499c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
500c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config;
501c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
502553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt
503c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
506c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->fsf_lic_version = bottom->lic_version;
507c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->adapter_features = bottom->adapter_features;
508c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->connection_features = bottom->connection_features;
509c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_wwpn = 0;
510c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_wwnn = 0;
511c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	adapter->peer_d_id = 0;
5128a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
513c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->header.fsf_status) {
514c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GOOD:
515c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (zfcp_fsf_exchange_config_evaluate(req))
516c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			return;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
518c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
519c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			dev_err(&adapter->ccw_device->dev,
520ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"FCP adapter maximum QTCB size (%d bytes) "
521ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				"is too small\n",
522ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt				bottom->max_qtcb_size);
523ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1");
524c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			return;
525c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		}
526c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
527c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				&adapter->status);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
529c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
530c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_node_name(shost) = 0;
531c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_name(shost) = 0;
532c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_id(shost) = 0;
533c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
534c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
535c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->hydra_version = 0;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
537edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_fsf_link_down_info_eval(req,
538c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			&qtcb->header.fsf_status_qual.link_down_info);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
540c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
541ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3");
542c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
543c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
545c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
546c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->hardware_version = bottom->hardware_version;
547c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(fc_host_serial_number(shost), bottom->serial_number,
548c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       min(FC_SERIAL_NUMBER_SIZE, 17));
549c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		EBCASC(fc_host_serial_number(shost),
550c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       min(FC_SERIAL_NUMBER_SIZE, 17));
551c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
553c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
554c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
555ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter only supports newer "
556ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"control block versions\n");
557ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4");
558c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
559c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
560c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
561c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&adapter->ccw_device->dev,
562ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"The FCP adapter only supports older "
563ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"control block versions\n");
564ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5");
565c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
566c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
568c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
569c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
570c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
571c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_port *bottom = &req->qtcb->bottom.port;
572c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct Scsi_Host *shost = adapter->scsi_host;
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
574c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->data)
575c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		memcpy(req->data, bottom, sizeof(*bottom));
5769eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin
5770282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
578c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = bottom->wwpn;
5790282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
5800282985da5923fa6365adcc1a1586ae0c13c1617Christof Schmitt	} else
581c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
582c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
583c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	fc_host_supported_speeds(shost) = bottom->supported_speed;
5842d8e62bbf7e83facd5701c100f62fbf0df4ee486Christof Schmitt	memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
5852d8e62bbf7e83facd5701c100f62fbf0df4ee486Christof Schmitt	       FC_FC4_LIST_SIZE);
5862d8e62bbf7e83facd5701c100f62fbf0df4ee486Christof Schmitt	memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
5872d8e62bbf7e83facd5701c100f62fbf0df4ee486Christof Schmitt	       FC_FC4_LIST_SIZE);
588c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
590c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
591c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
592c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
593c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
594c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
595c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
596c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
597c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (qtcb->header.fsf_status) {
598c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GOOD:
599c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_exchange_port_evaluate(req);
600c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
601c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
602c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_exchange_port_evaluate(req);
603edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_fsf_link_down_info_eval(req,
604c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			&qtcb->header.fsf_status_qual.link_down_info);
605aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin		break;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
607c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
608d26ab06ede83287f99067fee3034c5455a75faf9Swen Schillig
609a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligstatic struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
610c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
611c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
612a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
613a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(pool))
614a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		req = mempool_alloc(pool, GFP_ATOMIC);
615a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	else
616a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		req = kmalloc(sizeof(*req), GFP_ATOMIC);
617a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
618a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (unlikely(!req))
619c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
620a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
621c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(req, 0, sizeof(*req));
62288f2a977870af655296a682fe2a58c822cd25bb2Christof Schmitt	req->pool = pool;
623c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
624c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
625c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
626a4623c467ff76f9258555d44d68371e10c5406c2Swen Schilligstatic struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
627c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
628a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	struct fsf_qtcb *qtcb;
629c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
630c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (likely(pool))
631c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		qtcb = mempool_alloc(pool, GFP_ATOMIC);
632c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	else
633259afe2ed92c179e0a85da10ca63bf927b9851caChristof Schmitt		qtcb = kmem_cache_alloc(zfcp_fsf_qtcb_cache, GFP_ATOMIC);
634a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
635c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!qtcb))
636c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
637c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
638c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(qtcb, 0, sizeof(*qtcb));
639a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	return qtcb;
640c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
641c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
642564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligstatic struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
6433ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber						u32 fsf_cmd, u8 sbtype,
6441674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt						mempool_t *pool)
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
646564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
647a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
649c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(!req))
6501e9b16430ff4fd09408a74342d6b8338228e2f70Christof Schmitt		return ERR_PTR(-ENOMEM);
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
652c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (adapter->req_no == 0)
653c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->req_no++;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
655c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	INIT_LIST_HEAD(&req->list);
656c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	init_timer(&req->timer);
657058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig	init_completion(&req->completion);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
659c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->adapter = adapter;
660c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->fsf_command = fsf_cmd;
66152bfb558d2803590f86360ec3af1750897a9c010Christof Schmitt	req->req_id = adapter->req_no;
662c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
663a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig	if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
664a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (likely(pool))
665a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool);
666a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		else
667a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			req->qtcb = zfcp_qtcb_alloc(NULL);
668a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
669a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		if (unlikely(!req->qtcb)) {
670a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			zfcp_fsf_req_free(req);
671a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig			return ERR_PTR(-ENOMEM);
672a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig		}
673a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig
6745bdecd2248d4af6f3b311b4d8ca7f3f5f83a7191Christof Schmitt		req->seq_no = adapter->fsf_req_seq_no;
675564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
676c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.req_id = req->req_id;
677c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.ulp_info = 26;
678c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command];
679c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION;
680c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->header.req_handle = req->req_id;
681c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->header.fsf_command = req->fsf_command;
682c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
683c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
6841674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,
6851674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt			   req->qtcb, sizeof(struct fsf_qtcb));
6861674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt
687c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
690c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
691c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
692c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
693564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
694b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt	int with_qtcb = (req->qtcb != NULL);
695e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt	int req_id = req->req_id;
696c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
697b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt	zfcp_reqlist_add(adapter->req_list, req);
698c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
699706eca49a044a1ea89352dcc4b96ffc1631b2cb5Swen Schillig	req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free);
700c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->issued = get_clock();
70134c2b712992540ca436e97432ffc57c84c8f8c18Christof Schmitt	if (zfcp_qdio_send(qdio, &req->qdio_req)) {
702c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		del_timer(&req->timer);
7033765138ae946e6e29b22bf15a9647c600c232639Christof Schmitt		/* lookup request again, list might have changed */
704b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt		zfcp_reqlist_find_rm(adapter->req_list, req_id);
705ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1");
706c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EIO;
707c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
708c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
709c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	/* Don't increase for unsolicited status */
710135ea137e3c2872448c12d3a8890389fa64990c6Martin Petermann	if (with_qtcb)
711c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		adapter->fsf_req_seq_no++;
71252bfb558d2803590f86360ec3af1750897a9c010Christof Schmitt	adapter->req_no++;
713c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
714c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return 0;
715c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
716c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
717c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
718c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_status_read - send status read request
719c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @adapter: pointer to struct zfcp_adapter
720c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @req_flags: request flags
721c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, ERROR otherwise
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
723564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_status_read(struct zfcp_qdio *qdio)
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
725564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
726c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
727c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_status_read_buffer *sr_buf;
728c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	struct page *page;
729c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
73144a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
7326b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
733c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
734c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
7351674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, 0,
736a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig				  adapter->pool.status_read_req);
737025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
738c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
739c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
742c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	page = mempool_alloc(adapter->pool.sr_data, GFP_ATOMIC);
743c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	if (!page) {
744c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = -ENOMEM;
745c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_buf;
746c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
747c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	sr_buf = page_address(page);
748c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	memset(sr_buf, 0, sizeof(*sr_buf));
749c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = sr_buf;
7501674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt
7511674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_fill_next(qdio, &req->qdio_req, sr_buf, sizeof(*sr_buf));
7521674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
753059c97d0434834d291eff94669ca2dd3eaac9d28Andreas Herrmann
754c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
755c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (retval)
756c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_req_send;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
758c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
759c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
760c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_req_send:
761a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig	req->data = NULL;
762c7b279ae51942c14529bf2806685e9c658f28611Christof Schmitt	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
763c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_buf:
764a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig	zfcp_dbf_hba_fsf_uss("fssr__1", req);
765c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
766c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
76744a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
768c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
769c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
770c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
771c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
772c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
773b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct scsi_device *sdev = req->data;
774b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
775c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
776c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
777c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
778c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return;
779c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
780c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
782c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (fsq->word[0] == fsq->word[1]) {
783b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
784ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig						"fsafch1");
785c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_HANDLE_NOT_VALID:
789c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (fsq->word[0] == fsq->word[1]) {
790ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2");
791c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
795c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
798edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_port_status(zfcp_sdev->port,
799edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
800edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_port_reopen(zfcp_sdev->port,
801ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3");
8024c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_BOXED:
805edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
806edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
807ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				    "fsafch4");
8084c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                break;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
811c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		switch (fsq->word[0]) {
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
813b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			zfcp_fc_test_link(zfcp_sdev->port);
814dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt			/* fall through */
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
816c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
821c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
827b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
828b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * @scmnd: The SCSI command to abort
829c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: pointer to struct zfcp_fsf_req
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
832b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstruct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
834c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
835b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct scsi_device *sdev = scmnd->device;
836b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
837b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
838b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	unsigned long old_req_id = (unsigned long) scmnd->host_scribble;
8398a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
84044a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
8416b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
842c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
843564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
8443ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
845564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.scsi_abort);
846633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	if (IS_ERR(req)) {
847633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig		req = NULL;
848c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
849633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	}
8502abbe866c8eb0296e3f5343bcf73e5371522a738Andreas Herrmann
851b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
852c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
853c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out_error_free;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8576fbf25e86beef1c6719e760a241a7aef9ad145e3Swen Schillig	req->data = sdev;
858c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_abort_fcp_command_handler;
859b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
860b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
861c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.support.req_handle = (u64) old_req_id;
862c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
863c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
864c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!zfcp_fsf_req_send(req))
865c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
866c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
867c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout_error_free:
868c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
869c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req = NULL;
870c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
87144a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
872c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
875c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
877c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
8787c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt	struct zfcp_fsf_ct_els *ct = req->data;
879c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8817c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt	ct->status = -EINVAL;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
883c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_GOOD:
8882c55b750a884b86dea8b4cc5f15e1484cc47a25cSwen Schillig		zfcp_dbf_san_res("fsscth1", req);
8897c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt		ct->status = 0;
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
892c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_ADAPTER_STATUS_AVAILABLE:
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch (header->fsf_status_qual.word[0]){
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
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_ACCESS_DENIED:
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        case FSF_PORT_BOXED:
9054c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
907c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_HANDLE_NOT_VALID:
908ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1");
909dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
910c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_GENERIC_COMMAND_REJECTED:
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PAYLOAD_SIZE_MISMATCH:
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_REQUEST_SIZE_TOO_LARGE:
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_RESPONSE_SIZE_TOO_LARGE:
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_SBAL_MISMATCH:
915c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus:
9207c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt	if (ct->handler)
9217c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt		ct->handler(ct->handler_data);
922c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9241674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmittstatic void zfcp_fsf_setup_ct_els_unchained(struct zfcp_qdio *qdio,
9251674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt					    struct zfcp_qdio_req *q_req,
926426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt					    struct scatterlist *sg_req,
927426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt					    struct scatterlist *sg_resp)
928426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt{
9291674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_fill_next(qdio, q_req, sg_virt(sg_req), sg_req->length);
9301674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_fill_next(qdio, q_req, sg_virt(sg_resp), sg_resp->length);
9311674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, q_req);
932426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt}
933426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt
93439eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmittstatic int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
93539eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt				       struct scatterlist *sg_req,
93601b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig				       struct scatterlist *sg_resp)
937c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
93842428f747a8a0db9c6de03e105932316defad65dSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
93986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
94086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	struct fsf_qtcb *qtcb = req->qtcb;
94142428f747a8a0db9c6de03e105932316defad65dSwen Schillig	u32 feat = adapter->adapter_features;
942c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
94386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (zfcp_adapter_multi_buffer_active(adapter)) {
94486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
94586a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig			return -EIO;
94686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
94786a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig			return -EIO;
94839eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt
94986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
95086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig					zfcp_qdio_sbale_count(sg_req));
95186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
95286a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		zfcp_qdio_set_scount(qdio, &req->qdio_req);
953426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt		return 0;
954426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	}
955426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt
956426f6059b0eb66cec139f4b9066168ab72b85774Christof Schmitt	/* use single, unchained SBAL if it can hold the request */
95730b6777b8931afc5f3aa42858fe917938b570f79Swen Schillig	if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
95886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		zfcp_fsf_setup_ct_els_unchained(qdio, &req->qdio_req,
9591674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt						sg_req, sg_resp);
96039eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt		return 0;
96139eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt	}
96239eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt
96386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS))
96486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		return -EOPNOTSUPP;
96586a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig
96686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
9679072df4dc6e8fd569d583815edb0198af4b688b8Christof Schmitt		return -EIO;
968c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
96986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	qtcb->bottom.support.req_buf_length = zfcp_qdio_real_bytes(sg_req);
97086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig
97186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
97286a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	zfcp_qdio_skip_to_last_sbale(qdio, &req->qdio_req);
97386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig
97486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
9759072df4dc6e8fd569d583815edb0198af4b688b8Christof Schmitt		return -EIO;
97686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig
97786a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	qtcb->bottom.support.resp_buf_length = zfcp_qdio_real_bytes(sg_resp);
97886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig
97986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
98098fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt
981b1a58985853574346f1518531bdd82069501b317Christof Schmitt	return 0;
982b1a58985853574346f1518531bdd82069501b317Christof Schmitt}
983b1a58985853574346f1518531bdd82069501b317Christof Schmitt
984b1a58985853574346f1518531bdd82069501b317Christof Schmittstatic int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
985b1a58985853574346f1518531bdd82069501b317Christof Schmitt				 struct scatterlist *sg_req,
986b1a58985853574346f1518531bdd82069501b317Christof Schmitt				 struct scatterlist *sg_resp,
98701b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig				 unsigned int timeout)
988b1a58985853574346f1518531bdd82069501b317Christof Schmitt{
989b1a58985853574346f1518531bdd82069501b317Christof Schmitt	int ret;
990b1a58985853574346f1518531bdd82069501b317Christof Schmitt
99101b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig	ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp);
992b1a58985853574346f1518531bdd82069501b317Christof Schmitt	if (ret)
993b1a58985853574346f1518531bdd82069501b317Christof Schmitt		return ret;
994b1a58985853574346f1518531bdd82069501b317Christof Schmitt
99598fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	/* common settings for ct/gs and els requests */
99651375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig	if (timeout > 255)
99751375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig		timeout = 255; /* max value accepted by hardware */
99898fc4d5c8cd9bd1a412cca922feecb54c1c22d8eChristof Schmitt	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
99951375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig	req->qtcb->bottom.support.timeout = timeout;
100051375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig	zfcp_fsf_start_timer(req, (timeout + 10) * HZ);
1001c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1002c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return 0;
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1006c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS)
1007c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @ct: pointer to struct zfcp_send_ct with data for request
1008c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
10107c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmittint zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
101151375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig		     struct zfcp_fsf_ct_els *ct, mempool_t *pool,
101251375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig		     unsigned int timeout)
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1014564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1015c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1016c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int ret = -EIO;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101844a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
10196b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
1020c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10221674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC,
10233ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_WRITE_READ, pool);
102409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1025025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1026c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		ret = PTR_ERR(req);
1027c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
10283f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt	}
10293f0ca62add34010241db682e63bb68ba765bf4a9Christof Schmitt
103009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
103101b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig	ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout);
1032553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (ret)
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto failed_send;
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1035c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_ct_handler;
10365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->qtcb->header.port_handle = wka_port->handle;
1037c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = ct;
1038c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
10392c55b750a884b86dea8b4cc5f15e1484cc47a25cSwen Schillig	zfcp_dbf_san_req("fssct_1", req, wka_port->d_id);
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	ret = zfcp_fsf_req_send(req);
1042c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1043c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1045c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1047c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_send:
1048c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1049c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
105044a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
1051c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ret;
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1054c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10567c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt	struct zfcp_fsf_ct_els *send_els = req->data;
1057c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = send_els->port;
1058c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1060c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	send_els->status = -EINVAL;
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1062c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto skip_fsfstatus;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
10672c55b750a884b86dea8b4cc5f15e1484cc47a25cSwen Schillig		zfcp_dbf_san_res("fsselh1", req);
1068c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		send_els->status = 0;
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
1071c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]){
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_RETRY_IF_POSSIBLE:
1078c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ELS_COMMAND_REJECTED:
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PAYLOAD_SIZE_MISMATCH:
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_REQUEST_SIZE_TOO_LARGE:
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_RESPONSE_SIZE_TOO_LARGE:
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1088a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		if (port) {
1089a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt			zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
1090a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1091a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		}
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1093c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SBAL_MISMATCH:
109425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* should never occur, avoided in zfcp_fsf_send_els */
1095c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1097c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsskip_fsfstatus:
1101aa551daf5cc6fb6c6e09bb993737f9cd46dc7145Heiko Carstens	if (send_els->handler)
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_els->handler(send_els->handler_data);
1103c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1105c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1106c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
1107c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @els: pointer to struct zfcp_send_els with data for the command
1108c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig */
11097c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmittint zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
111051375ee8374dd7fa574e1a14ebac406c6d28543bSwen Schillig		      struct zfcp_fsf_ct_els *els, unsigned int timeout)
1111c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
1112c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
11137c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt	struct zfcp_qdio *qdio = adapter->qdio;
1114c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int ret = -EIO;
1115c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
111644a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
11176b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
1118c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
111909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
11201674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS,
11213ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_WRITE_READ, NULL);
112209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1123025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1124c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		ret = PTR_ERR(req);
1125c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1126c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
1127c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
112809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
112901b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig
113086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (!zfcp_adapter_multi_buffer_active(adapter))
113186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
113201b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig
113301b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig	ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout);
113444cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig
1135c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1136c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
1137c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
11387c7dc196814b9e1d5cc254dc579a5fa78ae524f7Christof Schmitt	hton24(req->qtcb->bottom.support.d_id, d_id);
1139c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_send_els_handler;
1140c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = els;
1141c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
11422c55b750a884b86dea8b4cc5f15e1484cc47a25cSwen Schillig	zfcp_dbf_san_req("fssels1", req, d_id);
1143c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1144c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	ret = zfcp_fsf_req_send(req);
1145c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (ret)
1146c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_send;
1147c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1148c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
1149c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1150c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_send:
1151c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1152c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
115344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
1154c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ret;
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1157c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1159c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1160564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1161c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1162c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
116344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
11646b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
1165c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
116609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1167564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
11683ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1169564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
117009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1171025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1172c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1173c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
117609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
11771674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1179c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.config.feature_selection =
1180aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_CFDC |
1181aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_LUN_SHARING |
11829eb69aff79264b5f35e41922df20a488c67e9ee2Maxim Shchetynin			FSF_FEATURE_NOTIFICATION_LOST |
1183aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin			FSF_FEATURE_UPDATE_ALERT;
1184c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1185c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_config_data_handler;
1186e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt	erp_action->fsf_req_id = req->req_id;
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1188287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1189c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1191c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
1192e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt		erp_action->fsf_req_id = 0;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1194c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
119544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
119652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	return retval;
119752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig}
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1199564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
1200c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				       struct fsf_qtcb_bottom_config *data)
120152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{
1202c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
1203c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1204c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
120544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
12066b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
1207ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
1208c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
12091674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
12103ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ, NULL);
121109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1212025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1213c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1214ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
121552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	}
121652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
12171674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1218c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_config_data_handler;
121952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1220c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.config.feature_selection =
122152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_CFDC |
122252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_LUN_SHARING |
122352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_NOTIFICATION_LOST |
122452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig			FSF_FEATURE_UPDATE_ALERT;
122552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
122652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	if (data)
1227c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->data = data;
122852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1229c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
1230c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
123144a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
1232553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (!retval)
1233058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
123452ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1235c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
1236ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt	return retval;
123752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1238ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmittout_unlock:
123944a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * zfcp_fsf_exchange_port_data - request information about local port
1245aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin * @erp_action: ERP action for the adapter for which port data is requested
1246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1248c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1250564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1252c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1254564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
125552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig		return -EOPNOTSUPP;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
125744a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
12586b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
1259c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
126009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1261564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
12623ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1263564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
126409a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1265025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1266c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1267c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1268aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin	}
1269aef4a983090fa590481a86d9690dc3fa6bb121faMaxim Shchetynin
127009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
12711674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1273c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_port_data_handler;
1274c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1275e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt	erp_action->fsf_req_id = req->req_id;
127652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1277287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1280c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
1281e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt		erp_action->fsf_req_id = 0;
128252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	}
1283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
128444a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
128552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	return retval;
128652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig}
128752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
128852ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig/**
128952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig * zfcp_fsf_exchange_port_data_sync - request information about local port
1290564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig * @qdio: pointer to struct zfcp_qdio
1291c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @data: pointer to struct fsf_qtcb_bottom_port
1292c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
129352ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig */
1294564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligint zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
1295c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				     struct fsf_qtcb_bottom_port *data)
129652ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig{
1297c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
1298c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
129952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1300564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
130152ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig		return -EOPNOTSUPP;
130252ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
130344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
13046b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
1305ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
1306c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
13071674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
13083ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ, NULL);
130909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1310025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1311c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1312ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt		goto out_unlock;
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131552ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig	if (data)
1316c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->data = data;
131752ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
13181674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
131952ef11a7170e1b8a0d5f9a42dbb43c38c335c32eSwen Schillig
1320c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_exchange_port_data_handler;
1321c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
1322c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
132344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
1324ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt
1325553448f6c4838a1e4bed2bc9301c748278d7d9ceChristof Schmitt	if (!retval)
1326058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
1327058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig
1328c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
1331ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt
1332ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmittout_unlock:
133344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
1334ada81b748b768eb5b75567fd1db5e87ba5c98bf0Christof Schmitt	return retval;
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1337c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1339c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
1340c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
13419d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt	struct fc_els_flogi *plogi;
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1344a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann		goto out;
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_ALREADY_OPEN:
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1350a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
1351a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
1354c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&req->adapter->ccw_device->dev,
1355ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "Not enough FCP adapter resources to open "
13567ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 "remote port 0x%016Lx\n",
13577ba58c9cc16d296290fe645acb11db2b01276544Swen Schillig			 (unsigned long long)port->wwpn);
1358edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_port_status(port,
1359edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig					 ZFCP_STATUS_COMMON_ERP_FAILED);
1360c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_NO_RETRY_POSSIBLE:
1367c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		port->handle = header->port_handle;
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1375d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1376d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
1377d736a27b7efbc835c7b83db5c1bbd41edbadf32eAndreas Herrmann		                  &port->status);
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* check whether D_ID has changed during open */
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * FIXME: This check is not airtight, as the FCP channel does
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * not monitor closures of target port connections caused on
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the remote side. Thus, they might miss out on invalidating
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * locally cached WWPNs (and other N_Port parameters) of gone
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * target ports. So, our heroic attempt to make things safe
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * could be undermined by 'open port' response data tagged with
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * obsolete WWPNs. Another reason to monitor potential
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * connection closures ourself at least (by interpreting
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * incoming ELS' and unsolicited status). It just crosses my
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * mind that one should be able to cross-check by means of
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * another GID_PN straight after a port has been opened.
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Alternately, an ADISC/PDISC ELS should suffice, as well.
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13939d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt		plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els;
139439eb7e9aca2a582330ddb6f1167272268e6b3965Christof Schmitt		if (req->qtcb->bottom.support.els1_length >=
13959d05ce2c0a6704ff84df02cbb3baef94fcac4f5dChristof Schmitt		    FSF_PLOGI_MIN_LEN)
1396c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig				zfcp_fc_plogi_evaluate(port, plogi);
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_UNKNOWN_OP_SUBTYPE:
1399c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1402a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann
1403a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermannout:
1404615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	put_device(&port->dev);
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1407c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1408c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_open_port - create and send open port request
1409c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1410c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1412c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1414564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1415a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	struct zfcp_port *port = erp_action->port;
1416564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_fsf_req *req;
1417c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1418c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
141944a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
14206b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
1421c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1422c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1423564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
14243ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1425564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
142609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1427025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1428c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
1430c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
143209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
14331674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1435c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_open_port_handler;
1436800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt	hton24(req->qtcb->bottom.support.d_id, port->d_id);
1437a17c5855643afa7838f542cbd0a1ed9a73968cefMartin Petermann	req->data = port;
1438c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1439e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt	erp_action->fsf_req_id = req->req_id;
1440615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt	get_device(&port->dev);
1441c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1442287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1443c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1445c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
1446e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt		erp_action->fsf_req_id = 0;
1447615f59e0daaf56e43dcaaf3ea228967d9bc21584Christof Schmitt		put_device(&port->dev);
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1449c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
145044a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1454c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1456c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1458c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
145944cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
1463ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1");
1464c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
1469edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN);
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1474c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1475c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_port - create and send close port request
1476c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1477c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1479c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1481564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1482c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1483c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1484c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
148544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
14866b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
1487c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1488c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1489564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
14903ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1491564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
149209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1493025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1494c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
1496c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
149809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
14991674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_close_port_handler;
1502c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->port;
1503c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1504c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1505e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt	erp_action->fsf_req_id = req->req_id;
1506c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1507287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1508c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1510c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
1511e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt		erp_action->fsf_req_id = 0;
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1513c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
151444a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15185ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligstatic void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
15195ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
1520bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt	struct zfcp_fc_wka_port *wka_port = req->data;
15215ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
15225ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
15235ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
1524bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
15255ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
15265ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
15275ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
15285ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	switch (header->fsf_status) {
15295ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
15305ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		dev_warn(&req->adapter->ccw_device->dev,
15315ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig			 "Opening WKA port 0x%x failed\n", wka_port->d_id);
1532dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
15335ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
15345ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1535dceab655d9f7d99881c2033c8ff4e1c7b444e104Christof Schmitt		/* fall through */
15365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_ACCESS_DENIED:
1537bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
15385ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		break;
15395ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	case FSF_GOOD:
15405ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		wka_port->handle = header->port_handle;
154127f492ccec94b6acd8440c83bfe0515ce4db0af0Swen Schillig		/* fall through */
154227f492ccec94b6acd8440c83bfe0515ce4db0af0Swen Schillig	case FSF_PORT_ALREADY_OPEN:
1543bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt		wka_port->status = ZFCP_FC_WKA_PORT_ONLINE;
15445ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
15455ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
15465ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	wake_up(&wka_port->completion_wq);
15475ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
15485ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
15495ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig/**
15505ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * zfcp_fsf_open_wka_port - create and send open wka-port request
1551bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt * @wka_port: pointer to struct zfcp_fc_wka_port
15525ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * Returns: 0 on success, error otherwise
15535ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig */
1554bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmittint zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
15555ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
1556564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
15575ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_fsf_req *req;
15585ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	int retval = -EIO;
15595ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
156044a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
15616b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
15625ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
15635ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1564564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
15653ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1566564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
156709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
15684e7d7af4dfea65b50b0fc694e3febc202e4e9839Tobias Klauser	if (IS_ERR(req)) {
15695ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		retval = PTR_ERR(req);
15705ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
15715ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
15725ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
157309a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
15741674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
15755ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
15765ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->handler = zfcp_fsf_open_wka_port_handler;
1577800c0cad962dcf630cabf3efdc5983619e73d4c9Christof Schmitt	hton24(req->qtcb->bottom.support.d_id, wka_port->d_id);
15785ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->data = wka_port;
15795ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
15805ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
15815ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	retval = zfcp_fsf_req_send(req);
15825ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (retval)
15835ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		zfcp_fsf_req_free(req);
15845ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
158544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
15865ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	return retval;
15875ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
15885ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
15895ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligstatic void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
15905ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
1591bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt	struct zfcp_fc_wka_port *wka_port = req->data;
15925ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
15935ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
15945ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1595ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1");
15965ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
15975ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1598bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt	wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
15995ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	wake_up(&wka_port->completion_wq);
16005ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
16015ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16025ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig/**
16035ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * zfcp_fsf_close_wka_port - create and send close wka port request
1604bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmitt * @wka_port: WKA port to open
16055ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig * Returns: 0 on success, error otherwise
16065ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig */
1607bd0072ecc449fb2ea8f6a2c9f6ff308f3ae0b078Christof Schmittint zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
16085ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig{
1609564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
16105ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	struct zfcp_fsf_req *req;
16115ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	int retval = -EIO;
16125ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
161344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
16146b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
16155ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16165ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1617564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
16183ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1619564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
162009a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
16214e7d7af4dfea65b50b0fc694e3febc202e4e9839Tobias Klauser	if (IS_ERR(req)) {
16225ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		retval = PTR_ERR(req);
16235ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		goto out;
16245ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	}
16255ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
162609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
16271674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
16285ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16295ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->handler = zfcp_fsf_close_wka_port_handler;
16305ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->data = wka_port;
16315ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	req->qtcb->header.port_handle = wka_port->handle;
16325ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
16335ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
16345ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	retval = zfcp_fsf_req_send(req);
16355ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	if (retval)
16365ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig		zfcp_fsf_req_free(req);
16375ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schilligout:
163844a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
16395ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig	return retval;
16405ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig}
16415ab944f97e09a3d52951fe903eed9a7b88d810b2Swen Schillig
1642c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1644c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_port *port = req->data;
1645c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
1646b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct scsi_device *sdev;
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1648c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1649a5b11dda12ed7e3a79180b10ad6209a40a02989fChristof Schmitt		return;
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
1653ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1");
1654c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1657a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
16605c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		/* can't use generic zfcp_erp_modify_port_status because
16615c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
16625c815d1501a9ce84578cb3ec64c9d31ef91e3de2Christof Schmitt		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1663b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		shost_for_each_device(sdev, port->adapter->scsi_host)
1664b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			if (sdev_to_zfcp(sdev)->port == port)
1665b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt				atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1666b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt						  &sdev_to_zfcp(sdev)->status);
1667edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
1668edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
1669ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				     "fscpph2");
16704c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1675c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
1677c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* can't use generic zfcp_erp_modify_port_status because
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1686b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		shost_for_each_device(sdev, port->adapter->scsi_host)
1687b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			if (sdev_to_zfcp(sdev)->port == port)
1688b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt				atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1689b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt						  &sdev_to_zfcp(sdev)->status);
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1694c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1695c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_close_physical_port - close physical port
1696c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1697c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1699c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligint zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1701564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1702c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1703c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1704c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
170544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
17066b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1709564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
17103ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1711564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
171209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1713025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1714c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1715c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1716c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171809a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
17191674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1721c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = erp_action->port;
1722c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1723c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1724c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_close_physical_port_handler;
1725e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt	erp_action->fsf_req_id = req->req_id;
1726c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1727287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1728c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1730c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
1731e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt		erp_action->fsf_req_id = 0;
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1733c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
173444a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1738b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstatic void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1740c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = req->adapter;
1741b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct scsi_device *sdev = req->data;
1742b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
1743c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
1744c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1746c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
174744cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1750b64ddf96456cde17be22bf74cafed381a29d58baHeiko Carstens			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
1751b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			  ZFCP_STATUS_LUN_SHARED |
1752b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			  ZFCP_STATUS_LUN_READONLY,
1753b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			  &zfcp_sdev->status);
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (header->fsf_status) {
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
1758ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
1759c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_ALREADY_OPEN:
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ACCESS_DENIED:
1763a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
1764a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
1767edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_port_status(zfcp_sdev->port,
1768edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
1769edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_port_reopen(zfcp_sdev->port,
1770ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2");
17714c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_SHARING_VIOLATION:
1774a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual);
1775c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
1778c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_warn(&adapter->ccw_device->dev,
1779ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "No handle is available for LUN "
1780ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			 "0x%016Lx on port 0x%016Lx\n",
1781b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			 (unsigned long long)zfcp_scsi_dev_lun(sdev),
1782b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			 (unsigned long long)zfcp_sdev->port->wwpn);
1783edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
1784c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		/* fall through */
1785c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_INVALID_COMMAND_OPTION:
1786c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (header->fsf_status_qual.word[0]) {
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1791b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			zfcp_fc_test_link(zfcp_sdev->port);
1792c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
1794c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
1800b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		zfcp_sdev->lun_handle = header->lun_handle;
1801b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
1802a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		zfcp_cfdc_open_lun_eval(sdev, bottom);
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1807c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
1808b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_open_lun - open LUN
1809c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @erp_action: pointer to struct zfcp_erp_action
1810c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1812b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittint zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1814c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_adapter *adapter = erp_action->adapter;
1815564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
1816c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1817c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
1818c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
181944a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
18206b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1823564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
18243ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1825a4623c467ff76f9258555d44d68371e10c5406c2Swen Schillig				  adapter->pool.erp_req);
182609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1827025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1828c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1829c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1830c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
1831c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
183209a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
18331674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1835c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1836b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->qtcb->bottom.support.fcp_lun = zfcp_scsi_dev_lun(erp_action->sdev);
1837b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->handler = zfcp_fsf_open_lun_handler;
1838b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->data = erp_action->sdev;
1839c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1840e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt	erp_action->fsf_req_id = req->req_id;
1841c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1842c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE))
1843c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING;
1844c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
1845287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1846c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (retval) {
1848c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
1849e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt		erp_action->fsf_req_id = 0;
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1851c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
185244a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1856b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstatic void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1858b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct scsi_device *sdev = req->data;
1859b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
186244cc76f2d154aa24340354b4711a0fe7f8f08adcSwen Schillig		return;
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1864c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (req->qtcb->header.fsf_status) {
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_HANDLE_NOT_VALID:
1866ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1");
1867c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_LUN_HANDLE_NOT_VALID:
1870ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2");
1871c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_PORT_BOXED:
1874edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_port_status(zfcp_sdev->port,
1875edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
1876edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_port_reopen(zfcp_sdev->port,
1877ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				     ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3");
18784c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_ADAPTER_STATUS_AVAILABLE:
1881c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		switch (req->qtcb->header.fsf_status_qual.word[0]) {
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1883b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			zfcp_fc_test_link(zfcp_sdev->port);
1884c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			/* fall through */
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
1886c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FSF_GOOD:
1891b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
1897b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_close_LUN - close LUN
1898b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * @erp_action: pointer to erp_action triggering the "close LUN"
1899c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: 0 on success, error otherwise
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1901b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittint zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1903564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1904b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
1905c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
1906c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	int retval = -EIO;
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
190844a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
19096b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
191109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1912564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
19133ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_READ,
1914564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.erp_req);
191509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
1916025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
1917c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
1918c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
1919c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
192109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
19221674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1924c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->header.port_handle = erp_action->port->handle;
1925b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
1926b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->handler = zfcp_fsf_close_lun_handler;
1927b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->data = erp_action->sdev;
1928c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->erp_action = erp_action;
1929e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt	erp_action->fsf_req_id = req->req_id;
1930fdf234527a070f6fc89f3ec5ee4ae1b263e59939Christof Schmitt
1931287ac01acf22ab6aaaf9f5a4919ce2449c8b391cChristof Schmitt	zfcp_fsf_start_erp_timer(req);
1932c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
1933c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (retval) {
1934c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
1935e60a6d69f1f84c2ef1cc63aefaadfe7ae9f12934Christof Schmitt		erp_action->fsf_req_id = 0;
1936c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
1937c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
193844a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
1939c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1942c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmittstatic void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
1943c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt{
1944c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt	lat_rec->sum += lat;
1945c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	lat_rec->min = min(lat_rec->min, lat);
1946c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	lat_rec->max = max(lat_rec->max, lat);
1947c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt}
1948c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
1949d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmittstatic void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
1950c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt{
1951d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	struct fsf_qual_latency_info *lat_in;
1952d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	struct latency_cont *lat = NULL;
1953b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
1954d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	struct zfcp_blk_drv_data blktrc;
1955d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	int ticks = req->adapter->timer_ticks;
1956c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
1957d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	lat_in = &req->qtcb->prefix.prot_status_qual.latency_info;
1958c9615858a81d2424c78b10a2f689ba24b156937cChristof Schmitt
1959d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	blktrc.flags = 0;
1960d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
1961d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1962d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		blktrc.flags |= ZFCP_BLK_REQ_ERROR;
1963706eca49a044a1ea89352dcc4b96ffc1631b2cb5Swen Schillig	blktrc.inb_usage = 0;
196434c2b712992540ca436e97432ffc57c84c8f8c18Christof Schmitt	blktrc.outb_usage = req->qdio_req.qdio_outb_usage;
1965d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt
19665bbf297cc652713a0a6511004b8d4c1cc21a3b02Christof Schmitt	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
19675bbf297cc652713a0a6511004b8d4c1cc21a3b02Christof Schmitt	    !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
1968d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		blktrc.flags |= ZFCP_BLK_LAT_VALID;
1969d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		blktrc.channel_lat = lat_in->channel_lat * ticks;
1970d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		blktrc.fabric_lat = lat_in->fabric_lat * ticks;
1971d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt
1972d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		switch (req->qtcb->bottom.io.data_direction) {
1973ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		case FSF_DATADIR_DIF_READ_STRIP:
1974ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		case FSF_DATADIR_DIF_READ_CONVERT:
1975d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		case FSF_DATADIR_READ:
1976b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			lat = &zfcp_sdev->latencies.read;
1977d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			break;
1978ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		case FSF_DATADIR_DIF_WRITE_INSERT:
1979ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		case FSF_DATADIR_DIF_WRITE_CONVERT:
1980d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		case FSF_DATADIR_WRITE:
1981b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			lat = &zfcp_sdev->latencies.write;
1982d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			break;
1983d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		case FSF_DATADIR_CMND:
1984b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			lat = &zfcp_sdev->latencies.cmd;
1985d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			break;
1986d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		}
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1988d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		if (lat) {
1989b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			spin_lock(&zfcp_sdev->latencies.lock);
1990d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
1991d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
1992d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			lat->counter++;
1993b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			spin_unlock(&zfcp_sdev->latencies.lock);
1994d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt		}
19950997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl	}
19960997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
1997d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt	blk_add_driver_data(scsi->request->q, scsi->request, &blktrc,
1998d9742b42b5c76e2a3a39de0d187fac4f6852134eChristof Schmitt			    sizeof(blktrc));
19990997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl}
20000997f1c5fec0b540784611036d458a84a1f7029aStefan Raspl
2001c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmittstatic void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
2002c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
2003b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct scsi_cmnd *scmnd = req->data;
2004b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct scsi_device *sdev = scmnd->device;
2005b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
2006c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_header *header = &req->qtcb->header;
2007c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2008c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
2009c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		return;
20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (header->fsf_status) {
2012c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_HANDLE_MISMATCH:
2013c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_HANDLE_NOT_VALID:
2014ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1");
2015c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2016c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2017c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_FCPLUN_NOT_VALID:
2018c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_LUN_HANDLE_NOT_VALID:
2019ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2");
2020c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2022c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
2023c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_class_not_supp(req);
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2025c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ACCESS_DENIED:
2026a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
2027a1ca48319a9aa1c5b57ce142f538e76050bb8972Christof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2028c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2029c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_DIRECTION_INDICATOR_NOT_VALID:
2030c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
2031b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			"Incorrect direction %d, LUN 0x%016Lx on port "
2032ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"0x%016Lx closed\n",
2033c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->bottom.io.data_direction,
2034b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			(unsigned long long)zfcp_scsi_dev_lun(sdev),
2035b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			(unsigned long long)zfcp_sdev->port->wwpn);
2036b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
2037ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig					  "fssfch3");
2038c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2039c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2040c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_CMND_LENGTH_NOT_VALID:
2041c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		dev_err(&req->adapter->ccw_device->dev,
2042b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			"Incorrect CDB length %d, LUN 0x%016Lx on "
2043ff3b24fa5370a7ca618f212284d9b36fcedb9c0eChristof Schmitt			"port 0x%016Lx closed\n",
2044c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig			req->qtcb->bottom.io.fcp_cmnd_length,
2045b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			(unsigned long long)zfcp_scsi_dev_lun(sdev),
2046b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			(unsigned long long)zfcp_sdev->port->wwpn);
2047b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
2048ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig					  "fssfch4");
2049c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2050c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2051c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_PORT_BOXED:
2052edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_port_status(zfcp_sdev->port,
2053edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
2054edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_port_reopen(zfcp_sdev->port,
2055ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				     ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5");
20564c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2057c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2058c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_LUN_BOXED:
2059edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
2060edaed859e63aac174fcc3fed81886b91bb124661Swen Schillig		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
2061ea4a3a6ac40e2a585654808d4aefb39a6d57dca0Swen Schillig				    "fssfch6");
20624c571c659e9d41332b6981ca5379047681ce9d2fChristof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
2063c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2064c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_ADAPTER_STATUS_AVAILABLE:
2065c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		if (header->fsf_status_qual.word[0] ==
2066c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
2067b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt			zfcp_fc_test_link(zfcp_sdev->port);
2068c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2071c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt}
2072c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2073c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmittstatic void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
2074c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt{
2075c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	struct scsi_cmnd *scpnt;
2076c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	struct fcp_resp_with_ext *fcp_rsp;
2077c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	unsigned long flags;
2078c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2079c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	read_lock_irqsave(&req->adapter->abort_lock, flags);
2080c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2081c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	scpnt = req->data;
2082c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	if (unlikely(!scpnt)) {
2083c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		read_unlock_irqrestore(&req->adapter->abort_lock, flags);
2084c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		return;
2085c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2086c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
20875bfb2c31487eaff3840e02548e6acf89a048765bSwen Schillig	zfcp_fsf_fcp_handler_common(req);
20885bfb2c31487eaff3840e02548e6acf89a048765bSwen Schillig
2089c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2090c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED);
2091c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		goto skip_fsfstatus;
2092c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	}
2093c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2094c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	switch (req->qtcb->header.fsf_status) {
2095c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	case FSF_INCONSISTENT_PROT_DATA:
2096c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	case FSF_INVALID_PROT_PARM:
2097c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		set_host_byte(scpnt, DID_ERROR);
2098c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		goto skip_fsfstatus;
2099c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	case FSF_BLOCK_GUARD_CHECK_FAILURE:
2100c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		zfcp_scsi_dif_sense_error(scpnt, 0x1);
2101c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		goto skip_fsfstatus;
2102c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	case FSF_APP_TAG_CHECK_FAILURE:
2103c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		zfcp_scsi_dif_sense_error(scpnt, 0x2);
2104c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		goto skip_fsfstatus;
2105c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	case FSF_REF_TAG_CHECK_FAILURE:
2106c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		zfcp_scsi_dif_sense_error(scpnt, 0x3);
2107c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		goto skip_fsfstatus;
2108c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	}
2109c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
2110c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt);
2111c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2112c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmittskip_fsfstatus:
2113c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	zfcp_fsf_req_trace(req, scpnt);
2114250a1352b95e1db3216e5c5d4f4365bea5122f4aSwen Schillig	zfcp_dbf_scsi_result(scpnt, req);
2115c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2116c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	scpnt->host_scribble = NULL;
2117c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	(scpnt->scsi_done) (scpnt);
2118c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	/*
2119c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	 * We must hold this lock until scsi_done has been called.
2120c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	 * Otherwise we may call scsi_done after abort regarding this
2121c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	 * command has completed.
2122c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	 * Note: scsi_done must not block!
2123c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	 */
2124c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2127ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beckstatic int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
2128ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck{
2129ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	switch (scsi_get_prot_op(scsi_cmnd)) {
2130ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	case SCSI_PROT_NORMAL:
2131ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		switch (scsi_cmnd->sc_data_direction) {
2132ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		case DMA_NONE:
2133ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck			*data_dir = FSF_DATADIR_CMND;
2134ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck			break;
2135ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		case DMA_FROM_DEVICE:
2136ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck			*data_dir = FSF_DATADIR_READ;
2137ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck			break;
2138ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		case DMA_TO_DEVICE:
2139ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck			*data_dir = FSF_DATADIR_WRITE;
2140ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck			break;
2141ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		case DMA_BIDIRECTIONAL:
2142ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck			return -EINVAL;
2143ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		}
2144ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		break;
2145ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
2146ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	case SCSI_PROT_READ_STRIP:
2147ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		*data_dir = FSF_DATADIR_DIF_READ_STRIP;
2148ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		break;
2149ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	case SCSI_PROT_WRITE_INSERT:
2150ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		*data_dir = FSF_DATADIR_DIF_WRITE_INSERT;
2151ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		break;
2152ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	case SCSI_PROT_READ_PASS:
2153ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		*data_dir = FSF_DATADIR_DIF_READ_CONVERT;
2154ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		break;
2155ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	case SCSI_PROT_WRITE_PASS:
2156ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		*data_dir = FSF_DATADIR_DIF_WRITE_CONVERT;
2157ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		break;
2158ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	default:
2159ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		return -EINVAL;
2160ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	}
2161ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
2162ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	return 0;
2163ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck}
2164ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
2165c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
2166b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
2167c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @scsi_cmnd: scsi command to be sent
21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2169b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittint zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2171c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req;
21724318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	struct fcp_cmnd *fcp_cmnd;
21733ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber	u8 sbtype = SBAL_SFLAGS0_TYPE_READ;
217486a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	int retval = -EIO;
2175b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct scsi_device *sdev = scsi_cmnd->device;
2176b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
2177b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
2178564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
2179ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	struct fsf_qtcb_bottom_io *io;
2180e55f87531c2c1eb071a296df7eb67f83d5f0b5dfChristof Schmitt	unsigned long flags;
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2182b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
2183c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
2184c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return -EBUSY;
21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2186e55f87531c2c1eb071a296df7eb67f83d5f0b5dfChristof Schmitt	spin_lock_irqsave(&qdio->req_q_lock, flags);
2187706eca49a044a1ea89352dcc4b96ffc1631b2cb5Swen Schillig	if (atomic_read(&qdio->req_q_free) <= 0) {
2188564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig		atomic_inc(&qdio->req_q_full);
2189c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
21908fdf30d5429605a4c30cc515c73e5eab140035deChristof Schmitt	}
219109a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
21921674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE)
21933ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber		sbtype = SBAL_SFLAGS0_TYPE_WRITE;
21941674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt
2195564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
21961674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt				  sbtype, adapter->pool.scsi_req);
219709a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2198025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
2199c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = PTR_ERR(req);
2200c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2201c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
2202c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2203ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	scsi_cmnd->host_scribble = (unsigned char *) req->req_id;
2204ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
2205ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	io = &req->qtcb->bottom.io;
220609a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
2207c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->data = scsi_cmnd;
2208c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	req->handler = zfcp_fsf_fcp_cmnd_handler;
2209b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
2210b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
2211ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	io->service_class = FSF_CLASS_3;
2212ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	io->fcp_cmnd_length = FCP_CMND_LEN;
2213c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2214ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	if (scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) {
2215ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		io->data_block_length = scsi_cmnd->device->sector_size;
2216ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		io->ref_tag_value = scsi_get_lba(scsi_cmnd) & 0xFFFFFFFF;
22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2219cc405acee244310cc87ddc5e3f4bc61342ec8161Steffen Maier	if (zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction))
2220cc405acee244310cc87ddc5e3f4bc61342ec8161Steffen Maier		goto failed_scsi_cmnd;
2221ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
22224318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
22232443c8b23aea83d529868030e28f45a6fa6553b2Christof Schmitt	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2225ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	if (scsi_prot_sg_count(scsi_cmnd)) {
2226ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
2227ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck				       scsi_prot_sg_count(scsi_cmnd));
222886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
222986a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig						 scsi_prot_sglist(scsi_cmnd));
223086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		if (retval)
223186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig			goto failed_scsi_cmnd;
223286a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		io->prot_data_length = zfcp_qdio_real_bytes(
2233ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck						scsi_prot_sglist(scsi_cmnd));
2234ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	}
2235ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
223686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
223786a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig					 scsi_sglist(scsi_cmnd));
223886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (unlikely(retval))
2239c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_scsi_cmnd;
22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2241ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
224286a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (zfcp_adapter_multi_buffer_active(adapter))
224386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		zfcp_qdio_set_scount(qdio, &req->qdio_req);
2244ef3eb71d8ba4fd9d48c5f9310bc9d90ca00323b4Felix Beck
2245c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
2246c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (unlikely(retval))
2247c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto failed_scsi_cmnd;
22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2249c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	goto out;
22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligfailed_scsi_cmnd:
2252c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
2253c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	scsi_cmnd->host_scribble = NULL;
2254c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
2255e55f87531c2c1eb071a296df7eb67f83d5f0b5dfChristof Schmitt	spin_unlock_irqrestore(&qdio->req_q_lock, flags);
2256c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return retval;
22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2259c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmittstatic void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
2260c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt{
2261c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	struct fcp_resp_with_ext *fcp_rsp;
2262c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	struct fcp_resp_rsp_info *rsp_info;
2263c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2264c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	zfcp_fsf_fcp_handler_common(req);
2265c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2266c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
2267c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
2268c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
2269c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
2270c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
2271c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
2272c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt}
2273c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt
22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
2275b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
2276b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt * @scmnd: SCSI command to send the task management command for
2277c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @tm_flags: unsigned byte for task management flags
2278c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: on success pointer to struct fsf_req, NULL otherwise
22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2280b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmittstruct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
2281b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt					    u8 tm_flags)
22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2283c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
22844318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	struct fcp_cmnd *fcp_cmnd;
2285b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
2286b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2288b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
2289c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		       ZFCP_STATUS_COMMON_UNBLOCKED)))
2290c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return NULL;
22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
229244a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
22936b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
2294c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
229509a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2296564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
22973ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber				  SBAL_SFLAGS0_TYPE_WRITE,
2298564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig				  qdio->adapter->pool.scsi_req);
229909a46c6e34ba152169b7400d266d2efb4c391a43Swen Schillig
2300633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	if (IS_ERR(req)) {
2301633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig		req = NULL;
2302c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2303633528c304f20b5c2e3e04d48f620548ce08b12eSwen Schillig	}
23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2305b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->data = scmnd;
2306c61b536c97f225a74cf430716fdb243dfafe9d48Christof Schmitt	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
2307b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
2308b62a8d9b45b971a67a0f8413338c230e3117dff5Christof Schmitt	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
2309c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
2310c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
23114318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
2312c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
23131674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23154318e08c84e4916ac463002ffb7f9901ddb3c385Christof Schmitt	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
23162443c8b23aea83d529868030e28f45a6fa6553b2Christof Schmitt	zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags);
23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2318c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
2319c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!zfcp_fsf_req_send(req))
2320c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2322c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_req_free(req);
2323c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req = NULL;
2324c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
232544a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
2326c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return req;
2327c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig}
23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2329c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstatic void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
2330c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig{
23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2333c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig/**
2334c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * zfcp_fsf_control_file - control file upload/download
2335c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @adapter: pointer to struct zfcp_adapter
2336c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * @fsf_cfdc: pointer to struct zfcp_fsf_cfdc
2337c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig * Returns: on success pointer to struct zfcp_fsf_req, NULL otherwise
23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2339c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligstruct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
2340c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig					   struct zfcp_fsf_cfdc *fsf_cfdc)
23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2342564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_qdio *qdio = adapter->qdio;
2343c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct zfcp_fsf_req *req = NULL;
2344c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	struct fsf_qtcb_bottom_support *bottom;
234586a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	int retval = -EIO;
23463ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber	u8 direction;
2347c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2348c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
2349c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return ERR_PTR(-EOPNOTSUPP);
2350c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig
2351c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	switch (fsf_cfdc->command) {
2352c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
23533ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber		direction = SBAL_SFLAGS0_TYPE_WRITE;
2354c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2355c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	case FSF_QTCB_UPLOAD_CONTROL_FILE:
23563ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber		direction = SBAL_SFLAGS0_TYPE_READ;
2357c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		break;
2358c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	default:
2359c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return ERR_PTR(-EINVAL);
2360c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
236244a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_lock_irq(&qdio->req_q_lock);
23636b9e1520094a8aa68009c265eb694e0be9f5be3fChristof Schmitt	if (zfcp_qdio_sbal_get(qdio))
2364c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23661674b4054744c2cfd6573e43eca45d86ff581d0eChristof Schmitt	req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, direction, NULL);
2367025270f0eaa2def673747ed6f77cca41f694f354Hirofumi Nakagawa	if (IS_ERR(req)) {
2368c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		retval = -EPERM;
2369c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2370c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2372c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	req->handler = zfcp_fsf_control_file_handler;
23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2374c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom = &req->qtcb->bottom.support;
2375c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
2376c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	bottom->option = fsf_cfdc->option;
23778a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
237886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);
237901b047599ade30051bf6c14fbe64181d1fec3dfaSwen Schillig
238086a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (retval ||
238186a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		(zfcp_qdio_real_bytes(fsf_cfdc->sg) != ZFCP_CFDC_MAX_SIZE)) {
2382c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		zfcp_fsf_req_free(req);
238386a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		retval = -EIO;
2384c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		goto out;
2385c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	}
238686a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
238786a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig	if (zfcp_adapter_multi_buffer_active(adapter))
238886a9668a8d29ea711613e1cb37efa68e7c4db564Swen Schillig		zfcp_qdio_set_scount(qdio, &req->qdio_req);
23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2390c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
2391c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	retval = zfcp_fsf_req_send(req);
2392c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schilligout:
239344a24cb3731495336d77f3a955a7004997270dfdChristof Schmitt	spin_unlock_irq(&qdio->req_q_lock);
23948a36e4532ea10471f0a8605207d071361d7be2c3Maxim Shchetynin
2395c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	if (!retval) {
2396058b8647892ed49ba6a0d2c0966a72e20e2e69ffSwen Schillig		wait_for_completion(&req->completion);
2397c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig		return req;
23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2399c41f8cbddd4e0e72951e0575165dea8ea26f1c4bSwen Schillig	return ERR_PTR(retval);
24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2401bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2402bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig/**
2403bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO
2404bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @adapter: pointer to struct zfcp_adapter
2405bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig * @sbal_idx: response queue index of SBAL to be processed
2406bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig */
2407564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schilligvoid zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2408bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig{
2409564e1c86c810f9ccfe4300afa402815e3db4886dSwen Schillig	struct zfcp_adapter *adapter = qdio->adapter;
2410706eca49a044a1ea89352dcc4b96ffc1631b2cb5Swen Schillig	struct qdio_buffer *sbal = qdio->res_q[sbal_idx];
2411bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct qdio_buffer_element *sbale;
2412bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	struct zfcp_fsf_req *fsf_req;
2413b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt	unsigned long req_id;
2414bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	int idx;
2415bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2416bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
2417bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2418bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		sbale = &sbal->element[idx];
2419bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		req_id = (unsigned long) sbale->addr;
2420b6bd2fb92a7bb9f1f3feecd9945c21e6c227dd51Christof Schmitt		fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id);
2421bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
2422339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt		if (!fsf_req) {
2423bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			/*
2424bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 * Unknown request means that we have potentially memory
2425bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 * corruption and must stop the machine immediately.
2426bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			 */
2427339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt			zfcp_qdio_siosl(adapter);
2428bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			panic("error: unknown req_id (%lx) on adapter %s.\n",
2429bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			      req_id, dev_name(&adapter->ccw_device->dev));
2430339f4f4eab80caa6cf0d39fb057ad6ddb84ba91eChristof Schmitt		}
2431bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
243234c2b712992540ca436e97432ffc57c84c8f8c18Christof Schmitt		fsf_req->qdio_req.sbal_response = sbal_idx;
2433bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig		zfcp_fsf_req_complete(fsf_req);
2434bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig
24353ec90878bade9280dee87c9e27d759f1cee07e70Jan Glauber		if (likely(sbale->eflags & SBAL_EFLAGS_LAST_ENTRY))
2436bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig			break;
2437bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig	}
2438bd63eaf4b8d783e6033930e377e516169abcadc4Swen Schillig}
2439a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig
2440a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schilligstruct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *qdio,
2441a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig				      struct qdio_buffer *sbal)
2442a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig{
2443a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig	struct qdio_buffer_element *sbale = &sbal->element[0];
2444a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig	u64 req_id = (unsigned long) sbale->addr;
2445a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig
2446a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig	return zfcp_reqlist_find(qdio->adapter->req_list, req_id);
2447a54ca0f62f953898b05549391ac2a8a4dad6482bSwen Schillig}
2448