zfcp_fsf.c 71.4 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
C
Christof Schmitt 已提交
2
 * zfcp device driver
L
Linus Torvalds 已提交
3
 *
C
Christof Schmitt 已提交
4
 * Implementation of FSF commands.
L
Linus Torvalds 已提交
5
 *
C
Christof Schmitt 已提交
6
 * Copyright IBM Corporation 2002, 2008
L
Linus Torvalds 已提交
7 8
 */

9 10 11
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

S
Stefan Raspl 已提交
12
#include <linux/blktrace_api.h>
L
Linus Torvalds 已提交
13 14
#include "zfcp_ext.h"

15 16 17
#define ZFCP_REQ_AUTO_CLEANUP	0x00000002
#define ZFCP_REQ_NO_QTCB	0x00000008

18 19 20
static void zfcp_fsf_request_timeout_handler(unsigned long data)
{
	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
21 22
	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
				"fsrth_1", NULL);
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
}

static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req,
				 unsigned long timeout)
{
	fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
	fsf_req->timer.data = (unsigned long) fsf_req->adapter;
	fsf_req->timer.expires = jiffies + timeout;
	add_timer(&fsf_req->timer);
}

static void zfcp_fsf_start_erp_timer(struct zfcp_fsf_req *fsf_req)
{
	BUG_ON(!fsf_req->erp_action);
	fsf_req->timer.function = zfcp_erp_timeout_handler;
	fsf_req->timer.data = (unsigned long) fsf_req->erp_action;
	fsf_req->timer.expires = jiffies + 30 * HZ;
	add_timer(&fsf_req->timer);
}

L
Linus Torvalds 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/* association between FSF command and FSF QTCB type */
static u32 fsf_qtcb_type[] = {
	[FSF_QTCB_FCP_CMND] =             FSF_IO_COMMAND,
	[FSF_QTCB_ABORT_FCP_CMND] =       FSF_SUPPORT_COMMAND,
	[FSF_QTCB_OPEN_PORT_WITH_DID] =   FSF_SUPPORT_COMMAND,
	[FSF_QTCB_OPEN_LUN] =             FSF_SUPPORT_COMMAND,
	[FSF_QTCB_CLOSE_LUN] =            FSF_SUPPORT_COMMAND,
	[FSF_QTCB_CLOSE_PORT] =           FSF_SUPPORT_COMMAND,
	[FSF_QTCB_CLOSE_PHYSICAL_PORT] =  FSF_SUPPORT_COMMAND,
	[FSF_QTCB_SEND_ELS] =             FSF_SUPPORT_COMMAND,
	[FSF_QTCB_SEND_GENERIC] =         FSF_SUPPORT_COMMAND,
	[FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND,
	[FSF_QTCB_EXCHANGE_PORT_DATA] =   FSF_PORT_COMMAND,
	[FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND,
	[FSF_QTCB_UPLOAD_CONTROL_FILE] =  FSF_SUPPORT_COMMAND
};

C
Christof Schmitt 已提交
60 61
static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
{
S
Swen Schillig 已提交
62
	u16 subtable = table >> 16;
C
Christof Schmitt 已提交
63
	u16 rule = table & 0xffff;
64
	const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
C
Christof Schmitt 已提交
65

66
	if (subtable && subtable < ARRAY_SIZE(act_type))
C
Christof Schmitt 已提交
67
		dev_warn(&adapter->ccw_device->dev,
68 69
			 "Access denied according to ACT rule type %s, "
			 "rule %d\n", act_type[subtable], rule);
C
Christof Schmitt 已提交
70 71 72 73 74 75 76
}

static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
					struct zfcp_port *port)
{
	struct fsf_qtcb_header *header = &req->qtcb->header;
	dev_warn(&req->adapter->ccw_device->dev,
77
		 "Access denied to port 0x%016Lx\n",
78
		 (unsigned long long)port->wwpn);
C
Christof Schmitt 已提交
79 80
	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
81
	zfcp_erp_port_access_denied(port, "fspad_1", req);
C
Christof Schmitt 已提交
82 83 84 85 86 87 88 89
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}

static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
					struct zfcp_unit *unit)
{
	struct fsf_qtcb_header *header = &req->qtcb->header;
	dev_warn(&req->adapter->ccw_device->dev,
90
		 "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
91 92
		 (unsigned long long)unit->fcp_lun,
		 (unsigned long long)unit->port->wwpn);
C
Christof Schmitt 已提交
93 94
	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
95
	zfcp_erp_unit_access_denied(unit, "fsuad_1", req);
C
Christof Schmitt 已提交
96 97 98 99 100
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}

static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
{
101 102
	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
		"operational because of an unsupported FC class\n");
103
	zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1", req);
C
Christof Schmitt 已提交
104 105 106
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}

S
Swen Schillig 已提交
107 108 109
/**
 * zfcp_fsf_req_free - free memory used by fsf request
 * @fsf_req: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
110
 */
S
Swen Schillig 已提交
111
void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
112
{
S
Swen Schillig 已提交
113 114
	if (likely(req->pool)) {
		mempool_free(req, req->pool);
115 116 117
		return;
	}

S
Swen Schillig 已提交
118 119
	if (req->qtcb) {
		kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, req);
120 121
		return;
	}
L
Linus Torvalds 已提交
122 123
}

S
Swen Schillig 已提交
124 125 126 127
/**
 * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
 * @adapter: pointer to struct zfcp_adapter
 *
128 129 130 131
 * Never ever call this without shutting down the adapter first.
 * Otherwise the adapter would continue using and corrupting s390 storage.
 * Included BUG_ON() call to ensure this is done.
 * ERP is supposed to be the only user of this function.
L
Linus Torvalds 已提交
132
 */
133
void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
134
{
S
Swen Schillig 已提交
135
	struct zfcp_fsf_req *req, *tmp;
136
	unsigned long flags;
137
	LIST_HEAD(remove_queue);
138
	unsigned int i;
139

S
Swen Schillig 已提交
140
	BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
141
	spin_lock_irqsave(&adapter->req_list_lock, flags);
142
	for (i = 0; i < REQUEST_LIST_SIZE; i++)
143
		list_splice_init(&adapter->req_list[i], &remove_queue);
144 145
	spin_unlock_irqrestore(&adapter->req_list_lock, flags);

S
Swen Schillig 已提交
146 147 148 149
	list_for_each_entry_safe(req, tmp, &remove_queue, list) {
		list_del(&req->list);
		req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
		zfcp_fsf_req_complete(req);
L
Linus Torvalds 已提交
150 151 152
	}
}

S
Swen Schillig 已提交
153
static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
154
{
S
Swen Schillig 已提交
155 156 157 158 159
	struct fsf_status_read_buffer *sr_buf = req->data;
	struct zfcp_adapter *adapter = req->adapter;
	struct zfcp_port *port;
	int d_id = sr_buf->d_id & ZFCP_DID_MASK;
	unsigned long flags;
L
Linus Torvalds 已提交
160

S
Swen Schillig 已提交
161 162 163 164
	read_lock_irqsave(&zfcp_data.config_lock, flags);
	list_for_each_entry(port, &adapter->port_list_head, list)
		if (port->d_id == d_id) {
			read_unlock_irqrestore(&zfcp_data.config_lock, flags);
165
			zfcp_erp_port_reopen(port, 0, "fssrpc1", req);
S
Swen Schillig 已提交
166 167 168
			return;
		}
	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
L
Linus Torvalds 已提交
169 170
}

171
static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
S
Swen Schillig 已提交
172
					 struct fsf_link_down_info *link_down)
173
{
S
Swen Schillig 已提交
174
	struct zfcp_adapter *adapter = req->adapter;
175

S
Swen Schillig 已提交
176
	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
177 178 179 180
		return;

	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);

S
Swen Schillig 已提交
181
	if (!link_down)
182
		goto out;
183

184 185
	switch (link_down->error_code) {
	case FSF_PSQ_LINK_NO_LIGHT:
S
Swen Schillig 已提交
186
		dev_warn(&req->adapter->ccw_device->dev,
187 188
			 "There is no light signal from the local "
			 "fibre channel cable\n");
189 190
		break;
	case FSF_PSQ_LINK_WRAP_PLUG:
S
Swen Schillig 已提交
191
		dev_warn(&req->adapter->ccw_device->dev,
192 193
			 "There is a wrap plug instead of a fibre "
			 "channel cable\n");
194 195
		break;
	case FSF_PSQ_LINK_NO_FCP:
S
Swen Schillig 已提交
196
		dev_warn(&req->adapter->ccw_device->dev,
197 198
			 "The adjacent fibre channel node does not "
			 "support FCP\n");
199 200
		break;
	case FSF_PSQ_LINK_FIRMWARE_UPDATE:
S
Swen Schillig 已提交
201
		dev_warn(&req->adapter->ccw_device->dev,
202 203
			 "The FCP device is suspended because of a "
			 "firmware update\n");
C
Christof Schmitt 已提交
204
		break;
205
	case FSF_PSQ_LINK_INVALID_WWPN:
S
Swen Schillig 已提交
206
		dev_warn(&req->adapter->ccw_device->dev,
207 208
			 "The FCP device detected a WWPN that is "
			 "duplicate or not valid\n");
209 210
		break;
	case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
S
Swen Schillig 已提交
211
		dev_warn(&req->adapter->ccw_device->dev,
212
			 "The fibre channel fabric does not support NPIV\n");
213 214
		break;
	case FSF_PSQ_LINK_NO_FCP_RESOURCES:
S
Swen Schillig 已提交
215
		dev_warn(&req->adapter->ccw_device->dev,
216
			 "The FCP adapter cannot support more NPIV ports\n");
217 218
		break;
	case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
S
Swen Schillig 已提交
219
		dev_warn(&req->adapter->ccw_device->dev,
220 221
			 "The adjacent switch cannot support "
			 "more NPIV ports\n");
222 223
		break;
	case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
S
Swen Schillig 已提交
224
		dev_warn(&req->adapter->ccw_device->dev,
225 226
			 "The FCP adapter could not log in to the "
			 "fibre channel fabric\n");
227 228
		break;
	case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
S
Swen Schillig 已提交
229
		dev_warn(&req->adapter->ccw_device->dev,
230 231
			 "The WWPN assignment file on the FCP adapter "
			 "has been damaged\n");
232 233
		break;
	case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
S
Swen Schillig 已提交
234
		dev_warn(&req->adapter->ccw_device->dev,
235 236
			 "The mode table on the FCP adapter "
			 "has been damaged\n");
237 238
		break;
	case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
S
Swen Schillig 已提交
239
		dev_warn(&req->adapter->ccw_device->dev,
240 241
			 "All NPIV ports on the FCP adapter have "
			 "been assigned\n");
242 243
		break;
	default:
S
Swen Schillig 已提交
244
		dev_warn(&req->adapter->ccw_device->dev,
245 246
			 "The link between the FCP adapter and "
			 "the FC fabric is down\n");
247
	}
S
Swen Schillig 已提交
248 249
out:
	zfcp_erp_adapter_failed(adapter, id, req);
250 251
}

S
Swen Schillig 已提交
252
static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
253
{
S
Swen Schillig 已提交
254 255 256
	struct fsf_status_read_buffer *sr_buf = req->data;
	struct fsf_link_down_info *ldi =
		(struct fsf_link_down_info *) &sr_buf->payload;
L
Linus Torvalds 已提交
257

S
Swen Schillig 已提交
258 259
	switch (sr_buf->status_subtype) {
	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
260
		zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi);
L
Linus Torvalds 已提交
261
		break;
S
Swen Schillig 已提交
262
	case FSF_STATUS_READ_SUB_FDISC_FAILED:
263
		zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi);
L
Linus Torvalds 已提交
264
		break;
S
Swen Schillig 已提交
265
	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
266
		zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL);
S
Swen Schillig 已提交
267 268
	};
}
L
Linus Torvalds 已提交
269

S
Swen Schillig 已提交
270 271 272 273
static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
	struct fsf_status_read_buffer *sr_buf = req->data;
L
Linus Torvalds 已提交
274

S
Swen Schillig 已提交
275 276 277 278 279 280
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
		zfcp_hba_dbf_event_fsf_unsol("dism", adapter, sr_buf);
		mempool_free(sr_buf, adapter->pool.data_status_read);
		zfcp_fsf_req_free(req);
		return;
	}
L
Linus Torvalds 已提交
281

S
Swen Schillig 已提交
282
	zfcp_hba_dbf_event_fsf_unsol("read", adapter, sr_buf);
L
Linus Torvalds 已提交
283

S
Swen Schillig 已提交
284 285 286
	switch (sr_buf->status_type) {
	case FSF_STATUS_READ_PORT_CLOSED:
		zfcp_fsf_status_read_port_closed(req);
L
Linus Torvalds 已提交
287
		break;
S
Swen Schillig 已提交
288 289
	case FSF_STATUS_READ_INCOMING_ELS:
		zfcp_fc_incoming_els(req);
L
Linus Torvalds 已提交
290
		break;
S
Swen Schillig 已提交
291
	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
L
Linus Torvalds 已提交
292
		break;
S
Swen Schillig 已提交
293
	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
294 295 296
		dev_warn(&adapter->ccw_device->dev,
			 "The error threshold for checksum statistics "
			 "has been exceeded\n");
297
		zfcp_hba_dbf_event_berr(adapter, req);
L
Linus Torvalds 已提交
298
		break;
S
Swen Schillig 已提交
299 300 301 302 303
	case FSF_STATUS_READ_LINK_DOWN:
		zfcp_fsf_status_read_link_down(req);
		break;
	case FSF_STATUS_READ_LINK_UP:
		dev_info(&adapter->ccw_device->dev,
304
			 "The local link has been restored\n");
S
Swen Schillig 已提交
305
		/* All ports should be marked as ready to run again */
306
		zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL,
S
Swen Schillig 已提交
307 308 309 310 311
					       ZFCP_STATUS_COMMON_RUNNING,
					       ZFCP_SET);
		zfcp_erp_adapter_reopen(adapter,
					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
					ZFCP_STATUS_COMMON_ERP_FAILED,
312
					"fssrh_2", req);
S
Swen Schillig 已提交
313 314 315
		break;
	case FSF_STATUS_READ_NOTIFICATION_LOST:
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
316 317
			zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
							req);
S
Swen Schillig 已提交
318 319 320 321
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
			schedule_work(&adapter->scan_work);
		break;
	case FSF_STATUS_READ_CFDC_UPDATED:
322
		zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
S
Swen Schillig 已提交
323 324 325
		break;
	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
		adapter->adapter_features = sr_buf->payload.word[0];
L
Linus Torvalds 已提交
326 327 328
		break;
	}

S
Swen Schillig 已提交
329 330
	mempool_free(sr_buf, adapter->pool.data_status_read);
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
331

S
Swen Schillig 已提交
332
	atomic_inc(&adapter->stat_miss);
333
	queue_work(zfcp_data.work_queue, &adapter->stat_work);
S
Swen Schillig 已提交
334
}
L
Linus Torvalds 已提交
335

S
Swen Schillig 已提交
336 337 338 339 340 341 342 343 344 345 346 347 348
static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
{
	switch (req->qtcb->header.fsf_status_qual.word[0]) {
	case FSF_SQ_FCP_RSP_AVAILABLE:
	case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
	case FSF_SQ_NO_RETRY_POSSIBLE:
	case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
		return;
	case FSF_SQ_COMMAND_ABORTED:
		req->status |= ZFCP_STATUS_FSFREQ_ABORTED;
		break;
	case FSF_SQ_NO_RECOM:
		dev_err(&req->adapter->ccw_device->dev,
349 350
			"The FCP adapter reported a problem "
			"that cannot be recovered\n");
351
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req);
S
Swen Schillig 已提交
352 353 354 355
		break;
	}
	/* all non-return stats set FSFREQ_ERROR*/
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
356 357
}

S
Swen Schillig 已提交
358
static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
359
{
S
Swen Schillig 已提交
360 361
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
		return;
L
Linus Torvalds 已提交
362

S
Swen Schillig 已提交
363 364 365
	switch (req->qtcb->header.fsf_status) {
	case FSF_UNKNOWN_COMMAND:
		dev_err(&req->adapter->ccw_device->dev,
366
			"The FCP adapter does not recognize the command 0x%x\n",
S
Swen Schillig 已提交
367
			req->qtcb->header.fsf_command);
368
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1", req);
S
Swen Schillig 已提交
369 370 371 372 373 374 375
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		zfcp_fsf_fsfstatus_qual_eval(req);
		break;
	}
}
L
Linus Torvalds 已提交
376

S
Swen Schillig 已提交
377 378 379 380 381
static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
	struct fsf_qtcb *qtcb = req->qtcb;
	union fsf_prot_status_qual *psq = &qtcb->prefix.prot_status_qual;
L
Linus Torvalds 已提交
382

S
Swen Schillig 已提交
383
	zfcp_hba_dbf_event_fsf_response(req);
L
Linus Torvalds 已提交
384

S
Swen Schillig 已提交
385 386 387 388 389
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */
		return;
	}
L
Linus Torvalds 已提交
390

S
Swen Schillig 已提交
391 392 393 394 395 396
	switch (qtcb->prefix.prot_status) {
	case FSF_PROT_GOOD:
	case FSF_PROT_FSF_STATUS_PRESENTED:
		return;
	case FSF_PROT_QTCB_VERSION_ERROR:
		dev_err(&adapter->ccw_device->dev,
397 398 399
			"QTCB version 0x%x not supported by FCP adapter "
			"(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION,
			psq->word[0], psq->word[1]);
400
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1", req);
S
Swen Schillig 已提交
401 402 403
		break;
	case FSF_PROT_ERROR_STATE:
	case FSF_PROT_SEQ_NUMB_ERROR:
404
		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req);
S
Swen Schillig 已提交
405 406 407 408
		req->status |= ZFCP_STATUS_FSFREQ_RETRY;
		break;
	case FSF_PROT_UNSUPP_QTCB_TYPE:
		dev_err(&adapter->ccw_device->dev,
409
			"The QTCB type is not supported by the FCP adapter\n");
410
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3", req);
S
Swen Schillig 已提交
411 412 413 414 415 416 417
		break;
	case FSF_PROT_HOST_CONNECTION_INITIALIZING:
		atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
				&adapter->status);
		break;
	case FSF_PROT_DUPLICATE_REQUEST_ID:
		dev_err(&adapter->ccw_device->dev,
418
			"0x%Lx is an ambiguous request identifier\n",
S
Swen Schillig 已提交
419
			(unsigned long long)qtcb->bottom.support.req_handle);
420
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
S
Swen Schillig 已提交
421 422
		break;
	case FSF_PROT_LINK_DOWN:
423 424
		zfcp_fsf_link_down_info_eval(req, "fspse_5",
					     &psq->link_down_info);
S
Swen Schillig 已提交
425
		/* FIXME: reopening adapter now? better wait for link up */
426
		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
S
Swen Schillig 已提交
427 428 429
		break;
	case FSF_PROT_REEST_QUEUE:
		/* All ports should be marked as ready to run again */
430
		zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL,
S
Swen Schillig 已提交
431 432 433 434
					       ZFCP_STATUS_COMMON_RUNNING,
					       ZFCP_SET);
		zfcp_erp_adapter_reopen(adapter,
					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
435 436
					ZFCP_STATUS_COMMON_ERP_FAILED,
					"fspse_8", req);
S
Swen Schillig 已提交
437 438 439
		break;
	default:
		dev_err(&adapter->ccw_device->dev,
440
			"0x%x is not a valid transfer protocol status\n",
S
Swen Schillig 已提交
441
			qtcb->prefix.prot_status);
442
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req);
S
Swen Schillig 已提交
443 444
	}
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
445 446
}

S
Swen Schillig 已提交
447 448 449 450 451 452 453 454 455 456
/**
 * zfcp_fsf_req_complete - process completion of a FSF request
 * @fsf_req: The FSF request that has been completed.
 *
 * When a request has been completed either from the FCP adapter,
 * or it has been dismissed due to a queue shutdown, this function
 * is called to process the completion status and trigger further
 * events related to the FSF request.
 */
void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
457
{
S
Swen Schillig 已提交
458 459 460 461
	if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
		zfcp_fsf_status_read_handler(req);
		return;
	}
L
Linus Torvalds 已提交
462

S
Swen Schillig 已提交
463 464 465 466
	del_timer(&req->timer);
	zfcp_fsf_protstatus_eval(req);
	zfcp_fsf_fsfstatus_eval(req);
	req->handler(req);
L
Linus Torvalds 已提交
467

S
Swen Schillig 已提交
468
	if (req->erp_action)
469
		zfcp_erp_notify(req->erp_action, 0);
S
Swen Schillig 已提交
470
	req->status |= ZFCP_STATUS_FSFREQ_COMPLETED;
L
Linus Torvalds 已提交
471

S
Swen Schillig 已提交
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
		zfcp_fsf_req_free(req);
	else
	/* notify initiator waiting for the requests completion */
	/*
	 * FIXME: Race! We must not access fsf_req here as it might have been
	 * cleaned up already due to the set ZFCP_STATUS_FSFREQ_COMPLETED
	 * flag. It's an improbable case. But, we have the same paranoia for
	 * the cleanup flag already.
	 * Might better be handled using complete()?
	 * (setting the flag and doing wakeup ought to be atomic
	 *  with regard to checking the flag as long as waitqueue is
	 *  part of the to be released structure)
	 */
		wake_up(&req->completion_wq);
}
L
Linus Torvalds 已提交
488

S
Swen Schillig 已提交
489 490 491 492 493
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
{
	struct fsf_qtcb_bottom_config *bottom;
	struct zfcp_adapter *adapter = req->adapter;
	struct Scsi_Host *shost = adapter->scsi_host;
L
Linus Torvalds 已提交
494

S
Swen Schillig 已提交
495
	bottom = &req->qtcb->bottom.config;
L
Linus Torvalds 已提交
496

S
Swen Schillig 已提交
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));

	fc_host_node_name(shost) = bottom->nport_serv_param.wwnn;
	fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
	fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
	fc_host_speed(shost) = bottom->fc_link_speed;
	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;

	adapter->hydra_version = bottom->adapter_type;
	adapter->timer_ticks = bottom->timer_interval;

	if (fc_host_permanent_port_name(shost) == -1)
		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);

	switch (bottom->fc_topology) {
	case FSF_TOPO_P2P:
		adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
		adapter->peer_wwpn = bottom->plogi_payload.wwpn;
		adapter->peer_wwnn = bottom->plogi_payload.wwnn;
		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
		break;
	case FSF_TOPO_FABRIC:
		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
		break;
	case FSF_TOPO_AL:
		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
	default:
		dev_err(&adapter->ccw_device->dev,
526 527
			"Unknown or unsupported arbitrated loop "
			"fibre channel topology detected\n");
528
		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req);
S
Swen Schillig 已提交
529
		return -EIO;
L
Linus Torvalds 已提交
530
	}
S
Swen Schillig 已提交
531

L
Linus Torvalds 已提交
532 533 534
	return 0;
}

S
Swen Schillig 已提交
535
static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
C
Christof Schmitt 已提交
536 537
{
	struct zfcp_adapter *adapter = req->adapter;
S
Swen Schillig 已提交
538 539 540
	struct fsf_qtcb *qtcb = req->qtcb;
	struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config;
	struct Scsi_Host *shost = adapter->scsi_host;
C
Christof Schmitt 已提交
541

S
Swen Schillig 已提交
542 543
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;
L
Linus Torvalds 已提交
544

S
Swen Schillig 已提交
545 546 547 548 549 550
	adapter->fsf_lic_version = bottom->lic_version;
	adapter->adapter_features = bottom->adapter_features;
	adapter->connection_features = bottom->connection_features;
	adapter->peer_wwpn = 0;
	adapter->peer_wwnn = 0;
	adapter->peer_d_id = 0;
551

S
Swen Schillig 已提交
552 553 554 555
	switch (qtcb->header.fsf_status) {
	case FSF_GOOD:
		if (zfcp_fsf_exchange_config_evaluate(req))
			return;
L
Linus Torvalds 已提交
556

S
Swen Schillig 已提交
557 558
		if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
			dev_err(&adapter->ccw_device->dev,
559 560 561
				"FCP adapter maximum QTCB size (%d bytes) "
				"is too small\n",
				bottom->max_qtcb_size);
562
			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1", req);
S
Swen Schillig 已提交
563 564 565 566
			return;
		}
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
				&adapter->status);
L
Linus Torvalds 已提交
567
		break;
S
Swen Schillig 已提交
568 569 570 571 572 573 574
	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
		fc_host_node_name(shost) = 0;
		fc_host_port_name(shost) = 0;
		fc_host_port_id(shost) = 0;
		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
		fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
		adapter->hydra_version = 0;
L
Linus Torvalds 已提交
575

S
Swen Schillig 已提交
576 577
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
				&adapter->status);
L
Linus Torvalds 已提交
578

579
		zfcp_fsf_link_down_info_eval(req, "fsecdh2",
S
Swen Schillig 已提交
580
			&qtcb->header.fsf_status_qual.link_down_info);
L
Linus Torvalds 已提交
581
		break;
S
Swen Schillig 已提交
582
	default:
583
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req);
S
Swen Schillig 已提交
584 585
		return;
	}
L
Linus Torvalds 已提交
586

S
Swen Schillig 已提交
587 588 589 590 591 592 593
	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
		adapter->hardware_version = bottom->hardware_version;
		memcpy(fc_host_serial_number(shost), bottom->serial_number,
		       min(FC_SERIAL_NUMBER_SIZE, 17));
		EBCASC(fc_host_serial_number(shost),
		       min(FC_SERIAL_NUMBER_SIZE, 17));
	}
L
Linus Torvalds 已提交
594

S
Swen Schillig 已提交
595 596
	if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
		dev_err(&adapter->ccw_device->dev,
597 598
			"The FCP adapter only supports newer "
			"control block versions\n");
599
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4", req);
S
Swen Schillig 已提交
600 601 602 603
		return;
	}
	if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
		dev_err(&adapter->ccw_device->dev,
604 605
			"The FCP adapter only supports older "
			"control block versions\n");
606
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5", req);
S
Swen Schillig 已提交
607 608
	}
}
L
Linus Torvalds 已提交
609

S
Swen Schillig 已提交
610 611 612 613 614
static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
	struct fsf_qtcb_bottom_port *bottom = &req->qtcb->bottom.port;
	struct Scsi_Host *shost = adapter->scsi_host;
L
Linus Torvalds 已提交
615

S
Swen Schillig 已提交
616 617
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));
618

S
Swen Schillig 已提交
619 620 621 622 623 624 625
	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
		fc_host_permanent_port_name(shost) = bottom->wwpn;
	else
		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
	fc_host_supported_speeds(shost) = bottom->supported_speed;
}
L
Linus Torvalds 已提交
626

S
Swen Schillig 已提交
627 628 629 630 631 632 633 634 635 636 637 638 639
static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
{
	struct fsf_qtcb *qtcb = req->qtcb;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;

	switch (qtcb->header.fsf_status) {
	case FSF_GOOD:
		zfcp_fsf_exchange_port_evaluate(req);
		break;
	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
		zfcp_fsf_exchange_port_evaluate(req);
640
		zfcp_fsf_link_down_info_eval(req, "fsepdh1",
S
Swen Schillig 已提交
641
			&qtcb->header.fsf_status_qual.link_down_info);
642
		break;
L
Linus Torvalds 已提交
643
	}
S
Swen Schillig 已提交
644
}
645

S
Swen Schillig 已提交
646
static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
647 648
	__releases(&adapter->req_q_lock)
	__acquires(&adapter->req_q_lock)
S
Swen Schillig 已提交
649
{
650
	struct zfcp_qdio_queue *req_q = &adapter->req_q;
S
Swen Schillig 已提交
651 652
	long ret;

653 654 655 656 657 658
	if (atomic_read(&req_q->count) <= -REQUEST_LIST_SIZE)
		return -EIO;
	if (atomic_read(&req_q->count) > 0)
		return 0;

	atomic_dec(&req_q->count);
659
	spin_unlock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
660
	ret = wait_event_interruptible_timeout(adapter->request_wq,
661 662 663 664 665
					atomic_read(&req_q->count) >= 0,
					5 * HZ);
	spin_lock_bh(&adapter->req_q_lock);
	atomic_inc(&req_q->count);

S
Swen Schillig 已提交
666 667
	if (ret > 0)
		return 0;
668 669
	if (!ret)
		atomic_inc(&adapter->qdio_outb_full);
S
Swen Schillig 已提交
670 671 672 673 674 675 676 677 678 679
	return -EIO;
}

static struct zfcp_fsf_req *zfcp_fsf_alloc_noqtcb(mempool_t *pool)
{
	struct zfcp_fsf_req *req;
	req = mempool_alloc(pool, GFP_ATOMIC);
	if (!req)
		return NULL;
	memset(req, 0, sizeof(*req));
680
	req->pool = pool;
S
Swen Schillig 已提交
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
	return req;
}

static struct zfcp_fsf_req *zfcp_fsf_alloc_qtcb(mempool_t *pool)
{
	struct zfcp_fsf_req_qtcb *qtcb;

	if (likely(pool))
		qtcb = mempool_alloc(pool, GFP_ATOMIC);
	else
		qtcb = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache,
					GFP_ATOMIC);
	if (unlikely(!qtcb))
		return NULL;

	memset(qtcb, 0, sizeof(*qtcb));
	qtcb->fsf_req.qtcb = &qtcb->qtcb;
	qtcb->fsf_req.pool = pool;

	return &qtcb->fsf_req;
}

static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
						u32 fsf_cmd, int req_flags,
						mempool_t *pool)
L
Linus Torvalds 已提交
706
{
707
	struct qdio_buffer_element *sbale;
L
Linus Torvalds 已提交
708

S
Swen Schillig 已提交
709 710
	struct zfcp_fsf_req *req;
	struct zfcp_qdio_queue *req_q = &adapter->req_q;
711

S
Swen Schillig 已提交
712 713 714 715
	if (req_flags & ZFCP_REQ_NO_QTCB)
		req = zfcp_fsf_alloc_noqtcb(pool);
	else
		req = zfcp_fsf_alloc_qtcb(pool);
L
Linus Torvalds 已提交
716

S
Swen Schillig 已提交
717 718
	if (unlikely(!req))
		return ERR_PTR(-EIO);
L
Linus Torvalds 已提交
719

S
Swen Schillig 已提交
720 721
	if (adapter->req_no == 0)
		adapter->req_no++;
L
Linus Torvalds 已提交
722

S
Swen Schillig 已提交
723 724 725
	INIT_LIST_HEAD(&req->list);
	init_timer(&req->timer);
	init_waitqueue_head(&req->completion_wq);
L
Linus Torvalds 已提交
726

S
Swen Schillig 已提交
727 728
	req->adapter = adapter;
	req->fsf_command = fsf_cmd;
729
	req->req_id = adapter->req_no;
S
Swen Schillig 已提交
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
	req->sbal_number = 1;
	req->sbal_first = req_q->first;
	req->sbal_last = req_q->first;
	req->sbale_curr = 1;

	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].addr = (void *) req->req_id;
	sbale[0].flags |= SBAL_FLAGS0_COMMAND;

	if (likely(req->qtcb)) {
		req->qtcb->prefix.req_seq_no = req->adapter->fsf_req_seq_no;
		req->qtcb->prefix.req_id = req->req_id;
		req->qtcb->prefix.ulp_info = 26;
		req->qtcb->prefix.qtcb_type = fsf_qtcb_type[req->fsf_command];
		req->qtcb->prefix.qtcb_version = FSF_QTCB_CURRENT_VERSION;
		req->qtcb->header.req_handle = req->req_id;
		req->qtcb->header.fsf_command = req->fsf_command;
		req->seq_no = adapter->fsf_req_seq_no;
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
		sbale[1].addr = (void *) req->qtcb;
		sbale[1].length = sizeof(struct fsf_qtcb);
	}

	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) {
		zfcp_fsf_req_free(req);
		return ERR_PTR(-EIO);
	}
757

S
Swen Schillig 已提交
758 759
	if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP))
		req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
L
Linus Torvalds 已提交
760

S
Swen Schillig 已提交
761
	return req;
L
Linus Torvalds 已提交
762 763
}

S
Swen Schillig 已提交
764 765 766
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
767
	unsigned long flags;
S
Swen Schillig 已提交
768 769 770
	int idx;

	/* put allocated FSF request into hash table */
771
	spin_lock_irqsave(&adapter->req_list_lock, flags);
S
Swen Schillig 已提交
772 773
	idx = zfcp_reqlist_hash(req->req_id);
	list_add_tail(&req->list, &adapter->req_list[idx]);
774
	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
S
Swen Schillig 已提交
775

776
	req->qdio_outb_usage = atomic_read(&adapter->req_q.count);
S
Swen Schillig 已提交
777 778 779
	req->issued = get_clock();
	if (zfcp_qdio_send(req)) {
		del_timer(&req->timer);
780 781 782 783 784
		spin_lock_irqsave(&adapter->req_list_lock, flags);
		/* lookup request again, list might have changed */
		if (zfcp_reqlist_find_safe(adapter, req))
			zfcp_reqlist_remove(adapter, req);
		spin_unlock_irqrestore(&adapter->req_list_lock, flags);
785
		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req);
S
Swen Schillig 已提交
786 787 788 789 790 791
		return -EIO;
	}

	/* Don't increase for unsolicited status */
	if (req->qtcb)
		adapter->fsf_req_seq_no++;
792
	adapter->req_no++;
S
Swen Schillig 已提交
793 794 795 796 797 798 799 800 801

	return 0;
}

/**
 * zfcp_fsf_status_read - send status read request
 * @adapter: pointer to struct zfcp_adapter
 * @req_flags: request flags
 * Returns: 0 on success, ERROR otherwise
L
Linus Torvalds 已提交
802
 */
S
Swen Schillig 已提交
803
int zfcp_fsf_status_read(struct zfcp_adapter *adapter)
L
Linus Torvalds 已提交
804
{
S
Swen Schillig 已提交
805 806
	struct zfcp_fsf_req *req;
	struct fsf_status_read_buffer *sr_buf;
807
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
808
	int retval = -EIO;
L
Linus Torvalds 已提交
809

810
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
811 812 813 814 815 816
	if (zfcp_fsf_req_sbal_get(adapter))
		goto out;

	req = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS,
				  ZFCP_REQ_NO_QTCB,
				  adapter->pool.fsf_req_status_read);
817
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
818 819
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
820 821
	}

S
Swen Schillig 已提交
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].flags |= SBAL_FLAGS0_TYPE_STATUS;
	sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
	req->sbale_curr = 2;

	sr_buf = mempool_alloc(adapter->pool.data_status_read, GFP_ATOMIC);
	if (!sr_buf) {
		retval = -ENOMEM;
		goto failed_buf;
	}
	memset(sr_buf, 0, sizeof(*sr_buf));
	req->data = sr_buf;
	sbale = zfcp_qdio_sbale_curr(req);
	sbale->addr = (void *) sr_buf;
	sbale->length = sizeof(*sr_buf);
837

S
Swen Schillig 已提交
838 839 840
	retval = zfcp_fsf_req_send(req);
	if (retval)
		goto failed_req_send;
L
Linus Torvalds 已提交
841

S
Swen Schillig 已提交
842 843 844 845 846 847 848 849
	goto out;

failed_req_send:
	mempool_free(sr_buf, adapter->pool.data_status_read);
failed_buf:
	zfcp_fsf_req_free(req);
	zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL);
out:
850
	spin_unlock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
851 852 853 854 855 856 857 858 859 860 861 862
	return retval;
}

static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_unit *unit = req->data;
	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;

	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
863
	case FSF_PORT_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
864
		if (fsq->word[0] == fsq->word[1]) {
865 866
			zfcp_erp_adapter_reopen(unit->port->adapter, 0,
						"fsafch1", req);
S
Swen Schillig 已提交
867
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
868 869 870
		}
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
871
		if (fsq->word[0] == fsq->word[1]) {
872
			zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
S
Swen Schillig 已提交
873
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
874 875 876
		}
		break;
	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
S
Swen Schillig 已提交
877
		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
L
Linus Torvalds 已提交
878 879
		break;
	case FSF_PORT_BOXED:
880
		zfcp_erp_port_boxed(unit->port, "fsafch3", req);
S
Swen Schillig 已提交
881 882
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
883 884
		break;
	case FSF_LUN_BOXED:
885
		zfcp_erp_unit_boxed(unit, "fsafch4", req);
S
Swen Schillig 已提交
886 887
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
888 889
                break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
890
		switch (fsq->word[0]) {
L
Linus Torvalds 已提交
891
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
892
			zfcp_test_link(unit->port);
L
Linus Torvalds 已提交
893
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
894
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
895 896 897 898
			break;
		}
		break;
	case FSF_GOOD:
S
Swen Schillig 已提交
899
		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
L
Linus Torvalds 已提交
900 901 902 903 904
		break;
	}
}

/**
S
Swen Schillig 已提交
905 906 907 908
 * zfcp_fsf_abort_fcp_command - abort running SCSI command
 * @old_req_id: unsigned long
 * @unit: pointer to struct zfcp_unit
 * Returns: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
909 910
 */

S
Swen Schillig 已提交
911
struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
912
						struct zfcp_unit *unit)
L
Linus Torvalds 已提交
913
{
914
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
915
	struct zfcp_fsf_req *req = NULL;
916
	struct zfcp_adapter *adapter = unit->port->adapter;
917

918 919
	spin_lock_bh(&adapter->req_q_lock);
	if (zfcp_fsf_req_sbal_get(adapter))
S
Swen Schillig 已提交
920 921
		goto out;
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
922
				  0, adapter->pool.fsf_req_abort);
923 924
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
925
		goto out;
926
	}
927

S
Swen Schillig 已提交
928 929 930
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		goto out_error_free;
L
Linus Torvalds 已提交
931

S
Swen Schillig 已提交
932 933 934
	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
935

S
Swen Schillig 已提交
936 937 938 939 940 941 942 943 944 945 946 947 948 949
	req->data = unit;
	req->handler = zfcp_fsf_abort_fcp_command_handler;
	req->qtcb->header.lun_handle = unit->handle;
	req->qtcb->header.port_handle = unit->port->handle;
	req->qtcb->bottom.support.req_handle = (u64) old_req_id;

	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;

out_error_free:
	zfcp_fsf_req_free(req);
	req = NULL;
out:
950
	spin_unlock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
951
	return req;
L
Linus Torvalds 已提交
952 953
}

S
Swen Schillig 已提交
954
static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
955
{
S
Swen Schillig 已提交
956 957 958
	struct zfcp_adapter *adapter = req->adapter;
	struct zfcp_send_ct *send_ct = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
959

S
Swen Schillig 已提交
960
	send_ct->status = -EINVAL;
L
Linus Torvalds 已提交
961

S
Swen Schillig 已提交
962
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
963 964 965 966
		goto skip_fsfstatus;

	switch (header->fsf_status) {
        case FSF_GOOD:
S
Swen Schillig 已提交
967 968
		zfcp_san_dbf_event_ct_response(req);
		send_ct->status = 0;
L
Linus Torvalds 已提交
969 970
		break;
        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
971
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
972 973 974 975 976
		break;
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (header->fsf_status_qual.word[0]){
                case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
                case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
977
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
978 979 980 981 982 983
			break;
                }
                break;
	case FSF_ACCESS_DENIED:
		break;
        case FSF_PORT_BOXED:
S
Swen Schillig 已提交
984 985
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
986
		break;
S
Swen Schillig 已提交
987
	case FSF_PORT_HANDLE_NOT_VALID:
988
		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req);
S
Swen Schillig 已提交
989
	case FSF_GENERIC_COMMAND_REJECTED:
L
Linus Torvalds 已提交
990 991 992 993
	case FSF_PAYLOAD_SIZE_MISMATCH:
	case FSF_REQUEST_SIZE_TOO_LARGE:
	case FSF_RESPONSE_SIZE_TOO_LARGE:
	case FSF_SBAL_MISMATCH:
S
Swen Schillig 已提交
994
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
995 996 997 998
		break;
	}

skip_fsfstatus:
S
Swen Schillig 已提交
999
	if (send_ct->handler)
L
Linus Torvalds 已提交
1000
		send_ct->handler(send_ct->handler_data);
S
Swen Schillig 已提交
1001
}
L
Linus Torvalds 已提交
1002

1003 1004 1005 1006
static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
				       struct scatterlist *sg_req,
				       struct scatterlist *sg_resp,
				       int max_sbals)
S
Swen Schillig 已提交
1007
{
1008 1009
	struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(req);
	u32 feat = req->adapter->adapter_features;
S
Swen Schillig 已提交
1010 1011
	int bytes;

1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
		if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE ||
		    !sg_is_last(sg_req) || !sg_is_last(sg_resp))
			return -EOPNOTSUPP;

		sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
		sbale[2].addr   = sg_virt(sg_req);
		sbale[2].length = sg_req->length;
		sbale[3].addr   = sg_virt(sg_resp);
		sbale[3].length = sg_resp->length;
		sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
		return 0;
	}

S
Swen Schillig 已提交
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
	bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
					sg_req, max_sbals);
	if (bytes <= 0)
		return -ENOMEM;
	req->qtcb->bottom.support.req_buf_length = bytes;
	req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;

	bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
					sg_resp, max_sbals);
	if (bytes <= 0)
		return -ENOMEM;
	req->qtcb->bottom.support.resp_buf_length = bytes;

	return 0;
L
Linus Torvalds 已提交
1040 1041 1042
}

/**
S
Swen Schillig 已提交
1043 1044 1045 1046
 * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS)
 * @ct: pointer to struct zfcp_send_ct with data for request
 * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
 * @erp_action: if non-null the Generic Service request sent within ERP
L
Linus Torvalds 已提交
1047
 */
S
Swen Schillig 已提交
1048 1049
int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
		     struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1050
{
1051 1052
	struct zfcp_wka_port *wka_port = ct->wka_port;
	struct zfcp_adapter *adapter = wka_port->adapter;
S
Swen Schillig 已提交
1053 1054
	struct zfcp_fsf_req *req;
	int ret = -EIO;
L
Linus Torvalds 已提交
1055

1056
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
1057 1058
	if (zfcp_fsf_req_sbal_get(adapter))
		goto out;
L
Linus Torvalds 已提交
1059

S
Swen Schillig 已提交
1060 1061
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC,
				  ZFCP_REQ_AUTO_CLEANUP, pool);
1062
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1063 1064
		ret = PTR_ERR(req);
		goto out;
1065 1066
	}

1067 1068
	ret = zfcp_fsf_setup_ct_els_sbals(req, ct->req, ct->resp,
					  FSF_MAX_SBALS_PER_REQ);
C
Christof Schmitt 已提交
1069
	if (ret)
L
Linus Torvalds 已提交
1070 1071
		goto failed_send;

S
Swen Schillig 已提交
1072
	req->handler = zfcp_fsf_send_ct_handler;
1073
	req->qtcb->header.port_handle = wka_port->handle;
S
Swen Schillig 已提交
1074 1075 1076 1077 1078 1079 1080 1081 1082
	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
	req->qtcb->bottom.support.timeout = ct->timeout;
	req->data = ct;

	zfcp_san_dbf_event_ct_request(req);

	if (erp_action) {
		erp_action->fsf_req = req;
		req->erp_action = erp_action;
1083
		zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1084 1085
	} else
		zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
L
Linus Torvalds 已提交
1086

S
Swen Schillig 已提交
1087 1088 1089
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;
L
Linus Torvalds 已提交
1090

S
Swen Schillig 已提交
1091
	goto out;
L
Linus Torvalds 已提交
1092

S
Swen Schillig 已提交
1093 1094 1095 1096 1097
failed_send:
	zfcp_fsf_req_free(req);
	if (erp_action)
		erp_action->fsf_req = NULL;
out:
1098
	spin_unlock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
1099
	return ret;
L
Linus Torvalds 已提交
1100 1101
}

S
Swen Schillig 已提交
1102
static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1103
{
S
Swen Schillig 已提交
1104 1105 1106
	struct zfcp_send_els *send_els = req->data;
	struct zfcp_port *port = send_els->port;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1107

S
Swen Schillig 已提交
1108
	send_els->status = -EINVAL;
L
Linus Torvalds 已提交
1109

S
Swen Schillig 已提交
1110
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
1111 1112 1113 1114
		goto skip_fsfstatus;

	switch (header->fsf_status) {
	case FSF_GOOD:
S
Swen Schillig 已提交
1115 1116
		zfcp_san_dbf_event_els_response(req);
		send_els->status = 0;
L
Linus Torvalds 已提交
1117 1118
		break;
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
1119
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
1120 1121 1122 1123
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]){
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1124 1125
			if (port && (send_els->ls_code != ZFCP_LS_ADISC))
				zfcp_test_link(port);
S
Swen Schillig 已提交
1126
			/*fall through */
L
Linus Torvalds 已提交
1127 1128
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
		case FSF_SQ_RETRY_IF_POSSIBLE:
S
Swen Schillig 已提交
1129
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1130 1131 1132 1133 1134 1135 1136 1137 1138
			break;
		}
		break;
	case FSF_ELS_COMMAND_REJECTED:
	case FSF_PAYLOAD_SIZE_MISMATCH:
	case FSF_REQUEST_SIZE_TOO_LARGE:
	case FSF_RESPONSE_SIZE_TOO_LARGE:
		break;
	case FSF_ACCESS_DENIED:
S
Swen Schillig 已提交
1139
		zfcp_fsf_access_denied_port(req, port);
L
Linus Torvalds 已提交
1140
		break;
S
Swen Schillig 已提交
1141 1142 1143
	case FSF_SBAL_MISMATCH:
		/* should never occure, avoided in zfcp_fsf_send_els */
		/* fall through */
L
Linus Torvalds 已提交
1144
	default:
S
Swen Schillig 已提交
1145
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1146 1147 1148
		break;
	}
skip_fsfstatus:
H
Heiko Carstens 已提交
1149
	if (send_els->handler)
L
Linus Torvalds 已提交
1150
		send_els->handler(send_els->handler_data);
S
Swen Schillig 已提交
1151
}
L
Linus Torvalds 已提交
1152

S
Swen Schillig 已提交
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
/**
 * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
 * @els: pointer to struct zfcp_send_els with data for the command
 */
int zfcp_fsf_send_els(struct zfcp_send_els *els)
{
	struct zfcp_fsf_req *req;
	struct zfcp_adapter *adapter = els->adapter;
	struct fsf_qtcb_bottom_support *bottom;
	int ret = -EIO;

1164 1165
	spin_lock_bh(&adapter->req_q_lock);
	if (zfcp_fsf_req_sbal_get(adapter))
S
Swen Schillig 已提交
1166 1167 1168
		goto out;
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS,
				  ZFCP_REQ_AUTO_CLEANUP, NULL);
1169
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1170 1171 1172 1173
		ret = PTR_ERR(req);
		goto out;
	}

1174
	ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
1175

S
Swen Schillig 已提交
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
	if (ret)
		goto failed_send;

	bottom = &req->qtcb->bottom.support;
	req->handler = zfcp_fsf_send_els_handler;
	bottom->d_id = els->d_id;
	bottom->service_class = FSF_CLASS_3;
	bottom->timeout = 2 * R_A_TOV;
	req->data = els;

	zfcp_san_dbf_event_els_request(req);

	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;

	goto out;

failed_send:
	zfcp_fsf_req_free(req);
out:
1198
	spin_unlock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
1199
	return ret;
L
Linus Torvalds 已提交
1200 1201
}

S
Swen Schillig 已提交
1202
int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1203
{
1204
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1205
	struct zfcp_fsf_req *req;
1206
	struct zfcp_adapter *adapter = erp_action->adapter;
S
Swen Schillig 已提交
1207 1208
	int retval = -EIO;

1209
	spin_lock_bh(&adapter->req_q_lock);
1210
	if (zfcp_fsf_req_sbal_get(adapter))
S
Swen Schillig 已提交
1211 1212 1213 1214 1215
		goto out;
	req = zfcp_fsf_req_create(adapter,
				  FSF_QTCB_EXCHANGE_CONFIG_DATA,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
1216
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1217 1218
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
1219 1220
	}

S
Swen Schillig 已提交
1221
	sbale = zfcp_qdio_sbale_req(req);
1222 1223
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
1224

S
Swen Schillig 已提交
1225
	req->qtcb->bottom.config.feature_selection =
1226 1227
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
1228
			FSF_FEATURE_NOTIFICATION_LOST |
1229
			FSF_FEATURE_UPDATE_ALERT;
S
Swen Schillig 已提交
1230 1231 1232
	req->erp_action = erp_action;
	req->handler = zfcp_fsf_exchange_config_data_handler;
	erp_action->fsf_req = req;
L
Linus Torvalds 已提交
1233

1234
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1235
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1236
	if (retval) {
S
Swen Schillig 已提交
1237
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1238 1239
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1240
out:
1241
	spin_unlock_bh(&adapter->req_q_lock);
1242 1243
	return retval;
}
L
Linus Torvalds 已提交
1244

S
Swen Schillig 已提交
1245 1246
int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
				       struct fsf_qtcb_bottom_config *data)
1247
{
1248
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1249 1250 1251
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;

1252
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
1253 1254 1255 1256 1257
	if (zfcp_fsf_req_sbal_get(adapter))
		goto out;

	req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
				  0, NULL);
1258
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1259 1260
		retval = PTR_ERR(req);
		goto out;
1261 1262
	}

S
Swen Schillig 已提交
1263
	sbale = zfcp_qdio_sbale_req(req);
1264 1265
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
S
Swen Schillig 已提交
1266
	req->handler = zfcp_fsf_exchange_config_data_handler;
1267

S
Swen Schillig 已提交
1268
	req->qtcb->bottom.config.feature_selection =
1269 1270 1271 1272 1273 1274
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
			FSF_FEATURE_NOTIFICATION_LOST |
			FSF_FEATURE_UPDATE_ALERT;

	if (data)
S
Swen Schillig 已提交
1275
		req->data = data;
1276

S
Swen Schillig 已提交
1277 1278 1279
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
out:
1280
	spin_unlock_bh(&adapter->req_q_lock);
C
Christof Schmitt 已提交
1281
	if (!retval)
S
Swen Schillig 已提交
1282 1283
		wait_event(req->completion_wq,
			   req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
1284

S
Swen Schillig 已提交
1285
	zfcp_fsf_req_free(req);
1286

L
Linus Torvalds 已提交
1287 1288 1289 1290 1291
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data - request information about local port
1292
 * @erp_action: ERP action for the adapter for which port data is requested
S
Swen Schillig 已提交
1293
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1294
 */
S
Swen Schillig 已提交
1295
int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1296
{
1297
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1298
	struct zfcp_fsf_req *req;
1299
	struct zfcp_adapter *adapter = erp_action->adapter;
S
Swen Schillig 已提交
1300
	int retval = -EIO;
L
Linus Torvalds 已提交
1301

C
Christof Schmitt 已提交
1302
	if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1303
		return -EOPNOTSUPP;
L
Linus Torvalds 已提交
1304

1305
	spin_lock_bh(&adapter->req_q_lock);
1306
	if (zfcp_fsf_req_sbal_get(adapter))
S
Swen Schillig 已提交
1307 1308 1309 1310
		goto out;
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
1311
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1312 1313
		retval = PTR_ERR(req);
		goto out;
1314 1315
	}

S
Swen Schillig 已提交
1316
	sbale = zfcp_qdio_sbale_req(req);
1317 1318
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
1319

S
Swen Schillig 已提交
1320 1321 1322
	req->handler = zfcp_fsf_exchange_port_data_handler;
	req->erp_action = erp_action;
	erp_action->fsf_req = req;
1323

1324
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1325
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1326
	if (retval) {
S
Swen Schillig 已提交
1327
		zfcp_fsf_req_free(req);
1328 1329
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1330
out:
1331
	spin_unlock_bh(&adapter->req_q_lock);
1332 1333 1334 1335 1336
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data_sync - request information about local port
S
Swen Schillig 已提交
1337 1338 1339
 * @adapter: pointer to struct zfcp_adapter
 * @data: pointer to struct fsf_qtcb_bottom_port
 * Returns: 0 on success, error otherwise
1340
 */
S
Swen Schillig 已提交
1341 1342
int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
				     struct fsf_qtcb_bottom_port *data)
1343
{
1344
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1345 1346
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;
1347

C
Christof Schmitt 已提交
1348
	if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1349 1350
		return -EOPNOTSUPP;

1351
	spin_lock_bh(&adapter->req_q_lock);
1352
	if (zfcp_fsf_req_sbal_get(adapter))
S
Swen Schillig 已提交
1353 1354 1355 1356
		goto out;

	req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0,
				  NULL);
1357
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1358 1359
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
1360 1361
	}

1362
	if (data)
S
Swen Schillig 已提交
1363
		req->data = data;
1364

S
Swen Schillig 已提交
1365
	sbale = zfcp_qdio_sbale_req(req);
1366 1367 1368
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1369 1370 1371 1372
	req->handler = zfcp_fsf_exchange_port_data_handler;
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
out:
1373
	spin_unlock_bh(&adapter->req_q_lock);
C
Christof Schmitt 已提交
1374
	if (!retval)
S
Swen Schillig 已提交
1375 1376 1377
		wait_event(req->completion_wq,
			   req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1378 1379 1380 1381

	return retval;
}

S
Swen Schillig 已提交
1382
static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1383
{
S
Swen Schillig 已提交
1384 1385
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1386 1387
	struct fsf_plogi *plogi;

S
Swen Schillig 已提交
1388
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1389
		return;
L
Linus Torvalds 已提交
1390 1391 1392 1393 1394

	switch (header->fsf_status) {
	case FSF_PORT_ALREADY_OPEN:
		break;
	case FSF_ACCESS_DENIED:
S
Swen Schillig 已提交
1395
		zfcp_fsf_access_denied_port(req, port);
L
Linus Torvalds 已提交
1396 1397
		break;
	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
S
Swen Schillig 已提交
1398
		dev_warn(&req->adapter->ccw_device->dev,
1399
			 "Not enough FCP adapter resources to open "
1400 1401
			 "remote port 0x%016Lx\n",
			 (unsigned long long)port->wwpn);
1402
		zfcp_erp_port_failed(port, "fsoph_1", req);
S
Swen Schillig 已提交
1403
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1404 1405 1406 1407 1408 1409
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
		case FSF_SQ_NO_RETRY_POSSIBLE:
S
Swen Schillig 已提交
1410
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1411 1412 1413 1414 1415 1416 1417
			break;
		}
		break;
	case FSF_GOOD:
		port->handle = header->port_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1418 1419 1420
		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
		                  &port->status);
L
Linus Torvalds 已提交
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
		/* check whether D_ID has changed during open */
		/*
		 * FIXME: This check is not airtight, as the FCP channel does
		 * not monitor closures of target port connections caused on
		 * the remote side. Thus, they might miss out on invalidating
		 * locally cached WWPNs (and other N_Port parameters) of gone
		 * target ports. So, our heroic attempt to make things safe
		 * could be undermined by 'open port' response data tagged with
		 * obsolete WWPNs. Another reason to monitor potential
		 * connection closures ourself at least (by interpreting
		 * incoming ELS' and unsolicited status). It just crosses my
		 * mind that one should be able to cross-check by means of
		 * another GID_PN straight after a port has been opened.
		 * Alternately, an ADISC/PDISC ELS should suffice, as well.
		 */
S
Swen Schillig 已提交
1436
		plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
1437 1438
		if (req->qtcb->bottom.support.els1_length >=
		    FSF_PLOGI_MIN_LEN) {
S
Swen Schillig 已提交
1439
			if (plogi->serv_param.wwpn != port->wwpn)
1440
				port->d_id = 0;
S
Swen Schillig 已提交
1441 1442 1443
			else {
				port->wwnn = plogi->serv_param.wwnn;
				zfcp_fc_plogi_evaluate(port, plogi);
L
Linus Torvalds 已提交
1444 1445 1446 1447
			}
		}
		break;
	case FSF_UNKNOWN_OP_SUBTYPE:
S
Swen Schillig 已提交
1448
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1449 1450 1451 1452
		break;
	}
}

S
Swen Schillig 已提交
1453 1454 1455 1456
/**
 * zfcp_fsf_open_port - create and send open port request
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1457
 */
S
Swen Schillig 已提交
1458
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1459
{
1460
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1461 1462 1463 1464
	struct zfcp_adapter *adapter = erp_action->adapter;
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1465
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
1466 1467 1468 1469 1470 1471 1472
	if (zfcp_fsf_req_sbal_get(adapter))
		goto out;

	req = zfcp_fsf_req_create(adapter,
				  FSF_QTCB_OPEN_PORT_WITH_DID,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
1473
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1474
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1475
		goto out;
S
Swen Schillig 已提交
1476
	}
L
Linus Torvalds 已提交
1477

S
Swen Schillig 已提交
1478
	sbale = zfcp_qdio_sbale_req(req);
L
Linus Torvalds 已提交
1479 1480 1481
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1482 1483 1484 1485 1486 1487
	req->handler = zfcp_fsf_open_port_handler;
	req->qtcb->bottom.support.d_id = erp_action->port->d_id;
	req->data = erp_action->port;
	req->erp_action = erp_action;
	erp_action->fsf_req = req;

1488
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1489
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1490
	if (retval) {
S
Swen Schillig 已提交
1491
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1492 1493
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1494
out:
1495
	spin_unlock_bh(&adapter->req_q_lock);
L
Linus Torvalds 已提交
1496 1497 1498
	return retval;
}

S
Swen Schillig 已提交
1499
static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1500
{
S
Swen Schillig 已提交
1501
	struct zfcp_port *port = req->data;
L
Linus Torvalds 已提交
1502

S
Swen Schillig 已提交
1503
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1504
		return;
L
Linus Torvalds 已提交
1505

S
Swen Schillig 已提交
1506
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1507
	case FSF_PORT_HANDLE_NOT_VALID:
1508
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req);
S
Swen Schillig 已提交
1509
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1510 1511 1512 1513
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		break;
	case FSF_GOOD:
1514
		zfcp_erp_modify_port_status(port, "fscph_2", req,
L
Linus Torvalds 已提交
1515 1516 1517 1518 1519 1520
					    ZFCP_STATUS_COMMON_OPEN,
					    ZFCP_CLEAR);
		break;
	}
}

S
Swen Schillig 已提交
1521 1522 1523 1524
/**
 * zfcp_fsf_close_port - create and send close port request
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1525
 */
S
Swen Schillig 已提交
1526
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1527
{
1528
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1529 1530 1531 1532
	struct zfcp_adapter *adapter = erp_action->adapter;
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1533
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
1534 1535 1536 1537 1538 1539
	if (zfcp_fsf_req_sbal_get(adapter))
		goto out;

	req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
1540
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1541
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1542
		goto out;
S
Swen Schillig 已提交
1543
	}
L
Linus Torvalds 已提交
1544

S
Swen Schillig 已提交
1545
	sbale = zfcp_qdio_sbale_req(req);
L
Linus Torvalds 已提交
1546 1547 1548
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1549 1550 1551 1552 1553 1554
	req->handler = zfcp_fsf_close_port_handler;
	req->data = erp_action->port;
	req->erp_action = erp_action;
	req->qtcb->header.port_handle = erp_action->port->handle;
	erp_action->fsf_req = req;

1555
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1556
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1557
	if (retval) {
S
Swen Schillig 已提交
1558
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1559 1560
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1561
out:
1562
	spin_unlock_bh(&adapter->req_q_lock);
L
Linus Torvalds 已提交
1563 1564 1565
	return retval;
}

1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585
static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_wka_port *wka_port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
		goto out;
	}

	switch (header->fsf_status) {
	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
		dev_warn(&req->adapter->ccw_device->dev,
			 "Opening WKA port 0x%x failed\n", wka_port->d_id);
	case FSF_ADAPTER_STATUS_AVAILABLE:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
	case FSF_ACCESS_DENIED:
		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
		break;
	case FSF_PORT_ALREADY_OPEN:
1586
		break;
1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
	case FSF_GOOD:
		wka_port->handle = header->port_handle;
		wka_port->status = ZFCP_WKA_PORT_ONLINE;
	}
out:
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_open_wka_port - create and send open wka-port request
 * @wka_port: pointer to struct zfcp_wka_port
 * Returns: 0 on success, error otherwise
 */
int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
{
	struct qdio_buffer_element *sbale;
	struct zfcp_adapter *adapter = wka_port->adapter;
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1607
	spin_lock_bh(&adapter->req_q_lock);
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632
	if (zfcp_fsf_req_sbal_get(adapter))
		goto out;

	req = zfcp_fsf_req_create(adapter,
				  FSF_QTCB_OPEN_PORT_WITH_DID,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
	if (unlikely(IS_ERR(req))) {
		retval = PTR_ERR(req);
		goto out;
	}

	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

	req->handler = zfcp_fsf_open_wka_port_handler;
	req->qtcb->bottom.support.d_id = wka_port->d_id;
	req->data = wka_port;

	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
	if (retval)
		zfcp_fsf_req_free(req);
out:
1633
	spin_unlock_bh(&adapter->req_q_lock);
1634 1635 1636 1637 1638 1639 1640 1641 1642
	return retval;
}

static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_wka_port *wka_port = req->data;

	if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1643
		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req);
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
	}

	wka_port->status = ZFCP_WKA_PORT_OFFLINE;
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_close_wka_port - create and send close wka port request
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
 */
int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
{
	struct qdio_buffer_element *sbale;
	struct zfcp_adapter *adapter = wka_port->adapter;
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1662
	spin_lock_bh(&adapter->req_q_lock);
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686
	if (zfcp_fsf_req_sbal_get(adapter))
		goto out;

	req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
	if (unlikely(IS_ERR(req))) {
		retval = PTR_ERR(req);
		goto out;
	}

	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

	req->handler = zfcp_fsf_close_wka_port_handler;
	req->data = wka_port;
	req->qtcb->header.port_handle = wka_port->handle;

	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
	if (retval)
		zfcp_fsf_req_free(req);
out:
1687
	spin_unlock_bh(&adapter->req_q_lock);
1688 1689 1690
	return retval;
}

S
Swen Schillig 已提交
1691
static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1692
{
S
Swen Schillig 已提交
1693 1694
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1695 1696
	struct zfcp_unit *unit;

S
Swen Schillig 已提交
1697
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1698
		return;
L
Linus Torvalds 已提交
1699 1700 1701

	switch (header->fsf_status) {
	case FSF_PORT_HANDLE_NOT_VALID:
1702
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req);
S
Swen Schillig 已提交
1703
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1704 1705
		break;
	case FSF_ACCESS_DENIED:
S
Swen Schillig 已提交
1706
		zfcp_fsf_access_denied_port(req, port);
L
Linus Torvalds 已提交
1707 1708
		break;
	case FSF_PORT_BOXED:
1709
		zfcp_erp_port_boxed(port, "fscpph2", req);
S
Swen Schillig 已提交
1710 1711
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
1712 1713 1714 1715 1716 1717
		/* can't use generic zfcp_erp_modify_port_status because
		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
		list_for_each_entry(unit, &port->unit_list_head, list)
			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
					  &unit->status);
L
Linus Torvalds 已提交
1718 1719 1720 1721
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
S
Swen Schillig 已提交
1722
			/* fall through */
L
Linus Torvalds 已提交
1723
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1724
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1725 1726 1727 1728 1729 1730 1731 1732 1733
			break;
		}
		break;
	case FSF_GOOD:
		/* can't use generic zfcp_erp_modify_port_status because
		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
		 */
		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
		list_for_each_entry(unit, &port->unit_list_head, list)
S
Swen Schillig 已提交
1734 1735
			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
					  &unit->status);
L
Linus Torvalds 已提交
1736 1737 1738 1739
		break;
	}
}

S
Swen Schillig 已提交
1740 1741 1742 1743
/**
 * zfcp_fsf_close_physical_port - close physical port
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success
L
Linus Torvalds 已提交
1744
 */
S
Swen Schillig 已提交
1745
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1746
{
1747
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1748 1749 1750 1751
	struct zfcp_adapter *adapter = erp_action->adapter;
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1752
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
1753
	if (zfcp_fsf_req_sbal_get(adapter))
L
Linus Torvalds 已提交
1754 1755
		goto out;

S
Swen Schillig 已提交
1756 1757 1758
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PHYSICAL_PORT,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
1759
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1760 1761 1762
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1763

S
Swen Schillig 已提交
1764 1765 1766
	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
1767

S
Swen Schillig 已提交
1768 1769 1770 1771 1772 1773
	req->data = erp_action->port;
	req->qtcb->header.port_handle = erp_action->port->handle;
	req->erp_action = erp_action;
	req->handler = zfcp_fsf_close_physical_port_handler;
	erp_action->fsf_req = req;

1774
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1775
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1776
	if (retval) {
S
Swen Schillig 已提交
1777
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1778 1779
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1780
out:
1781
	spin_unlock_bh(&adapter->req_q_lock);
L
Linus Torvalds 已提交
1782 1783 1784
	return retval;
}

S
Swen Schillig 已提交
1785
static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1786
{
S
Swen Schillig 已提交
1787 1788 1789 1790 1791 1792
	struct zfcp_adapter *adapter = req->adapter;
	struct zfcp_unit *unit = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
	struct fsf_queue_designator *queue_designator =
				&header->fsf_status_qual.fsf_queue_designator;
1793
	int exclusive, readwrite;
L
Linus Torvalds 已提交
1794

S
Swen Schillig 已提交
1795
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1796
		return;
L
Linus Torvalds 已提交
1797 1798

	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1799
			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
L
Linus Torvalds 已提交
1800 1801 1802 1803 1804 1805 1806
			  ZFCP_STATUS_UNIT_SHARED |
			  ZFCP_STATUS_UNIT_READONLY,
			  &unit->status);

	switch (header->fsf_status) {

	case FSF_PORT_HANDLE_NOT_VALID:
1807
		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req);
S
Swen Schillig 已提交
1808
		/* fall through */
L
Linus Torvalds 已提交
1809 1810 1811
	case FSF_LUN_ALREADY_OPEN:
		break;
	case FSF_ACCESS_DENIED:
S
Swen Schillig 已提交
1812
		zfcp_fsf_access_denied_unit(req, unit);
L
Linus Torvalds 已提交
1813
		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
C
Christof Schmitt 已提交
1814
		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
L
Linus Torvalds 已提交
1815 1816
		break;
	case FSF_PORT_BOXED:
1817
		zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
S
Swen Schillig 已提交
1818 1819
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
1820 1821
		break;
	case FSF_LUN_SHARING_VIOLATION:
S
Swen Schillig 已提交
1822
		if (header->fsf_status_qual.word[0])
C
Christof Schmitt 已提交
1823
			dev_warn(&adapter->ccw_device->dev,
1824 1825
				 "LUN 0x%Lx on port 0x%Lx is already in "
				 "use by CSS%d, MIF Image ID %x\n",
1826 1827
				 (unsigned long long)unit->fcp_lun,
				 (unsigned long long)unit->port->wwpn,
1828 1829
				 queue_designator->cssid,
				 queue_designator->hla);
S
Swen Schillig 已提交
1830
		else
C
Christof Schmitt 已提交
1831 1832
			zfcp_act_eval_err(adapter,
					  header->fsf_status_qual.word[2]);
1833
		zfcp_erp_unit_access_denied(unit, "fsouh_3", req);
L
Linus Torvalds 已提交
1834 1835
		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
S
Swen Schillig 已提交
1836
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1837 1838
		break;
	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
S
Swen Schillig 已提交
1839
		dev_warn(&adapter->ccw_device->dev,
1840 1841
			 "No handle is available for LUN "
			 "0x%016Lx on port 0x%016Lx\n",
1842 1843
			 (unsigned long long)unit->fcp_lun,
			 (unsigned long long)unit->port->wwpn);
1844
		zfcp_erp_unit_failed(unit, "fsouh_4", req);
S
Swen Schillig 已提交
1845 1846 1847
		/* fall through */
	case FSF_INVALID_COMMAND_OPTION:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1848 1849 1850 1851
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1852
			zfcp_test_link(unit->port);
S
Swen Schillig 已提交
1853
			/* fall through */
L
Linus Torvalds 已提交
1854
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1855
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1856 1857 1858 1859 1860 1861 1862
			break;
		}
		break;

	case FSF_GOOD:
		unit->handle = header->lun_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
1863 1864 1865 1866 1867 1868 1869 1870 1871

		if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
		    (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
		    (adapter->ccw_device->id.dev_model != ZFCP_DEVICE_MODEL_PRIV)) {
			exclusive = (bottom->lun_access_info &
					FSF_UNIT_ACCESS_EXCLUSIVE);
			readwrite = (bottom->lun_access_info &
					FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);

L
Linus Torvalds 已提交
1872 1873 1874 1875 1876 1877 1878
			if (!exclusive)
		                atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
						&unit->status);

			if (!readwrite) {
                		atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
						&unit->status);
S
Swen Schillig 已提交
1879
				dev_info(&adapter->ccw_device->dev,
1880 1881
					 "SCSI device at LUN 0x%016Lx on port "
					 "0x%016Lx opened read-only\n",
1882 1883
					 (unsigned long long)unit->fcp_lun,
					 (unsigned long long)unit->port->wwpn);
L
Linus Torvalds 已提交
1884 1885 1886
        		}

        		if (exclusive && !readwrite) {
S
Swen Schillig 已提交
1887
				dev_err(&adapter->ccw_device->dev,
1888 1889 1890
					"Exclusive read-only access not "
					"supported (unit 0x%016Lx, "
					"port 0x%016Lx)\n",
1891 1892
					(unsigned long long)unit->fcp_lun,
					(unsigned long long)unit->port->wwpn);
1893
				zfcp_erp_unit_failed(unit, "fsouh_5", req);
S
Swen Schillig 已提交
1894
				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1895
				zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req);
L
Linus Torvalds 已提交
1896
        		} else if (!exclusive && readwrite) {
S
Swen Schillig 已提交
1897
				dev_err(&adapter->ccw_device->dev,
1898 1899
					"Shared read-write access not "
					"supported (unit 0x%016Lx, port "
1900
					"0x%016Lx)\n",
1901 1902
					(unsigned long long)unit->fcp_lun,
					(unsigned long long)unit->port->wwpn);
1903
				zfcp_erp_unit_failed(unit, "fsouh_7", req);
S
Swen Schillig 已提交
1904
				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1905
				zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req);
L
Linus Torvalds 已提交
1906 1907 1908 1909 1910 1911
        		}
		}
		break;
	}
}

S
Swen Schillig 已提交
1912 1913 1914 1915
/**
 * zfcp_fsf_open_unit - open unit
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1916
 */
S
Swen Schillig 已提交
1917
int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1918
{
1919
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1920 1921 1922 1923
	struct zfcp_adapter *adapter = erp_action->adapter;
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1924
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
1925
	if (zfcp_fsf_req_sbal_get(adapter))
L
Linus Torvalds 已提交
1926 1927
		goto out;

S
Swen Schillig 已提交
1928 1929 1930
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_OPEN_LUN,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
1931
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1932 1933 1934 1935 1936
		retval = PTR_ERR(req);
		goto out;
	}

	sbale = zfcp_qdio_sbale_req(req);
L
Linus Torvalds 已提交
1937 1938 1939
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1940 1941 1942 1943 1944 1945 1946 1947 1948 1949
	req->qtcb->header.port_handle = erp_action->port->handle;
	req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
	req->handler = zfcp_fsf_open_unit_handler;
	req->data = erp_action->unit;
	req->erp_action = erp_action;
	erp_action->fsf_req = req;

	if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE))
		req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING;

1950
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1951
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1952
	if (retval) {
S
Swen Schillig 已提交
1953
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1954 1955
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1956
out:
1957
	spin_unlock_bh(&adapter->req_q_lock);
L
Linus Torvalds 已提交
1958 1959 1960
	return retval;
}

S
Swen Schillig 已提交
1961
static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1962
{
S
Swen Schillig 已提交
1963
	struct zfcp_unit *unit = req->data;
L
Linus Torvalds 已提交
1964

S
Swen Schillig 已提交
1965
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1966
		return;
L
Linus Torvalds 已提交
1967

S
Swen Schillig 已提交
1968
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1969
	case FSF_PORT_HANDLE_NOT_VALID:
1970
		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req);
S
Swen Schillig 已提交
1971
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1972 1973
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
1974
		zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req);
S
Swen Schillig 已提交
1975
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1976 1977
		break;
	case FSF_PORT_BOXED:
1978
		zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
S
Swen Schillig 已提交
1979 1980
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
1981 1982
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
1983
		switch (req->qtcb->header.fsf_status_qual.word[0]) {
L
Linus Torvalds 已提交
1984
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1985
			zfcp_test_link(unit->port);
S
Swen Schillig 已提交
1986
			/* fall through */
L
Linus Torvalds 已提交
1987
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1988
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1989 1990 1991 1992 1993 1994 1995 1996 1997 1998
			break;
		}
		break;
	case FSF_GOOD:
		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
		break;
	}
}

/**
S
Swen Schillig 已提交
1999 2000 2001
 * zfcp_fsf_close_unit - close zfcp unit
 * @erp_action: pointer to struct zfcp_unit
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
2002
 */
S
Swen Schillig 已提交
2003
int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
2004
{
2005
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
2006 2007 2008
	struct zfcp_adapter *adapter = erp_action->adapter;
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
2009

2010
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
2011
	if (zfcp_fsf_req_sbal_get(adapter))
L
Linus Torvalds 已提交
2012
		goto out;
S
Swen Schillig 已提交
2013 2014 2015
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN,
				  ZFCP_REQ_AUTO_CLEANUP,
				  adapter->pool.fsf_req_erp);
2016
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2017 2018 2019
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
2020

S
Swen Schillig 已提交
2021 2022
	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
L
Linus Torvalds 已提交
2023 2024
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
2025 2026 2027 2028 2029 2030
	req->qtcb->header.port_handle = erp_action->port->handle;
	req->qtcb->header.lun_handle = erp_action->unit->handle;
	req->handler = zfcp_fsf_close_unit_handler;
	req->data = erp_action->unit;
	req->erp_action = erp_action;
	erp_action->fsf_req = req;
2031

2032
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
2033 2034 2035 2036 2037 2038
	retval = zfcp_fsf_req_send(req);
	if (retval) {
		zfcp_fsf_req_free(req);
		erp_action->fsf_req = NULL;
	}
out:
2039
	spin_unlock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
2040
	return retval;
L
Linus Torvalds 已提交
2041 2042
}

2043 2044 2045
static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
{
	lat_rec->sum += lat;
S
Swen Schillig 已提交
2046 2047
	lat_rec->min = min(lat_rec->min, lat);
	lat_rec->max = max(lat_rec->max, lat);
2048 2049
}

S
Swen Schillig 已提交
2050
static void zfcp_fsf_req_latency(struct zfcp_fsf_req *req)
2051 2052 2053
{
	struct fsf_qual_latency_info *lat_inf;
	struct latency_cont *lat;
S
Swen Schillig 已提交
2054
	struct zfcp_unit *unit = req->unit;
2055

S
Swen Schillig 已提交
2056
	lat_inf = &req->qtcb->prefix.prot_status_qual.latency_info;
2057

S
Swen Schillig 已提交
2058
	switch (req->qtcb->bottom.io.data_direction) {
2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071
	case FSF_DATADIR_READ:
		lat = &unit->latencies.read;
		break;
	case FSF_DATADIR_WRITE:
		lat = &unit->latencies.write;
		break;
	case FSF_DATADIR_CMND:
		lat = &unit->latencies.cmd;
		break;
	default:
		return;
	}

2072
	spin_lock(&unit->latencies.lock);
2073 2074 2075
	zfcp_fsf_update_lat(&lat->channel, lat_inf->channel_lat);
	zfcp_fsf_update_lat(&lat->fabric, lat_inf->fabric_lat);
	lat->counter++;
2076
	spin_unlock(&unit->latencies.lock);
L
Linus Torvalds 已提交
2077 2078
}

S
Stefan Raspl 已提交
2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
#ifdef CONFIG_BLK_DEV_IO_TRACE
static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
{
	struct fsf_qual_latency_info *lat_inf;
	struct scsi_cmnd *scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
	struct request *req = scsi_cmnd->request;
	struct zfcp_blk_drv_data trace;
	int ticks = fsf_req->adapter->timer_ticks;

	trace.flags = 0;
	trace.magic = ZFCP_BLK_DRV_DATA_MAGIC;
	if (fsf_req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
		trace.flags |= ZFCP_BLK_LAT_VALID;
		lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
		trace.channel_lat = lat_inf->channel_lat * ticks;
		trace.fabric_lat = lat_inf->fabric_lat * ticks;
	}
	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
		trace.flags |= ZFCP_BLK_REQ_ERROR;
	trace.inb_usage = fsf_req->qdio_inb_usage;
	trace.outb_usage = fsf_req->qdio_outb_usage;

	blk_add_driver_data(req->q, req, &trace, sizeof(trace));
}
#else
static inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
{
}
#endif

S
Swen Schillig 已提交
2109
static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
2110
{
2111
	struct scsi_cmnd *scpnt;
L
Linus Torvalds 已提交
2112
	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
S
Swen Schillig 已提交
2113
	    &(req->qtcb->bottom.io.fcp_rsp);
L
Linus Torvalds 已提交
2114
	u32 sns_len;
2115
	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
L
Linus Torvalds 已提交
2116 2117
	unsigned long flags;

S
Swen Schillig 已提交
2118 2119
	read_lock_irqsave(&req->adapter->abort_lock, flags);

2120 2121 2122 2123 2124 2125
	scpnt = req->data;
	if (unlikely(!scpnt)) {
		read_unlock_irqrestore(&req->adapter->abort_lock, flags);
		return;
	}

S
Swen Schillig 已提交
2126
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) {
2127
		set_host_byte(scpnt, DID_SOFT_ERROR);
L
Linus Torvalds 已提交
2128 2129 2130
		goto skip_fsfstatus;
	}

S
Swen Schillig 已提交
2131
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2132
		set_host_byte(scpnt, DID_ERROR);
L
Linus Torvalds 已提交
2133 2134 2135
		goto skip_fsfstatus;
	}

2136
	set_msg_byte(scpnt, COMMAND_COMPLETE);
L
Linus Torvalds 已提交
2137 2138 2139

	scpnt->result |= fcp_rsp_iu->scsi_status;

S
Swen Schillig 已提交
2140 2141
	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
		zfcp_fsf_req_latency(req);
2142

S
Stefan Raspl 已提交
2143 2144
	zfcp_fsf_trace_latency(req);

L
Linus Torvalds 已提交
2145
	if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
S
Swen Schillig 已提交
2146
		if (fcp_rsp_info[3] == RSP_CODE_GOOD)
2147
			set_host_byte(scpnt, DID_OK);
S
Swen Schillig 已提交
2148
		else {
2149
			set_host_byte(scpnt, DID_ERROR);
已提交
2150
			goto skip_fsfstatus;
L
Linus Torvalds 已提交
2151 2152 2153 2154
		}
	}

	if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) {
S
Swen Schillig 已提交
2155 2156
		sns_len = FSF_FCP_RSP_SIZE - sizeof(struct fcp_rsp_iu) +
			  fcp_rsp_iu->fcp_rsp_len;
L
Linus Torvalds 已提交
2157 2158 2159
		sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE);
		sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len);

2160
		memcpy(scpnt->sense_buffer,
L
Linus Torvalds 已提交
2161 2162 2163 2164
		       zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len);
	}

	if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) {
2165 2166 2167
		scsi_set_resid(scpnt, fcp_rsp_iu->fcp_resid);
		if (scsi_bufflen(scpnt) - scsi_get_resid(scpnt) <
		    scpnt->underflow)
2168
			set_host_byte(scpnt, DID_ERROR);
L
Linus Torvalds 已提交
2169
	}
S
Swen Schillig 已提交
2170
skip_fsfstatus:
2171
	if (scpnt->result != 0)
S
Swen Schillig 已提交
2172
		zfcp_scsi_dbf_event_result("erro", 3, req->adapter, scpnt, req);
2173
	else if (scpnt->retries > 0)
S
Swen Schillig 已提交
2174
		zfcp_scsi_dbf_event_result("retr", 4, req->adapter, scpnt, req);
2175
	else
S
Swen Schillig 已提交
2176
		zfcp_scsi_dbf_event_result("norm", 6, req->adapter, scpnt, req);
L
Linus Torvalds 已提交
2177 2178 2179 2180 2181 2182 2183 2184 2185

	scpnt->host_scribble = NULL;
	(scpnt->scsi_done) (scpnt);
	/*
	 * We must hold this lock until scsi_done has been called.
	 * Otherwise we may call scsi_done after abort regarding this
	 * command has completed.
	 * Note: scsi_done must not block!
	 */
S
Swen Schillig 已提交
2186
	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
L
Linus Torvalds 已提交
2187 2188
}

S
Swen Schillig 已提交
2189
static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
2190 2191
{
	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
S
Swen Schillig 已提交
2192
	    &(req->qtcb->bottom.io.fcp_rsp);
2193
	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
L
Linus Torvalds 已提交
2194

S
Swen Schillig 已提交
2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211
	if ((fcp_rsp_info[3] != RSP_CODE_GOOD) ||
	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
}


static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_unit *unit;
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
		unit = req->data;
	else
		unit = req->unit;

	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
L
Linus Torvalds 已提交
2212 2213
		goto skip_fsfstatus;

S
Swen Schillig 已提交
2214 2215 2216
	switch (header->fsf_status) {
	case FSF_HANDLE_MISMATCH:
	case FSF_PORT_HANDLE_NOT_VALID:
2217
		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
S
Swen Schillig 已提交
2218 2219 2220 2221
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_FCPLUN_NOT_VALID:
	case FSF_LUN_HANDLE_NOT_VALID:
2222
		zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
S
Swen Schillig 已提交
2223
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2224
		break;
S
Swen Schillig 已提交
2225 2226
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
2227
		break;
S
Swen Schillig 已提交
2228 2229 2230 2231 2232
	case FSF_ACCESS_DENIED:
		zfcp_fsf_access_denied_unit(req, unit);
		break;
	case FSF_DIRECTION_INDICATOR_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2233 2234
			"Incorrect direction %d, unit 0x%016Lx on port "
			"0x%016Lx closed\n",
S
Swen Schillig 已提交
2235
			req->qtcb->bottom.io.data_direction,
2236 2237
			(unsigned long long)unit->fcp_lun,
			(unsigned long long)unit->port->wwpn);
2238 2239
		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
					  req);
S
Swen Schillig 已提交
2240 2241 2242 2243
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_CMND_LENGTH_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2244 2245
			"Incorrect CDB length %d, unit 0x%016Lx on "
			"port 0x%016Lx closed\n",
S
Swen Schillig 已提交
2246
			req->qtcb->bottom.io.fcp_cmnd_length,
2247 2248
			(unsigned long long)unit->fcp_lun,
			(unsigned long long)unit->port->wwpn);
2249 2250
		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
					  req);
S
Swen Schillig 已提交
2251 2252 2253
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_PORT_BOXED:
2254
		zfcp_erp_port_boxed(unit->port, "fssfch5", req);
S
Swen Schillig 已提交
2255 2256 2257 2258
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
		break;
	case FSF_LUN_BOXED:
2259
		zfcp_erp_unit_boxed(unit, "fssfch6", req);
S
Swen Schillig 已提交
2260 2261 2262 2263 2264 2265 2266 2267
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		if (header->fsf_status_qual.word[0] ==
		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
			zfcp_test_link(unit->port);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2268 2269
		break;
	}
S
Swen Schillig 已提交
2270 2271 2272 2273 2274 2275 2276 2277
skip_fsfstatus:
	if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
		zfcp_fsf_send_fcp_ctm_handler(req);
	else {
		zfcp_fsf_send_fcp_command_task_handler(req);
		req->unit = NULL;
		zfcp_unit_put(unit);
	}
L
Linus Torvalds 已提交
2278 2279
}

2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
{
	u32 *fcp_dl_ptr;

	/*
	 * fcp_dl_addr = start address of fcp_cmnd structure +
	 * size of fixed part + size of dynamically sized add_dcp_cdb field
	 * SEE FCP-2 documentation
	 */
	fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] +
			(fcp_cmd->add_fcp_cdb_length << 2));
	*fcp_dl_ptr = fcp_dl;
}

S
Swen Schillig 已提交
2294 2295 2296 2297
/**
 * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
 * @unit: unit where command is sent to
 * @scsi_cmnd: scsi command to be sent
L
Linus Torvalds 已提交
2298
 */
2299 2300
int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
				   struct scsi_cmnd *scsi_cmnd)
L
Linus Torvalds 已提交
2301
{
S
Swen Schillig 已提交
2302 2303 2304 2305
	struct zfcp_fsf_req *req;
	struct fcp_cmnd_iu *fcp_cmnd_iu;
	unsigned int sbtype;
	int real_bytes, retval = -EIO;
2306
	struct zfcp_adapter *adapter = unit->port->adapter;
L
Linus Torvalds 已提交
2307

S
Swen Schillig 已提交
2308 2309 2310
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return -EBUSY;
L
Linus Torvalds 已提交
2311

2312
	spin_lock(&adapter->req_q_lock);
2313 2314
	if (atomic_read(&adapter->req_q.count) <= 0) {
		atomic_inc(&adapter->qdio_outb_full);
S
Swen Schillig 已提交
2315
		goto out;
2316
	}
2317 2318
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND,
				  ZFCP_REQ_AUTO_CLEANUP,
S
Swen Schillig 已提交
2319
				  adapter->pool.fsf_req_scsi);
2320
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346
		retval = PTR_ERR(req);
		goto out;
	}

	zfcp_unit_get(unit);
	req->unit = unit;
	req->data = scsi_cmnd;
	req->handler = zfcp_fsf_send_fcp_command_handler;
	req->qtcb->header.lun_handle = unit->handle;
	req->qtcb->header.port_handle = unit->port->handle;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;

	scsi_cmnd->host_scribble = (unsigned char *) req->req_id;

	fcp_cmnd_iu = (struct fcp_cmnd_iu *) &(req->qtcb->bottom.io.fcp_cmnd);
	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
	/*
	 * set depending on data direction:
	 *      data direction bits in SBALE (SB Type)
	 *      data direction bits in QTCB
	 *      data direction bits in FCP_CMND IU
	 */
	switch (scsi_cmnd->sc_data_direction) {
	case DMA_NONE:
		req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
		sbtype = SBAL_FLAGS0_TYPE_READ;
L
Linus Torvalds 已提交
2347
		break;
S
Swen Schillig 已提交
2348 2349 2350 2351 2352 2353 2354 2355 2356
	case DMA_FROM_DEVICE:
		req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
		sbtype = SBAL_FLAGS0_TYPE_READ;
		fcp_cmnd_iu->rddata = 1;
		break;
	case DMA_TO_DEVICE:
		req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
		sbtype = SBAL_FLAGS0_TYPE_WRITE;
		fcp_cmnd_iu->wddata = 1;
L
Linus Torvalds 已提交
2357
		break;
S
Swen Schillig 已提交
2358
	case DMA_BIDIRECTIONAL:
L
Linus Torvalds 已提交
2359
	default:
S
Swen Schillig 已提交
2360 2361
		retval = -EIO;
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2362 2363
	}

S
Swen Schillig 已提交
2364 2365 2366 2367 2368 2369
	if (likely((scsi_cmnd->device->simple_tags) ||
		   ((atomic_read(&unit->status) & ZFCP_STATUS_UNIT_READONLY) &&
		    (atomic_read(&unit->status) & ZFCP_STATUS_UNIT_SHARED))))
		fcp_cmnd_iu->task_attribute = SIMPLE_Q;
	else
		fcp_cmnd_iu->task_attribute = UNTAGGED;
L
Linus Torvalds 已提交
2370

S
Swen Schillig 已提交
2371 2372 2373
	if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH))
		fcp_cmnd_iu->add_fcp_cdb_length =
			(scsi_cmnd->cmd_len - FCP_CDB_LENGTH) >> 2;
L
Linus Torvalds 已提交
2374

S
Swen Schillig 已提交
2375
	memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
2376

S
Swen Schillig 已提交
2377
	req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
2378
		fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
L
Linus Torvalds 已提交
2379

S
Swen Schillig 已提交
2380 2381 2382 2383 2384 2385 2386 2387
	real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype,
					     scsi_sglist(scsi_cmnd),
					     FSF_MAX_SBALS_PER_REQ);
	if (unlikely(real_bytes < 0)) {
		if (req->sbal_number < FSF_MAX_SBALS_PER_REQ)
			retval = -EIO;
		else {
			dev_err(&adapter->ccw_device->dev,
2388 2389
				"Oversize data package, unit 0x%016Lx "
				"on port 0x%016Lx closed\n",
2390 2391
				(unsigned long long)unit->fcp_lun,
				(unsigned long long)unit->port->wwpn);
2392
			zfcp_erp_unit_shutdown(unit, 0, "fssfct1", req);
S
Swen Schillig 已提交
2393 2394 2395
			retval = -EINVAL;
		}
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2396 2397
	}

S
Swen Schillig 已提交
2398
	zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes);
L
Linus Torvalds 已提交
2399

S
Swen Schillig 已提交
2400 2401 2402
	retval = zfcp_fsf_req_send(req);
	if (unlikely(retval))
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2403

S
Swen Schillig 已提交
2404
	goto out;
L
Linus Torvalds 已提交
2405

S
Swen Schillig 已提交
2406 2407 2408 2409 2410
failed_scsi_cmnd:
	zfcp_unit_put(unit);
	zfcp_fsf_req_free(req);
	scsi_cmnd->host_scribble = NULL;
out:
2411
	spin_unlock(&adapter->req_q_lock);
S
Swen Schillig 已提交
2412
	return retval;
L
Linus Torvalds 已提交
2413 2414 2415
}

/**
S
Swen Schillig 已提交
2416 2417 2418 2419
 * zfcp_fsf_send_fcp_ctm - send SCSI task management command
 * @unit: pointer to struct zfcp_unit
 * @tm_flags: unsigned byte for task management flags
 * Returns: on success pointer to struct fsf_req, NULL otherwise
L
Linus Torvalds 已提交
2420
 */
2421
struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
L
Linus Torvalds 已提交
2422
{
2423
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
2424 2425
	struct zfcp_fsf_req *req = NULL;
	struct fcp_cmnd_iu *fcp_cmnd_iu;
2426
	struct zfcp_adapter *adapter = unit->port->adapter;
L
Linus Torvalds 已提交
2427

S
Swen Schillig 已提交
2428 2429 2430
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return NULL;
L
Linus Torvalds 已提交
2431

2432 2433
	spin_lock_bh(&adapter->req_q_lock);
	if (zfcp_fsf_req_sbal_get(adapter))
S
Swen Schillig 已提交
2434
		goto out;
2435
	req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, 0,
S
Swen Schillig 已提交
2436
				  adapter->pool.fsf_req_scsi);
2437 2438
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
2439
		goto out;
2440
	}
L
Linus Torvalds 已提交
2441

S
Swen Schillig 已提交
2442 2443 2444 2445 2446 2447 2448 2449
	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
	req->data = unit;
	req->handler = zfcp_fsf_send_fcp_command_handler;
	req->qtcb->header.lun_handle = unit->handle;
	req->qtcb->header.port_handle = unit->port->handle;
	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
	req->qtcb->bottom.io.fcp_cmnd_length = 	sizeof(struct fcp_cmnd_iu) +
2450
						sizeof(u32);
S
Swen Schillig 已提交
2451 2452 2453 2454

	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
2455

S
Swen Schillig 已提交
2456 2457 2458
	fcp_cmnd_iu = (struct fcp_cmnd_iu *) &req->qtcb->bottom.io.fcp_cmnd;
	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
	fcp_cmnd_iu->task_management_flags = tm_flags;
L
Linus Torvalds 已提交
2459

S
Swen Schillig 已提交
2460 2461 2462
	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;
L
Linus Torvalds 已提交
2463

S
Swen Schillig 已提交
2464 2465 2466
	zfcp_fsf_req_free(req);
	req = NULL;
out:
2467
	spin_unlock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
2468 2469
	return req;
}
L
Linus Torvalds 已提交
2470

S
Swen Schillig 已提交
2471 2472 2473 2474
static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
{
	if (req->qtcb->header.fsf_status != FSF_GOOD)
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2475 2476
}

S
Swen Schillig 已提交
2477 2478 2479 2480 2481
/**
 * zfcp_fsf_control_file - control file upload/download
 * @adapter: pointer to struct zfcp_adapter
 * @fsf_cfdc: pointer to struct zfcp_fsf_cfdc
 * Returns: on success pointer to struct zfcp_fsf_req, NULL otherwise
L
Linus Torvalds 已提交
2482
 */
S
Swen Schillig 已提交
2483 2484
struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
					   struct zfcp_fsf_cfdc *fsf_cfdc)
L
Linus Torvalds 已提交
2485
{
2486
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503
	struct zfcp_fsf_req *req = NULL;
	struct fsf_qtcb_bottom_support *bottom;
	int direction, retval = -EIO, bytes;

	if (!(adapter->adapter_features & FSF_FEATURE_CFDC))
		return ERR_PTR(-EOPNOTSUPP);

	switch (fsf_cfdc->command) {
	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
		direction = SBAL_FLAGS0_TYPE_WRITE;
		break;
	case FSF_QTCB_UPLOAD_CONTROL_FILE:
		direction = SBAL_FLAGS0_TYPE_READ;
		break;
	default:
		return ERR_PTR(-EINVAL);
	}
L
Linus Torvalds 已提交
2504

2505
	spin_lock_bh(&adapter->req_q_lock);
S
Swen Schillig 已提交
2506 2507
	if (zfcp_fsf_req_sbal_get(adapter))
		goto out;
L
Linus Torvalds 已提交
2508

S
Swen Schillig 已提交
2509
	req = zfcp_fsf_req_create(adapter, fsf_cfdc->command, 0, NULL);
2510
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2511 2512 2513
		retval = -EPERM;
		goto out;
	}
L
Linus Torvalds 已提交
2514

S
Swen Schillig 已提交
2515
	req->handler = zfcp_fsf_control_file_handler;
L
Linus Torvalds 已提交
2516

S
Swen Schillig 已提交
2517 2518
	sbale = zfcp_qdio_sbale_req(req);
	sbale[0].flags |= direction;
2519

S
Swen Schillig 已提交
2520 2521 2522
	bottom = &req->qtcb->bottom.support;
	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
	bottom->option = fsf_cfdc->option;
2523

S
Swen Schillig 已提交
2524 2525 2526 2527 2528 2529 2530
	bytes = zfcp_qdio_sbals_from_sg(req, direction, fsf_cfdc->sg,
					FSF_MAX_SBALS_PER_REQ);
	if (bytes != ZFCP_CFDC_MAX_SIZE) {
		retval = -ENOMEM;
		zfcp_fsf_req_free(req);
		goto out;
	}
L
Linus Torvalds 已提交
2531

S
Swen Schillig 已提交
2532 2533 2534
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
out:
2535
	spin_unlock_bh(&adapter->req_q_lock);
2536

S
Swen Schillig 已提交
2537 2538 2539 2540
	if (!retval) {
		wait_event(req->completion_wq,
			   req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
		return req;
L
Linus Torvalds 已提交
2541
	}
S
Swen Schillig 已提交
2542
	return ERR_PTR(retval);
L
Linus Torvalds 已提交
2543
}