zfcp_fsf.c 67.1 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
L
Linus Torvalds 已提交
2
/*
C
Christof Schmitt 已提交
3
 * zfcp device driver
L
Linus Torvalds 已提交
4
 *
C
Christof Schmitt 已提交
5
 * Implementation of FSF commands.
L
Linus Torvalds 已提交
6
 *
7
 * Copyright IBM Corp. 2002, 2018
L
Linus Torvalds 已提交
8 9
 */

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

S
Stefan Raspl 已提交
13
#include <linux/blktrace_api.h>
14
#include <linux/slab.h>
15
#include <scsi/fc/fc_els.h>
L
Linus Torvalds 已提交
16
#include "zfcp_ext.h"
17
#include "zfcp_fc.h"
18
#include "zfcp_dbf.h"
19
#include "zfcp_qdio.h"
20
#include "zfcp_reqlist.h"
L
Linus Torvalds 已提交
21

22 23
struct kmem_cache *zfcp_fsf_qtcb_cache;

24 25 26 27 28
static bool ber_stop = true;
module_param(ber_stop, bool, 0600);
MODULE_PARM_DESC(ber_stop,
		 "Shuts down FCP devices for FCP channels that report a bit-error count in excess of its threshold (default on)");

29
static void zfcp_fsf_request_timeout_handler(struct timer_list *t)
30
{
31 32
	struct zfcp_fsf_req *fsf_req = from_timer(fsf_req, t, timer);
	struct zfcp_adapter *adapter = fsf_req->adapter;
33

34
	zfcp_qdio_siosl(adapter);
35
	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
36
				"fsrth_1");
37 38 39 40 41
}

static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req,
				 unsigned long timeout)
{
42
	fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
43 44 45 46 47 48 49
	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);
50
	fsf_req->timer.function = zfcp_erp_timeout_handler;
51 52 53 54
	fsf_req->timer.expires = jiffies + 30 * HZ;
	add_timer(&fsf_req->timer);
}

L
Linus Torvalds 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
/* 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 已提交
72 73
static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
{
74 75
	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
		"operational because of an unsupported FC class\n");
76
	zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1");
C
Christof Schmitt 已提交
77 78 79
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}

S
Swen Schillig 已提交
80 81 82
/**
 * zfcp_fsf_req_free - free memory used by fsf request
 * @fsf_req: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
83
 */
S
Swen Schillig 已提交
84
void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
85
{
S
Swen Schillig 已提交
86
	if (likely(req->pool)) {
87 88
		if (likely(req->qtcb))
			mempool_free(req->qtcb, req->adapter->pool.qtcb_pool);
S
Swen Schillig 已提交
89
		mempool_free(req, req->pool);
90 91 92
		return;
	}

93
	if (likely(req->qtcb))
94
		kmem_cache_free(zfcp_fsf_qtcb_cache, req->qtcb);
95
	kfree(req);
L
Linus Torvalds 已提交
96 97
}

S
Swen Schillig 已提交
98
static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
99
{
100
	unsigned long flags;
S
Swen Schillig 已提交
101 102 103
	struct fsf_status_read_buffer *sr_buf = req->data;
	struct zfcp_adapter *adapter = req->adapter;
	struct zfcp_port *port;
104
	int d_id = ntoh24(sr_buf->d_id);
L
Linus Torvalds 已提交
105

106 107
	read_lock_irqsave(&adapter->port_list_lock, flags);
	list_for_each_entry(port, &adapter->port_list, list)
S
Swen Schillig 已提交
108
		if (port->d_id == d_id) {
109
			zfcp_erp_port_reopen(port, 0, "fssrpc1");
110
			break;
S
Swen Schillig 已提交
111
		}
112
	read_unlock_irqrestore(&adapter->port_list_lock, flags);
L
Linus Torvalds 已提交
113 114
}

115
static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req,
S
Swen Schillig 已提交
116
					 struct fsf_link_down_info *link_down)
117
{
S
Swen Schillig 已提交
118
	struct zfcp_adapter *adapter = req->adapter;
119

S
Swen Schillig 已提交
120
	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
121 122
		return;

123
	atomic_or(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
124

125
	zfcp_scsi_schedule_rports_block(adapter);
126

S
Swen Schillig 已提交
127
	if (!link_down)
128
		goto out;
129

130 131
	switch (link_down->error_code) {
	case FSF_PSQ_LINK_NO_LIGHT:
S
Swen Schillig 已提交
132
		dev_warn(&req->adapter->ccw_device->dev,
133 134
			 "There is no light signal from the local "
			 "fibre channel cable\n");
135 136
		break;
	case FSF_PSQ_LINK_WRAP_PLUG:
S
Swen Schillig 已提交
137
		dev_warn(&req->adapter->ccw_device->dev,
138 139
			 "There is a wrap plug instead of a fibre "
			 "channel cable\n");
140 141
		break;
	case FSF_PSQ_LINK_NO_FCP:
S
Swen Schillig 已提交
142
		dev_warn(&req->adapter->ccw_device->dev,
143 144
			 "The adjacent fibre channel node does not "
			 "support FCP\n");
145 146
		break;
	case FSF_PSQ_LINK_FIRMWARE_UPDATE:
S
Swen Schillig 已提交
147
		dev_warn(&req->adapter->ccw_device->dev,
148 149
			 "The FCP device is suspended because of a "
			 "firmware update\n");
C
Christof Schmitt 已提交
150
		break;
151
	case FSF_PSQ_LINK_INVALID_WWPN:
S
Swen Schillig 已提交
152
		dev_warn(&req->adapter->ccw_device->dev,
153 154
			 "The FCP device detected a WWPN that is "
			 "duplicate or not valid\n");
155 156
		break;
	case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
S
Swen Schillig 已提交
157
		dev_warn(&req->adapter->ccw_device->dev,
158
			 "The fibre channel fabric does not support NPIV\n");
159 160
		break;
	case FSF_PSQ_LINK_NO_FCP_RESOURCES:
S
Swen Schillig 已提交
161
		dev_warn(&req->adapter->ccw_device->dev,
162
			 "The FCP adapter cannot support more NPIV ports\n");
163 164
		break;
	case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
S
Swen Schillig 已提交
165
		dev_warn(&req->adapter->ccw_device->dev,
166 167
			 "The adjacent switch cannot support "
			 "more NPIV ports\n");
168 169
		break;
	case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
S
Swen Schillig 已提交
170
		dev_warn(&req->adapter->ccw_device->dev,
171 172
			 "The FCP adapter could not log in to the "
			 "fibre channel fabric\n");
173 174
		break;
	case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
S
Swen Schillig 已提交
175
		dev_warn(&req->adapter->ccw_device->dev,
176 177
			 "The WWPN assignment file on the FCP adapter "
			 "has been damaged\n");
178 179
		break;
	case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
S
Swen Schillig 已提交
180
		dev_warn(&req->adapter->ccw_device->dev,
181 182
			 "The mode table on the FCP adapter "
			 "has been damaged\n");
183 184
		break;
	case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
S
Swen Schillig 已提交
185
		dev_warn(&req->adapter->ccw_device->dev,
186 187
			 "All NPIV ports on the FCP adapter have "
			 "been assigned\n");
188 189
		break;
	default:
S
Swen Schillig 已提交
190
		dev_warn(&req->adapter->ccw_device->dev,
191 192
			 "The link between the FCP adapter and "
			 "the FC fabric is down\n");
193
	}
S
Swen Schillig 已提交
194
out:
195
	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
196 197
}

S
Swen Schillig 已提交
198
static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
199
{
S
Swen Schillig 已提交
200 201 202
	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 已提交
203

S
Swen Schillig 已提交
204 205 206
	switch (sr_buf->status_subtype) {
	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
	case FSF_STATUS_READ_SUB_FDISC_FAILED:
207
		zfcp_fsf_link_down_info_eval(req, ldi);
L
Linus Torvalds 已提交
208
		break;
S
Swen Schillig 已提交
209
	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
210
		zfcp_fsf_link_down_info_eval(req, NULL);
211
	}
S
Swen Schillig 已提交
212
}
L
Linus Torvalds 已提交
213

S
Swen Schillig 已提交
214 215 216 217
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 已提交
218

S
Swen Schillig 已提交
219
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
220
		zfcp_dbf_hba_fsf_uss("fssrh_1", req);
221
		mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
S
Swen Schillig 已提交
222 223 224
		zfcp_fsf_req_free(req);
		return;
	}
L
Linus Torvalds 已提交
225

226
	zfcp_dbf_hba_fsf_uss("fssrh_4", req);
L
Linus Torvalds 已提交
227

S
Swen Schillig 已提交
228 229 230
	switch (sr_buf->status_type) {
	case FSF_STATUS_READ_PORT_CLOSED:
		zfcp_fsf_status_read_port_closed(req);
L
Linus Torvalds 已提交
231
		break;
S
Swen Schillig 已提交
232 233
	case FSF_STATUS_READ_INCOMING_ELS:
		zfcp_fc_incoming_els(req);
L
Linus Torvalds 已提交
234
		break;
S
Swen Schillig 已提交
235
	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
L
Linus Torvalds 已提交
236
		break;
S
Swen Schillig 已提交
237
	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
238
		zfcp_dbf_hba_bit_err("fssrh_3", req);
239 240 241 242 243 244 245 246
		if (ber_stop) {
			dev_warn(&adapter->ccw_device->dev,
				 "All paths over this FCP device are disused because of excessive bit errors\n");
			zfcp_erp_adapter_shutdown(adapter, 0, "fssrh_b");
		} else {
			dev_warn(&adapter->ccw_device->dev,
				 "The error threshold for checksum statistics has been exceeded\n");
		}
L
Linus Torvalds 已提交
247
		break;
S
Swen Schillig 已提交
248 249
	case FSF_STATUS_READ_LINK_DOWN:
		zfcp_fsf_status_read_link_down(req);
250
		zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKDOWN, 0);
S
Swen Schillig 已提交
251 252 253
		break;
	case FSF_STATUS_READ_LINK_UP:
		dev_info(&adapter->ccw_device->dev,
254
			 "The local link has been restored\n");
S
Swen Schillig 已提交
255
		/* All ports should be marked as ready to run again */
256 257
		zfcp_erp_set_adapter_status(adapter,
					    ZFCP_STATUS_COMMON_RUNNING);
S
Swen Schillig 已提交
258 259 260
		zfcp_erp_adapter_reopen(adapter,
					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
					ZFCP_STATUS_COMMON_ERP_FAILED,
261
					"fssrh_2");
262 263
		zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0);

S
Swen Schillig 已提交
264 265 266
		break;
	case FSF_STATUS_READ_NOTIFICATION_LOST:
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
267
			zfcp_fc_conditional_port_scan(adapter);
S
Swen Schillig 已提交
268 269 270
		break;
	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
		adapter->adapter_features = sr_buf->payload.word[0];
L
Linus Torvalds 已提交
271 272 273
		break;
	}

274
	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
S
Swen Schillig 已提交
275
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
276

S
Swen Schillig 已提交
277
	atomic_inc(&adapter->stat_miss);
278
	queue_work(adapter->work_queue, &adapter->stat_work);
S
Swen Schillig 已提交
279
}
L
Linus Torvalds 已提交
280

S
Swen Schillig 已提交
281 282 283 284 285 286 287 288 289 290 291 292
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:
		break;
	case FSF_SQ_NO_RECOM:
		dev_err(&req->adapter->ccw_device->dev,
293 294
			"The FCP adapter reported a problem "
			"that cannot be recovered\n");
295
		zfcp_qdio_siosl(req->adapter);
296
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1");
S
Swen Schillig 已提交
297 298 299 300
		break;
	}
	/* all non-return stats set FSFREQ_ERROR*/
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
301 302
}

S
Swen Schillig 已提交
303
static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
304
{
S
Swen Schillig 已提交
305 306
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
		return;
L
Linus Torvalds 已提交
307

S
Swen Schillig 已提交
308 309 310
	switch (req->qtcb->header.fsf_status) {
	case FSF_UNKNOWN_COMMAND:
		dev_err(&req->adapter->ccw_device->dev,
311
			"The FCP adapter does not recognize the command 0x%x\n",
S
Swen Schillig 已提交
312
			req->qtcb->header.fsf_command);
313
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1");
S
Swen Schillig 已提交
314 315 316 317 318 319 320
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		zfcp_fsf_fsfstatus_qual_eval(req);
		break;
	}
}
L
Linus Torvalds 已提交
321

S
Swen Schillig 已提交
322 323 324 325 326
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 已提交
327

S
Swen Schillig 已提交
328
	zfcp_dbf_hba_fsf_response(req);
L
Linus Torvalds 已提交
329

S
Swen Schillig 已提交
330
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
331
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
332 333
		return;
	}
L
Linus Torvalds 已提交
334

S
Swen Schillig 已提交
335 336 337 338 339 340
	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,
341 342 343
			"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]);
344
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1");
S
Swen Schillig 已提交
345 346 347
		break;
	case FSF_PROT_ERROR_STATE:
	case FSF_PROT_SEQ_NUMB_ERROR:
348
		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2");
349
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
350 351 352
		break;
	case FSF_PROT_UNSUPP_QTCB_TYPE:
		dev_err(&adapter->ccw_device->dev,
353
			"The QTCB type is not supported by the FCP adapter\n");
354
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3");
S
Swen Schillig 已提交
355 356
		break;
	case FSF_PROT_HOST_CONNECTION_INITIALIZING:
357
		atomic_or(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
S
Swen Schillig 已提交
358 359 360 361
				&adapter->status);
		break;
	case FSF_PROT_DUPLICATE_REQUEST_ID:
		dev_err(&adapter->ccw_device->dev,
362
			"0x%Lx is an ambiguous request identifier\n",
S
Swen Schillig 已提交
363
			(unsigned long long)qtcb->bottom.support.req_handle);
364
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4");
S
Swen Schillig 已提交
365 366
		break;
	case FSF_PROT_LINK_DOWN:
367
		zfcp_fsf_link_down_info_eval(req, &psq->link_down_info);
368
		/* go through reopen to flush pending requests */
369
		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6");
S
Swen Schillig 已提交
370 371 372
		break;
	case FSF_PROT_REEST_QUEUE:
		/* All ports should be marked as ready to run again */
373 374
		zfcp_erp_set_adapter_status(adapter,
					    ZFCP_STATUS_COMMON_RUNNING);
S
Swen Schillig 已提交
375 376
		zfcp_erp_adapter_reopen(adapter,
					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
377
					ZFCP_STATUS_COMMON_ERP_FAILED,
378
					"fspse_8");
S
Swen Schillig 已提交
379 380 381
		break;
	default:
		dev_err(&adapter->ccw_device->dev,
382
			"0x%x is not a valid transfer protocol status\n",
S
Swen Schillig 已提交
383
			qtcb->prefix.prot_status);
384
		zfcp_qdio_siosl(adapter);
385
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9");
S
Swen Schillig 已提交
386 387
	}
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
388 389
}

S
Swen Schillig 已提交
390 391 392 393 394 395 396 397 398
/**
 * 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.
 */
399
static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
400
{
S
Swen Schillig 已提交
401 402 403 404
	if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
		zfcp_fsf_status_read_handler(req);
		return;
	}
L
Linus Torvalds 已提交
405

S
Swen Schillig 已提交
406 407 408 409
	del_timer(&req->timer);
	zfcp_fsf_protstatus_eval(req);
	zfcp_fsf_fsfstatus_eval(req);
	req->handler(req);
L
Linus Torvalds 已提交
410

S
Swen Schillig 已提交
411
	if (req->erp_action)
412
		zfcp_erp_notify(req->erp_action, 0);
L
Linus Torvalds 已提交
413

S
Swen Schillig 已提交
414 415 416
	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
		zfcp_fsf_req_free(req);
	else
417
		complete(&req->completion);
S
Swen Schillig 已提交
418
}
L
Linus Torvalds 已提交
419

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
/**
 * zfcp_fsf_req_dismiss_all - dismiss all fsf requests
 * @adapter: pointer to struct zfcp_adapter
 *
 * 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.
 */
void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
{
	struct zfcp_fsf_req *req, *tmp;
	LIST_HEAD(remove_queue);

	BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
435
	zfcp_reqlist_move(adapter->req_list, &remove_queue);
436 437 438 439 440 441 442 443

	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);
	}
}

444 445 446 447 448 449
#define ZFCP_FSF_PORTSPEED_1GBIT	(1 <<  0)
#define ZFCP_FSF_PORTSPEED_2GBIT	(1 <<  1)
#define ZFCP_FSF_PORTSPEED_4GBIT	(1 <<  2)
#define ZFCP_FSF_PORTSPEED_10GBIT	(1 <<  3)
#define ZFCP_FSF_PORTSPEED_8GBIT	(1 <<  4)
#define ZFCP_FSF_PORTSPEED_16GBIT	(1 <<  5)
450 451 452
#define ZFCP_FSF_PORTSPEED_32GBIT	(1 <<  6)
#define ZFCP_FSF_PORTSPEED_64GBIT	(1 <<  7)
#define ZFCP_FSF_PORTSPEED_128GBIT	(1 <<  8)
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15)

static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed)
{
	u32 fdmi_speed = 0;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT)
		fdmi_speed |= FC_PORTSPEED_1GBIT;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_2GBIT)
		fdmi_speed |= FC_PORTSPEED_2GBIT;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_4GBIT)
		fdmi_speed |= FC_PORTSPEED_4GBIT;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_10GBIT)
		fdmi_speed |= FC_PORTSPEED_10GBIT;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_8GBIT)
		fdmi_speed |= FC_PORTSPEED_8GBIT;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT)
		fdmi_speed |= FC_PORTSPEED_16GBIT;
470 471 472 473 474 475
	if (fsf_speed & ZFCP_FSF_PORTSPEED_32GBIT)
		fdmi_speed |= FC_PORTSPEED_32GBIT;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_64GBIT)
		fdmi_speed |= FC_PORTSPEED_64GBIT;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_128GBIT)
		fdmi_speed |= FC_PORTSPEED_128GBIT;
476 477 478 479 480
	if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED)
		fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED;
	return fdmi_speed;
}

S
Swen Schillig 已提交
481 482
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
{
483
	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
S
Swen Schillig 已提交
484 485
	struct zfcp_adapter *adapter = req->adapter;
	struct Scsi_Host *shost = adapter->scsi_host;
486
	struct fc_els_flogi *nsp, *plogi;
L
Linus Torvalds 已提交
487

488 489 490 491 492
	/* adjust pointers for missing command code */
	nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param
					- sizeof(u32));
	plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload
					- sizeof(u32));
L
Linus Torvalds 已提交
493

S
Swen Schillig 已提交
494 495 496
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));

497 498
	fc_host_port_name(shost) = be64_to_cpu(nsp->fl_wwpn);
	fc_host_node_name(shost) = be64_to_cpu(nsp->fl_wwnn);
S
Swen Schillig 已提交
499 500
	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;

501
	adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK;
502 503
	adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
					 (u16)FSF_STATUS_READS_RECOM);
S
Swen Schillig 已提交
504 505 506 507

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

508 509 510 511 512 513 514 515 516 517 518 519 520
	zfcp_scsi_set_prot(adapter);

	/* no error return above here, otherwise must fix call chains */
	/* do not evaluate invalid fields */
	if (req->qtcb->header.fsf_status == FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE)
		return 0;

	fc_host_port_id(shost) = ntoh24(bottom->s_id);
	fc_host_speed(shost) =
		zfcp_fsf_convert_portspeed(bottom->fc_link_speed);

	adapter->hydra_version = bottom->adapter_type;

S
Swen Schillig 已提交
521 522
	switch (bottom->fc_topology) {
	case FSF_TOPO_P2P:
523
		adapter->peer_d_id = ntoh24(bottom->peer_d_id);
524 525
		adapter->peer_wwpn = be64_to_cpu(plogi->fl_wwpn);
		adapter->peer_wwnn = be64_to_cpu(plogi->fl_wwnn);
S
Swen Schillig 已提交
526 527 528
		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
		break;
	case FSF_TOPO_FABRIC:
529 530 531 532
		if (bottom->connection_features & FSF_FEATURE_NPIV_MODE)
			fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
		else
			fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
S
Swen Schillig 已提交
533 534 535
		break;
	case FSF_TOPO_AL:
		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
536
		/* fall through */
S
Swen Schillig 已提交
537 538
	default:
		dev_err(&adapter->ccw_device->dev,
539 540
			"Unknown or unsupported arbitrated loop "
			"fibre channel topology detected\n");
541
		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1");
S
Swen Schillig 已提交
542
		return -EIO;
L
Linus Torvalds 已提交
543
	}
S
Swen Schillig 已提交
544

L
Linus Torvalds 已提交
545 546 547
	return 0;
}

S
Swen Schillig 已提交
548
static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
C
Christof Schmitt 已提交
549 550
{
	struct zfcp_adapter *adapter = req->adapter;
S
Swen Schillig 已提交
551 552 553
	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 已提交
554

S
Swen Schillig 已提交
555 556
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;
L
Linus Torvalds 已提交
557

S
Swen Schillig 已提交
558 559 560 561 562 563
	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;
564

S
Swen Schillig 已提交
565 566 567 568
	switch (qtcb->header.fsf_status) {
	case FSF_GOOD:
		if (zfcp_fsf_exchange_config_evaluate(req))
			return;
L
Linus Torvalds 已提交
569

S
Swen Schillig 已提交
570 571
		if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
			dev_err(&adapter->ccw_device->dev,
572 573 574
				"FCP adapter maximum QTCB size (%d bytes) "
				"is too small\n",
				bottom->max_qtcb_size);
575
			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1");
S
Swen Schillig 已提交
576 577
			return;
		}
578
		atomic_or(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
S
Swen Schillig 已提交
579
				&adapter->status);
L
Linus Torvalds 已提交
580
		break;
S
Swen Schillig 已提交
581 582 583 584 585 586 587
	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 已提交
588

589 590
		/* avoids adapter shutdown to be able to recognize
		 * events such as LINK UP */
591
		atomic_or(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
592
				&adapter->status);
593
		zfcp_fsf_link_down_info_eval(req,
S
Swen Schillig 已提交
594
			&qtcb->header.fsf_status_qual.link_down_info);
595 596
		if (zfcp_fsf_exchange_config_evaluate(req))
			return;
L
Linus Torvalds 已提交
597
		break;
S
Swen Schillig 已提交
598
	default:
599
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3");
S
Swen Schillig 已提交
600 601
		return;
	}
L
Linus Torvalds 已提交
602

S
Swen Schillig 已提交
603 604 605 606 607 608 609
	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 已提交
610

S
Swen Schillig 已提交
611 612
	if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
		dev_err(&adapter->ccw_device->dev,
613 614
			"The FCP adapter only supports newer "
			"control block versions\n");
615
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4");
S
Swen Schillig 已提交
616 617 618 619
		return;
	}
	if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
		dev_err(&adapter->ccw_device->dev,
620 621
			"The FCP adapter only supports older "
			"control block versions\n");
622
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5");
S
Swen Schillig 已提交
623 624
	}
}
L
Linus Torvalds 已提交
625

S
Swen Schillig 已提交
626 627 628 629 630
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 已提交
631

S
Swen Schillig 已提交
632 633
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));
634

635
	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
S
Swen Schillig 已提交
636
		fc_host_permanent_port_name(shost) = bottom->wwpn;
637
	} else
S
Swen Schillig 已提交
638 639
		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
640 641
	fc_host_supported_speeds(shost) =
		zfcp_fsf_convert_portspeed(bottom->supported_speed);
642 643 644 645
	memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
	       FC_FC4_LIST_SIZE);
	memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
	       FC_FC4_LIST_SIZE);
S
Swen Schillig 已提交
646
}
L
Linus Torvalds 已提交
647

S
Swen Schillig 已提交
648 649 650 651 652 653 654 655 656 657 658 659 660
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);
661
		zfcp_fsf_link_down_info_eval(req,
S
Swen Schillig 已提交
662
			&qtcb->header.fsf_status_qual.link_down_info);
663
		break;
L
Linus Torvalds 已提交
664
	}
S
Swen Schillig 已提交
665
}
666

667
static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
S
Swen Schillig 已提交
668 669
{
	struct zfcp_fsf_req *req;
670 671 672 673 674 675 676

	if (likely(pool))
		req = mempool_alloc(pool, GFP_ATOMIC);
	else
		req = kmalloc(sizeof(*req), GFP_ATOMIC);

	if (unlikely(!req))
S
Swen Schillig 已提交
677
		return NULL;
678

S
Swen Schillig 已提交
679
	memset(req, 0, sizeof(*req));
680
	req->pool = pool;
S
Swen Schillig 已提交
681 682 683
	return req;
}

684
static struct fsf_qtcb *zfcp_fsf_qtcb_alloc(mempool_t *pool)
S
Swen Schillig 已提交
685
{
686
	struct fsf_qtcb *qtcb;
S
Swen Schillig 已提交
687 688 689 690

	if (likely(pool))
		qtcb = mempool_alloc(pool, GFP_ATOMIC);
	else
691
		qtcb = kmem_cache_alloc(zfcp_fsf_qtcb_cache, GFP_ATOMIC);
692

S
Swen Schillig 已提交
693 694 695 696
	if (unlikely(!qtcb))
		return NULL;

	memset(qtcb, 0, sizeof(*qtcb));
697
	return qtcb;
S
Swen Schillig 已提交
698 699
}

700
static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
701
						u32 fsf_cmd, u8 sbtype,
702
						mempool_t *pool)
L
Linus Torvalds 已提交
703
{
704
	struct zfcp_adapter *adapter = qdio->adapter;
705
	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
L
Linus Torvalds 已提交
706

S
Swen Schillig 已提交
707
	if (unlikely(!req))
708
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
709

S
Swen Schillig 已提交
710 711
	if (adapter->req_no == 0)
		adapter->req_no++;
L
Linus Torvalds 已提交
712

S
Swen Schillig 已提交
713
	INIT_LIST_HEAD(&req->list);
714
	timer_setup(&req->timer, NULL, 0);
715
	init_completion(&req->completion);
L
Linus Torvalds 已提交
716

S
Swen Schillig 已提交
717 718
	req->adapter = adapter;
	req->fsf_command = fsf_cmd;
719
	req->req_id = adapter->req_no;
S
Swen Schillig 已提交
720

721 722
	if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
		if (likely(pool))
723 724
			req->qtcb = zfcp_fsf_qtcb_alloc(
				adapter->pool.qtcb_pool);
725
		else
726
			req->qtcb = zfcp_fsf_qtcb_alloc(NULL);
727 728 729 730 731 732

		if (unlikely(!req->qtcb)) {
			zfcp_fsf_req_free(req);
			return ERR_PTR(-ENOMEM);
		}

733
		req->seq_no = adapter->fsf_req_seq_no;
734
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
S
Swen Schillig 已提交
735 736 737 738 739 740 741 742
		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;
	}

743 744 745
	zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,
			   req->qtcb, sizeof(struct fsf_qtcb));

S
Swen Schillig 已提交
746
	return req;
L
Linus Torvalds 已提交
747 748
}

S
Swen Schillig 已提交
749 750 751
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
752
	struct zfcp_qdio *qdio = adapter->qdio;
753
	int with_qtcb = (req->qtcb != NULL);
754
	int req_id = req->req_id;
S
Swen Schillig 已提交
755

756
	zfcp_reqlist_add(adapter->req_list, req);
S
Swen Schillig 已提交
757

758
	req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free);
759
	req->issued = get_tod_clock();
760
	if (zfcp_qdio_send(qdio, &req->qdio_req)) {
S
Swen Schillig 已提交
761
		del_timer(&req->timer);
762
		/* lookup request again, list might have changed */
763
		zfcp_reqlist_find_rm(adapter->req_list, req_id);
764
		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1");
S
Swen Schillig 已提交
765 766 767 768
		return -EIO;
	}

	/* Don't increase for unsolicited status */
769
	if (with_qtcb)
S
Swen Schillig 已提交
770
		adapter->fsf_req_seq_no++;
771
	adapter->req_no++;
S
Swen Schillig 已提交
772 773 774 775 776 777 778 779 780

	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 已提交
781
 */
782
int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
L
Linus Torvalds 已提交
783
{
784
	struct zfcp_adapter *adapter = qdio->adapter;
S
Swen Schillig 已提交
785 786
	struct zfcp_fsf_req *req;
	struct fsf_status_read_buffer *sr_buf;
787
	struct page *page;
S
Swen Schillig 已提交
788
	int retval = -EIO;
L
Linus Torvalds 已提交
789

790
	spin_lock_irq(&qdio->req_q_lock);
791
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
792 793
		goto out;

794 795
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS,
				  SBAL_SFLAGS0_TYPE_STATUS,
796
				  adapter->pool.status_read_req);
797
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
798 799
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
800 801
	}

802 803
	page = mempool_alloc(adapter->pool.sr_data, GFP_ATOMIC);
	if (!page) {
S
Swen Schillig 已提交
804 805 806
		retval = -ENOMEM;
		goto failed_buf;
	}
807
	sr_buf = page_address(page);
S
Swen Schillig 已提交
808 809
	memset(sr_buf, 0, sizeof(*sr_buf));
	req->data = sr_buf;
810 811 812

	zfcp_qdio_fill_next(qdio, &req->qdio_req, sr_buf, sizeof(*sr_buf));
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
813

S
Swen Schillig 已提交
814 815 816
	retval = zfcp_fsf_req_send(req);
	if (retval)
		goto failed_req_send;
L
Linus Torvalds 已提交
817

S
Swen Schillig 已提交
818 819 820
	goto out;

failed_req_send:
821
	req->data = NULL;
822
	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
S
Swen Schillig 已提交
823
failed_buf:
824
	zfcp_dbf_hba_fsf_uss("fssr__1", req);
S
Swen Schillig 已提交
825 826
	zfcp_fsf_req_free(req);
out:
827
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
828 829 830 831 832
	return retval;
}

static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
833
	struct scsi_device *sdev = req->data;
834
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
835 836 837 838 839
	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;

840 841
	zfcp_sdev = sdev_to_zfcp(sdev);

S
Swen Schillig 已提交
842
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
843
	case FSF_PORT_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
844
		if (fsq->word[0] == fsq->word[1]) {
845
			zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
846
						"fsafch1");
S
Swen Schillig 已提交
847
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
848 849 850
		}
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
851
		if (fsq->word[0] == fsq->word[1]) {
852
			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2");
S
Swen Schillig 已提交
853
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
854 855 856
		}
		break;
	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
S
Swen Schillig 已提交
857
		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
L
Linus Torvalds 已提交
858 859
		break;
	case FSF_PORT_BOXED:
860 861 862
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
863
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3");
864
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
865 866
		break;
	case FSF_LUN_BOXED:
867 868
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
869
				    "fsafch4");
870
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
871 872
                break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
873
		switch (fsq->word[0]) {
L
Linus Torvalds 已提交
874
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
875
			zfcp_fc_test_link(zfcp_sdev->port);
876
			/* fall through */
L
Linus Torvalds 已提交
877
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
878
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
879 880 881 882
			break;
		}
		break;
	case FSF_GOOD:
S
Swen Schillig 已提交
883
		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
L
Linus Torvalds 已提交
884 885 886 887 888
		break;
	}
}

/**
889 890
 * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
 * @scmnd: The SCSI command to abort
S
Swen Schillig 已提交
891
 * Returns: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
892 893
 */

894
struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
L
Linus Torvalds 已提交
895
{
S
Swen Schillig 已提交
896
	struct zfcp_fsf_req *req = NULL;
897 898 899 900
	struct scsi_device *sdev = scmnd->device;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
	unsigned long old_req_id = (unsigned long) scmnd->host_scribble;
901

902
	spin_lock_irq(&qdio->req_q_lock);
903
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
904
		goto out;
905
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
906
				  SBAL_SFLAGS0_TYPE_READ,
907
				  qdio->adapter->pool.scsi_abort);
908 909
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
910
		goto out;
911
	}
912

913
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
914 915
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		goto out_error_free;
L
Linus Torvalds 已提交
916

917
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
918

919
	req->data = sdev;
S
Swen Schillig 已提交
920
	req->handler = zfcp_fsf_abort_fcp_command_handler;
921 922
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
923 924 925 926 927 928 929 930 931 932
	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:
933
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
934
	return req;
L
Linus Torvalds 已提交
935 936
}

S
Swen Schillig 已提交
937
static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
938
{
S
Swen Schillig 已提交
939
	struct zfcp_adapter *adapter = req->adapter;
940
	struct zfcp_fsf_ct_els *ct = req->data;
S
Swen Schillig 已提交
941
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
942

943
	ct->status = -EINVAL;
L
Linus Torvalds 已提交
944

S
Swen Schillig 已提交
945
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
946 947 948 949
		goto skip_fsfstatus;

	switch (header->fsf_status) {
        case FSF_GOOD:
950
		ct->status = 0;
951
		zfcp_dbf_san_res("fsscth2", req);
L
Linus Torvalds 已提交
952 953
		break;
        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
954
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
955 956 957 958 959
		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 已提交
960
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
961 962 963 964
			break;
                }
                break;
        case FSF_PORT_BOXED:
965
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
966
		break;
S
Swen Schillig 已提交
967
	case FSF_PORT_HANDLE_NOT_VALID:
968
		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1");
969
		/* fall through */
S
Swen Schillig 已提交
970
	case FSF_GENERIC_COMMAND_REJECTED:
L
Linus Torvalds 已提交
971 972 973 974
	case FSF_PAYLOAD_SIZE_MISMATCH:
	case FSF_REQUEST_SIZE_TOO_LARGE:
	case FSF_RESPONSE_SIZE_TOO_LARGE:
	case FSF_SBAL_MISMATCH:
S
Swen Schillig 已提交
975
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
976 977 978 979
		break;
	}

skip_fsfstatus:
980 981
	if (ct->handler)
		ct->handler(ct->handler_data);
S
Swen Schillig 已提交
982
}
L
Linus Torvalds 已提交
983

984 985
static void zfcp_fsf_setup_ct_els_unchained(struct zfcp_qdio *qdio,
					    struct zfcp_qdio_req *q_req,
986 987 988
					    struct scatterlist *sg_req,
					    struct scatterlist *sg_resp)
{
989 990 991
	zfcp_qdio_fill_next(qdio, q_req, sg_virt(sg_req), sg_req->length);
	zfcp_qdio_fill_next(qdio, q_req, sg_virt(sg_resp), sg_resp->length);
	zfcp_qdio_set_sbale_last(qdio, q_req);
992 993
}

994 995
static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
				       struct scatterlist *sg_req,
996
				       struct scatterlist *sg_resp)
S
Swen Schillig 已提交
997
{
998
	struct zfcp_adapter *adapter = req->adapter;
999 1000
	struct zfcp_qdio *qdio = adapter->qdio;
	struct fsf_qtcb *qtcb = req->qtcb;
1001
	u32 feat = adapter->adapter_features;
S
Swen Schillig 已提交
1002

1003 1004 1005
	if (zfcp_adapter_multi_buffer_active(adapter)) {
		if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
			return -EIO;
1006 1007
		qtcb->bottom.support.req_buf_length =
			zfcp_qdio_real_bytes(sg_req);
1008 1009
		if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
			return -EIO;
1010 1011
		qtcb->bottom.support.resp_buf_length =
			zfcp_qdio_real_bytes(sg_resp);
1012

1013
		zfcp_qdio_set_data_div(qdio, &req->qdio_req, sg_nents(sg_req));
1014 1015
		zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
		zfcp_qdio_set_scount(qdio, &req->qdio_req);
1016 1017 1018 1019
		return 0;
	}

	/* use single, unchained SBAL if it can hold the request */
1020
	if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
1021
		zfcp_fsf_setup_ct_els_unchained(qdio, &req->qdio_req,
1022
						sg_req, sg_resp);
1023 1024 1025
		return 0;
	}

1026 1027 1028 1029
	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS))
		return -EOPNOTSUPP;

	if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
1030
		return -EIO;
S
Swen Schillig 已提交
1031

1032 1033 1034 1035 1036 1037
	qtcb->bottom.support.req_buf_length = zfcp_qdio_real_bytes(sg_req);

	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
	zfcp_qdio_skip_to_last_sbale(qdio, &req->qdio_req);

	if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
1038
		return -EIO;
1039 1040 1041 1042

	qtcb->bottom.support.resp_buf_length = zfcp_qdio_real_bytes(sg_resp);

	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1043

1044 1045 1046 1047 1048 1049
	return 0;
}

static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
				 struct scatterlist *sg_req,
				 struct scatterlist *sg_resp,
1050
				 unsigned int timeout)
1051 1052 1053
{
	int ret;

1054
	ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp);
1055 1056 1057
	if (ret)
		return ret;

1058
	/* common settings for ct/gs and els requests */
1059 1060
	if (timeout > 255)
		timeout = 255; /* max value accepted by hardware */
1061
	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
1062 1063
	req->qtcb->bottom.support.timeout = timeout;
	zfcp_fsf_start_timer(req, (timeout + 10) * HZ);
S
Swen Schillig 已提交
1064 1065

	return 0;
L
Linus Torvalds 已提交
1066 1067 1068
}

/**
S
Swen Schillig 已提交
1069 1070 1071
 * 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
L
Linus Torvalds 已提交
1072
 */
1073
int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
1074 1075
		     struct zfcp_fsf_ct_els *ct, mempool_t *pool,
		     unsigned int timeout)
L
Linus Torvalds 已提交
1076
{
1077
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
S
Swen Schillig 已提交
1078 1079
	struct zfcp_fsf_req *req;
	int ret = -EIO;
L
Linus Torvalds 已提交
1080

1081
	spin_lock_irq(&qdio->req_q_lock);
1082
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1083
		goto out;
L
Linus Torvalds 已提交
1084

1085
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC,
1086
				  SBAL_SFLAGS0_TYPE_WRITE_READ, pool);
1087

1088
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1089 1090
		ret = PTR_ERR(req);
		goto out;
1091 1092
	}

1093
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1094
	ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout);
C
Christof Schmitt 已提交
1095
	if (ret)
L
Linus Torvalds 已提交
1096 1097
		goto failed_send;

S
Swen Schillig 已提交
1098
	req->handler = zfcp_fsf_send_ct_handler;
1099
	req->qtcb->header.port_handle = wka_port->handle;
1100
	ct->d_id = wka_port->d_id;
S
Swen Schillig 已提交
1101 1102
	req->data = ct;

1103
	zfcp_dbf_san_req("fssct_1", req, wka_port->d_id);
L
Linus Torvalds 已提交
1104

S
Swen Schillig 已提交
1105 1106 1107
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;
L
Linus Torvalds 已提交
1108

S
Swen Schillig 已提交
1109
	goto out;
L
Linus Torvalds 已提交
1110

S
Swen Schillig 已提交
1111 1112 1113
failed_send:
	zfcp_fsf_req_free(req);
out:
1114
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1115
	return ret;
L
Linus Torvalds 已提交
1116 1117
}

S
Swen Schillig 已提交
1118
static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1119
{
1120
	struct zfcp_fsf_ct_els *send_els = req->data;
S
Swen Schillig 已提交
1121
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1122

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

S
Swen Schillig 已提交
1125
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
1126 1127 1128 1129
		goto skip_fsfstatus;

	switch (header->fsf_status) {
	case FSF_GOOD:
S
Swen Schillig 已提交
1130
		send_els->status = 0;
1131
		zfcp_dbf_san_res("fsselh1", req);
L
Linus Torvalds 已提交
1132 1133
		break;
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
1134
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
1135 1136 1137 1138 1139 1140
		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_RETRY_IF_POSSIBLE:
S
Swen Schillig 已提交
1141
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1142 1143 1144 1145 1146 1147 1148 1149
			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;
S
Swen Schillig 已提交
1150
	case FSF_SBAL_MISMATCH:
L
Lucas De Marchi 已提交
1151
		/* should never occur, avoided in zfcp_fsf_send_els */
S
Swen Schillig 已提交
1152
		/* fall through */
L
Linus Torvalds 已提交
1153
	default:
S
Swen Schillig 已提交
1154
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1155 1156 1157
		break;
	}
skip_fsfstatus:
H
Heiko Carstens 已提交
1158
	if (send_els->handler)
L
Linus Torvalds 已提交
1159
		send_els->handler(send_els->handler_data);
S
Swen Schillig 已提交
1160
}
L
Linus Torvalds 已提交
1161

S
Swen Schillig 已提交
1162 1163 1164 1165
/**
 * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
 * @els: pointer to struct zfcp_send_els with data for the command
 */
1166
int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
1167
		      struct zfcp_fsf_ct_els *els, unsigned int timeout)
S
Swen Schillig 已提交
1168 1169
{
	struct zfcp_fsf_req *req;
1170
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1171 1172
	int ret = -EIO;

1173
	spin_lock_irq(&qdio->req_q_lock);
1174
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1175
		goto out;
1176

1177
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS,
1178
				  SBAL_SFLAGS0_TYPE_WRITE_READ, NULL);
1179

1180
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1181 1182 1183 1184
		ret = PTR_ERR(req);
		goto out;
	}

1185
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1186

1187 1188
	if (!zfcp_adapter_multi_buffer_active(adapter))
		zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
1189 1190

	ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout);
1191

S
Swen Schillig 已提交
1192 1193 1194
	if (ret)
		goto failed_send;

1195
	hton24(req->qtcb->bottom.support.d_id, d_id);
S
Swen Schillig 已提交
1196
	req->handler = zfcp_fsf_send_els_handler;
1197
	els->d_id = d_id;
S
Swen Schillig 已提交
1198 1199
	req->data = els;

1200
	zfcp_dbf_san_req("fssels1", req, d_id);
S
Swen Schillig 已提交
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210

	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;

	goto out;

failed_send:
	zfcp_fsf_req_free(req);
out:
1211
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1212
	return ret;
L
Linus Torvalds 已提交
1213 1214
}

S
Swen Schillig 已提交
1215
int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1216
{
S
Swen Schillig 已提交
1217
	struct zfcp_fsf_req *req;
1218
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1219 1220
	int retval = -EIO;

1221
	spin_lock_irq(&qdio->req_q_lock);
1222
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1223
		goto out;
1224

1225
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
1226
				  SBAL_SFLAGS0_TYPE_READ,
1227
				  qdio->adapter->pool.erp_req);
1228

1229
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1230 1231
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
1232 1233
	}

1234
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1235
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1236

S
Swen Schillig 已提交
1237
	req->qtcb->bottom.config.feature_selection =
1238
			FSF_FEATURE_NOTIFICATION_LOST |
1239
			FSF_FEATURE_UPDATE_ALERT;
S
Swen Schillig 已提交
1240 1241
	req->erp_action = erp_action;
	req->handler = zfcp_fsf_exchange_config_data_handler;
1242
	erp_action->fsf_req_id = req->req_id;
L
Linus Torvalds 已提交
1243

1244
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1245
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1246
	if (retval) {
S
Swen Schillig 已提交
1247
		zfcp_fsf_req_free(req);
1248
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1249
	}
S
Swen Schillig 已提交
1250
out:
1251
	spin_unlock_irq(&qdio->req_q_lock);
1252 1253
	return retval;
}
L
Linus Torvalds 已提交
1254

1255
int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
S
Swen Schillig 已提交
1256
				       struct fsf_qtcb_bottom_config *data)
1257
{
S
Swen Schillig 已提交
1258 1259 1260
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;

1261
	spin_lock_irq(&qdio->req_q_lock);
1262
	if (zfcp_qdio_sbal_get(qdio))
1263
		goto out_unlock;
S
Swen Schillig 已提交
1264

1265
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
1266
				  SBAL_SFLAGS0_TYPE_READ, NULL);
1267

1268
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1269
		retval = PTR_ERR(req);
1270
		goto out_unlock;
1271 1272
	}

1273
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
S
Swen Schillig 已提交
1274
	req->handler = zfcp_fsf_exchange_config_data_handler;
1275

S
Swen Schillig 已提交
1276
	req->qtcb->bottom.config.feature_selection =
1277 1278 1279 1280
			FSF_FEATURE_NOTIFICATION_LOST |
			FSF_FEATURE_UPDATE_ALERT;

	if (data)
S
Swen Schillig 已提交
1281
		req->data = data;
1282

S
Swen Schillig 已提交
1283 1284
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
1285
	spin_unlock_irq(&qdio->req_q_lock);
C
Christof Schmitt 已提交
1286
	if (!retval)
1287
		wait_for_completion(&req->completion);
1288

S
Swen Schillig 已提交
1289
	zfcp_fsf_req_free(req);
1290
	return retval;
1291

1292
out_unlock:
1293
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1294 1295 1296 1297 1298
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data - request information about local port
1299
 * @erp_action: ERP action for the adapter for which port data is requested
S
Swen Schillig 已提交
1300
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1301
 */
S
Swen Schillig 已提交
1302
int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1303
{
1304
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1305 1306
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1307

1308
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1309
		return -EOPNOTSUPP;
L
Linus Torvalds 已提交
1310

1311
	spin_lock_irq(&qdio->req_q_lock);
1312
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1313
		goto out;
1314

1315
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
1316
				  SBAL_SFLAGS0_TYPE_READ,
1317
				  qdio->adapter->pool.erp_req);
1318

1319
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1320 1321
		retval = PTR_ERR(req);
		goto out;
1322 1323
	}

1324
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1325
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1326

S
Swen Schillig 已提交
1327 1328
	req->handler = zfcp_fsf_exchange_port_data_handler;
	req->erp_action = erp_action;
1329
	erp_action->fsf_req_id = req->req_id;
1330

1331
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1332
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1333
	if (retval) {
S
Swen Schillig 已提交
1334
		zfcp_fsf_req_free(req);
1335
		erp_action->fsf_req_id = 0;
1336
	}
S
Swen Schillig 已提交
1337
out:
1338
	spin_unlock_irq(&qdio->req_q_lock);
1339 1340 1341 1342 1343
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data_sync - request information about local port
1344
 * @qdio: pointer to struct zfcp_qdio
S
Swen Schillig 已提交
1345 1346
 * @data: pointer to struct fsf_qtcb_bottom_port
 * Returns: 0 on success, error otherwise
1347
 */
1348
int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
S
Swen Schillig 已提交
1349
				     struct fsf_qtcb_bottom_port *data)
1350
{
S
Swen Schillig 已提交
1351 1352
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;
1353

1354
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1355 1356
		return -EOPNOTSUPP;

1357
	spin_lock_irq(&qdio->req_q_lock);
1358
	if (zfcp_qdio_sbal_get(qdio))
1359
		goto out_unlock;
S
Swen Schillig 已提交
1360

1361
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
1362
				  SBAL_SFLAGS0_TYPE_READ, NULL);
1363

1364
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1365
		retval = PTR_ERR(req);
1366
		goto out_unlock;
L
Linus Torvalds 已提交
1367 1368
	}

1369
	if (data)
S
Swen Schillig 已提交
1370
		req->data = data;
1371

1372
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1373

S
Swen Schillig 已提交
1374 1375 1376
	req->handler = zfcp_fsf_exchange_port_data_handler;
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
1377
	spin_unlock_irq(&qdio->req_q_lock);
1378

C
Christof Schmitt 已提交
1379
	if (!retval)
1380 1381
		wait_for_completion(&req->completion);

S
Swen Schillig 已提交
1382
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1383 1384

	return retval;
1385 1386

out_unlock:
1387
	spin_unlock_irq(&qdio->req_q_lock);
1388
	return retval;
L
Linus Torvalds 已提交
1389 1390
}

S
Swen Schillig 已提交
1391
static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1392
{
S
Swen Schillig 已提交
1393 1394
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
1395
	struct fc_els_flogi *plogi;
L
Linus Torvalds 已提交
1396

S
Swen Schillig 已提交
1397
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1398
		goto out;
L
Linus Torvalds 已提交
1399 1400 1401 1402 1403

	switch (header->fsf_status) {
	case FSF_PORT_ALREADY_OPEN:
		break;
	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
S
Swen Schillig 已提交
1404
		dev_warn(&req->adapter->ccw_device->dev,
1405
			 "Not enough FCP adapter resources to open "
1406 1407
			 "remote port 0x%016Lx\n",
			 (unsigned long long)port->wwpn);
1408 1409
		zfcp_erp_set_port_status(port,
					 ZFCP_STATUS_COMMON_ERP_FAILED);
S
Swen Schillig 已提交
1410
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1411 1412 1413 1414
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1415 1416
			/* no zfcp_fc_test_link() with failed open port */
			/* fall through */
L
Linus Torvalds 已提交
1417 1418
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
		case FSF_SQ_NO_RETRY_POSSIBLE:
S
Swen Schillig 已提交
1419
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1420 1421 1422 1423 1424
			break;
		}
		break;
	case FSF_GOOD:
		port->handle = header->port_handle;
1425
		atomic_or(ZFCP_STATUS_COMMON_OPEN |
L
Linus Torvalds 已提交
1426
				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1427
		atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_BOXED,
1428
		                  &port->status);
L
Linus Torvalds 已提交
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
		/* 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.
		 */
1444
		plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els;
1445
		if (req->qtcb->bottom.support.els1_length >=
1446
		    FSF_PLOGI_MIN_LEN)
S
Swen Schillig 已提交
1447
				zfcp_fc_plogi_evaluate(port, plogi);
L
Linus Torvalds 已提交
1448 1449
		break;
	case FSF_UNKNOWN_OP_SUBTYPE:
S
Swen Schillig 已提交
1450
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1451 1452
		break;
	}
1453 1454

out:
1455
	put_device(&port->dev);
L
Linus Torvalds 已提交
1456 1457
}

S
Swen Schillig 已提交
1458 1459 1460 1461
/**
 * 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 已提交
1462
 */
S
Swen Schillig 已提交
1463
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1464
{
1465
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1466
	struct zfcp_port *port = erp_action->port;
1467
	struct zfcp_fsf_req *req;
S
Swen Schillig 已提交
1468 1469
	int retval = -EIO;

1470
	spin_lock_irq(&qdio->req_q_lock);
1471
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1472 1473
		goto out;

1474
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1475
				  SBAL_SFLAGS0_TYPE_READ,
1476
				  qdio->adapter->pool.erp_req);
1477

1478
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1479
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1480
		goto out;
S
Swen Schillig 已提交
1481
	}
L
Linus Torvalds 已提交
1482

1483
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1484
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1485

S
Swen Schillig 已提交
1486
	req->handler = zfcp_fsf_open_port_handler;
1487
	hton24(req->qtcb->bottom.support.d_id, port->d_id);
1488
	req->data = port;
S
Swen Schillig 已提交
1489
	req->erp_action = erp_action;
1490
	erp_action->fsf_req_id = req->req_id;
1491
	get_device(&port->dev);
S
Swen Schillig 已提交
1492

1493
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1494
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1495
	if (retval) {
S
Swen Schillig 已提交
1496
		zfcp_fsf_req_free(req);
1497
		erp_action->fsf_req_id = 0;
1498
		put_device(&port->dev);
L
Linus Torvalds 已提交
1499
	}
S
Swen Schillig 已提交
1500
out:
1501
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1502 1503 1504
	return retval;
}

S
Swen Schillig 已提交
1505
static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1506
{
S
Swen Schillig 已提交
1507
	struct zfcp_port *port = req->data;
L
Linus Torvalds 已提交
1508

S
Swen Schillig 已提交
1509
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1510
		return;
L
Linus Torvalds 已提交
1511

S
Swen Schillig 已提交
1512
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1513
	case FSF_PORT_HANDLE_NOT_VALID:
1514
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1");
S
Swen Schillig 已提交
1515
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1516 1517 1518 1519
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		break;
	case FSF_GOOD:
1520
		zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN);
L
Linus Torvalds 已提交
1521 1522 1523 1524
		break;
	}
}

S
Swen Schillig 已提交
1525 1526 1527 1528
/**
 * 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 已提交
1529
 */
S
Swen Schillig 已提交
1530
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1531
{
1532
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1533 1534 1535
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1536
	spin_lock_irq(&qdio->req_q_lock);
1537
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1538 1539
		goto out;

1540
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1541
				  SBAL_SFLAGS0_TYPE_READ,
1542
				  qdio->adapter->pool.erp_req);
1543

1544
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1545
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1546
		goto out;
S
Swen Schillig 已提交
1547
	}
L
Linus Torvalds 已提交
1548

1549
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1550
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1551

S
Swen Schillig 已提交
1552 1553 1554 1555
	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;
1556
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1557

1558
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1559
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1560
	if (retval) {
S
Swen Schillig 已提交
1561
		zfcp_fsf_req_free(req);
1562
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1563
	}
S
Swen Schillig 已提交
1564
out:
1565
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1566 1567 1568
	return retval;
}

1569 1570
static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
{
1571
	struct zfcp_fc_wka_port *wka_port = req->data;
1572 1573 1574
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
1575
		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1576 1577 1578 1579 1580 1581 1582
		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);
1583
		/* fall through */
1584 1585
	case FSF_ADAPTER_STATUS_AVAILABLE:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1586
		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1587 1588 1589
		break;
	case FSF_GOOD:
		wka_port->handle = header->port_handle;
1590 1591
		/* fall through */
	case FSF_PORT_ALREADY_OPEN:
1592
		wka_port->status = ZFCP_FC_WKA_PORT_ONLINE;
1593 1594 1595 1596 1597 1598 1599
	}
out:
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_open_wka_port - create and send open wka-port request
1600
 * @wka_port: pointer to struct zfcp_fc_wka_port
1601 1602
 * Returns: 0 on success, error otherwise
 */
1603
int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
1604
{
1605
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1606
	struct zfcp_fsf_req *req;
1607
	unsigned long req_id = 0;
1608 1609
	int retval = -EIO;

1610
	spin_lock_irq(&qdio->req_q_lock);
1611
	if (zfcp_qdio_sbal_get(qdio))
1612 1613
		goto out;

1614
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1615
				  SBAL_SFLAGS0_TYPE_READ,
1616
				  qdio->adapter->pool.erp_req);
1617

1618
	if (IS_ERR(req)) {
1619 1620 1621 1622
		retval = PTR_ERR(req);
		goto out;
	}

1623
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1624
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1625 1626

	req->handler = zfcp_fsf_open_wka_port_handler;
1627
	hton24(req->qtcb->bottom.support.d_id, wka_port->d_id);
1628 1629
	req->data = wka_port;

1630 1631
	req_id = req->req_id;

1632 1633 1634 1635 1636
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
	if (retval)
		zfcp_fsf_req_free(req);
out:
1637
	spin_unlock_irq(&qdio->req_q_lock);
1638
	if (!retval)
1639
		zfcp_dbf_rec_run_wka("fsowp_1", wka_port, req_id);
1640 1641 1642 1643 1644
	return retval;
}

static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
{
1645
	struct zfcp_fc_wka_port *wka_port = req->data;
1646 1647 1648

	if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1649
		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1");
1650 1651
	}

1652
	wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1653 1654 1655 1656 1657
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_close_wka_port - create and send close wka port request
1658
 * @wka_port: WKA port to open
1659 1660
 * Returns: 0 on success, error otherwise
 */
1661
int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
1662
{
1663
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1664
	struct zfcp_fsf_req *req;
1665
	unsigned long req_id = 0;
1666 1667
	int retval = -EIO;

1668
	spin_lock_irq(&qdio->req_q_lock);
1669
	if (zfcp_qdio_sbal_get(qdio))
1670 1671
		goto out;

1672
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1673
				  SBAL_SFLAGS0_TYPE_READ,
1674
				  qdio->adapter->pool.erp_req);
1675

1676
	if (IS_ERR(req)) {
1677 1678 1679 1680
		retval = PTR_ERR(req);
		goto out;
	}

1681
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1682
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1683 1684 1685 1686 1687

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

1688 1689
	req_id = req->req_id;

1690 1691 1692 1693 1694
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
	if (retval)
		zfcp_fsf_req_free(req);
out:
1695
	spin_unlock_irq(&qdio->req_q_lock);
1696
	if (!retval)
1697
		zfcp_dbf_rec_run_wka("fscwp_1", wka_port, req_id);
1698 1699 1700
	return retval;
}

S
Swen Schillig 已提交
1701
static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1702
{
S
Swen Schillig 已提交
1703 1704
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
1705
	struct scsi_device *sdev;
L
Linus Torvalds 已提交
1706

S
Swen Schillig 已提交
1707
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1708
		return;
L
Linus Torvalds 已提交
1709 1710 1711

	switch (header->fsf_status) {
	case FSF_PORT_HANDLE_NOT_VALID:
1712
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1");
S
Swen Schillig 已提交
1713
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1714 1715
		break;
	case FSF_PORT_BOXED:
1716 1717
		/* can't use generic zfcp_erp_modify_port_status because
		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
1718
		atomic_andnot(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1719 1720
		shost_for_each_device(sdev, port->adapter->scsi_host)
			if (sdev_to_zfcp(sdev)->port == port)
1721
				atomic_andnot(ZFCP_STATUS_COMMON_OPEN,
1722
						  &sdev_to_zfcp(sdev)->status);
1723 1724
		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
1725
				     "fscpph2");
1726
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1727 1728 1729 1730
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
S
Swen Schillig 已提交
1731
			/* fall through */
L
Linus Torvalds 已提交
1732
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1733
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1734 1735 1736 1737 1738 1739 1740
			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
		 */
1741
		atomic_andnot(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1742 1743
		shost_for_each_device(sdev, port->adapter->scsi_host)
			if (sdev_to_zfcp(sdev)->port == port)
1744
				atomic_andnot(ZFCP_STATUS_COMMON_OPEN,
1745
						  &sdev_to_zfcp(sdev)->status);
L
Linus Torvalds 已提交
1746 1747 1748 1749
		break;
	}
}

S
Swen Schillig 已提交
1750 1751 1752 1753
/**
 * zfcp_fsf_close_physical_port - close physical port
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success
L
Linus Torvalds 已提交
1754
 */
S
Swen Schillig 已提交
1755
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1756
{
1757
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1758 1759 1760
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1761
	spin_lock_irq(&qdio->req_q_lock);
1762
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1763 1764
		goto out;

1765
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
1766
				  SBAL_SFLAGS0_TYPE_READ,
1767
				  qdio->adapter->pool.erp_req);
1768

1769
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1770 1771 1772
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1773

1774
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1775
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1776

S
Swen Schillig 已提交
1777 1778 1779 1780
	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;
1781
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1782

1783
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1784
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1785
	if (retval) {
S
Swen Schillig 已提交
1786
		zfcp_fsf_req_free(req);
1787
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1788
	}
S
Swen Schillig 已提交
1789
out:
1790
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1791 1792 1793
	return retval;
}

1794
static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1795
{
S
Swen Schillig 已提交
1796
	struct zfcp_adapter *adapter = req->adapter;
1797
	struct scsi_device *sdev = req->data;
1798
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
1799
	struct fsf_qtcb_header *header = &req->qtcb->header;
1800
	union fsf_status_qual *qual = &header->fsf_status_qual;
L
Linus Torvalds 已提交
1801

S
Swen Schillig 已提交
1802
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1803
		return;
L
Linus Torvalds 已提交
1804

1805 1806
	zfcp_sdev = sdev_to_zfcp(sdev);

1807
	atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1808
			  ZFCP_STATUS_COMMON_ACCESS_BOXED,
1809
			  &zfcp_sdev->status);
L
Linus Torvalds 已提交
1810 1811 1812 1813

	switch (header->fsf_status) {

	case FSF_PORT_HANDLE_NOT_VALID:
1814
		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
S
Swen Schillig 已提交
1815
		/* fall through */
L
Linus Torvalds 已提交
1816 1817 1818
	case FSF_LUN_ALREADY_OPEN:
		break;
	case FSF_PORT_BOXED:
1819 1820 1821
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
1822
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2");
1823
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1824 1825
		break;
	case FSF_LUN_SHARING_VIOLATION:
1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836
		if (qual->word[0])
			dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
				 "LUN 0x%Lx on port 0x%Lx is already in "
				 "use by CSS%d, MIF Image ID %x\n",
				 zfcp_scsi_dev_lun(sdev),
				 (unsigned long long)zfcp_sdev->port->wwpn,
				 qual->fsf_queue_designator.cssid,
				 qual->fsf_queue_designator.hla);
		zfcp_erp_set_lun_status(sdev,
					ZFCP_STATUS_COMMON_ERP_FAILED |
					ZFCP_STATUS_COMMON_ACCESS_DENIED);
S
Swen Schillig 已提交
1837
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1838 1839
		break;
	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
S
Swen Schillig 已提交
1840
		dev_warn(&adapter->ccw_device->dev,
1841 1842
			 "No handle is available for LUN "
			 "0x%016Lx on port 0x%016Lx\n",
1843 1844
			 (unsigned long long)zfcp_scsi_dev_lun(sdev),
			 (unsigned long long)zfcp_sdev->port->wwpn);
1845
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
S
Swen Schillig 已提交
1846 1847 1848
		/* fall through */
	case FSF_INVALID_COMMAND_OPTION:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1849 1850 1851 1852
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1853
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
1854
			/* fall through */
L
Linus Torvalds 已提交
1855
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1856
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1857 1858 1859 1860 1861
			break;
		}
		break;

	case FSF_GOOD:
1862
		zfcp_sdev->lun_handle = header->lun_handle;
1863
		atomic_or(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
L
Linus Torvalds 已提交
1864 1865 1866 1867
		break;
	}
}

S
Swen Schillig 已提交
1868
/**
1869
 * zfcp_fsf_open_lun - open LUN
S
Swen Schillig 已提交
1870 1871
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1872
 */
1873
int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1874
{
S
Swen Schillig 已提交
1875
	struct zfcp_adapter *adapter = erp_action->adapter;
1876
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1877 1878 1879
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1880
	spin_lock_irq(&qdio->req_q_lock);
1881
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1882 1883
		goto out;

1884
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1885
				  SBAL_SFLAGS0_TYPE_READ,
1886
				  adapter->pool.erp_req);
1887

1888
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1889 1890 1891 1892
		retval = PTR_ERR(req);
		goto out;
	}

1893
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1894
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1895

S
Swen Schillig 已提交
1896
	req->qtcb->header.port_handle = erp_action->port->handle;
1897 1898 1899
	req->qtcb->bottom.support.fcp_lun = zfcp_scsi_dev_lun(erp_action->sdev);
	req->handler = zfcp_fsf_open_lun_handler;
	req->data = erp_action->sdev;
S
Swen Schillig 已提交
1900
	req->erp_action = erp_action;
1901
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1902 1903 1904 1905

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

1906
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1907
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1908
	if (retval) {
S
Swen Schillig 已提交
1909
		zfcp_fsf_req_free(req);
1910
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1911
	}
S
Swen Schillig 已提交
1912
out:
1913
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1914 1915 1916
	return retval;
}

1917
static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1918
{
1919
	struct scsi_device *sdev = req->data;
1920
	struct zfcp_scsi_dev *zfcp_sdev;
L
Linus Torvalds 已提交
1921

S
Swen Schillig 已提交
1922
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1923
		return;
L
Linus Torvalds 已提交
1924

1925 1926
	zfcp_sdev = sdev_to_zfcp(sdev);

S
Swen Schillig 已提交
1927
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1928
	case FSF_PORT_HANDLE_NOT_VALID:
1929
		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1");
S
Swen Schillig 已提交
1930
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1931 1932
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
1933
		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2");
S
Swen Schillig 已提交
1934
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1935 1936
		break;
	case FSF_PORT_BOXED:
1937 1938 1939
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
1940
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3");
1941
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1942 1943
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
1944
		switch (req->qtcb->header.fsf_status_qual.word[0]) {
L
Linus Torvalds 已提交
1945
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1946
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
1947
			/* fall through */
L
Linus Torvalds 已提交
1948
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1949
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1950 1951 1952 1953
			break;
		}
		break;
	case FSF_GOOD:
1954
		atomic_andnot(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
L
Linus Torvalds 已提交
1955 1956 1957 1958 1959
		break;
	}
}

/**
1960 1961
 * zfcp_fsf_close_LUN - close LUN
 * @erp_action: pointer to erp_action triggering the "close LUN"
S
Swen Schillig 已提交
1962
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1963
 */
1964
int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1965
{
1966
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1967
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
S
Swen Schillig 已提交
1968 1969
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1970

1971
	spin_lock_irq(&qdio->req_q_lock);
1972
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1973
		goto out;
1974

1975
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
1976
				  SBAL_SFLAGS0_TYPE_READ,
1977
				  qdio->adapter->pool.erp_req);
1978

1979
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1980 1981 1982
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1983

1984
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1985
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1986

S
Swen Schillig 已提交
1987
	req->qtcb->header.port_handle = erp_action->port->handle;
1988 1989 1990
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->handler = zfcp_fsf_close_lun_handler;
	req->data = erp_action->sdev;
S
Swen Schillig 已提交
1991
	req->erp_action = erp_action;
1992
	erp_action->fsf_req_id = req->req_id;
1993

1994
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1995 1996 1997
	retval = zfcp_fsf_req_send(req);
	if (retval) {
		zfcp_fsf_req_free(req);
1998
		erp_action->fsf_req_id = 0;
S
Swen Schillig 已提交
1999 2000
	}
out:
2001
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
2002
	return retval;
L
Linus Torvalds 已提交
2003 2004
}

2005 2006 2007
static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
{
	lat_rec->sum += lat;
S
Swen Schillig 已提交
2008 2009
	lat_rec->min = min(lat_rec->min, lat);
	lat_rec->max = max(lat_rec->max, lat);
2010 2011
}

2012
static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
2013
{
2014 2015
	struct fsf_qual_latency_info *lat_in;
	struct latency_cont *lat = NULL;
2016
	struct zfcp_scsi_dev *zfcp_sdev;
2017 2018
	struct zfcp_blk_drv_data blktrc;
	int ticks = req->adapter->timer_ticks;
2019

2020
	lat_in = &req->qtcb->prefix.prot_status_qual.latency_info;
2021

2022 2023 2024 2025
	blktrc.flags = 0;
	blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		blktrc.flags |= ZFCP_BLK_REQ_ERROR;
2026
	blktrc.inb_usage = 0;
2027
	blktrc.outb_usage = req->qdio_req.qdio_outb_usage;
2028

2029 2030
	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
	    !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2031
		zfcp_sdev = sdev_to_zfcp(scsi->device);
2032 2033 2034 2035 2036
		blktrc.flags |= ZFCP_BLK_LAT_VALID;
		blktrc.channel_lat = lat_in->channel_lat * ticks;
		blktrc.fabric_lat = lat_in->fabric_lat * ticks;

		switch (req->qtcb->bottom.io.data_direction) {
2037 2038
		case FSF_DATADIR_DIF_READ_STRIP:
		case FSF_DATADIR_DIF_READ_CONVERT:
2039
		case FSF_DATADIR_READ:
2040
			lat = &zfcp_sdev->latencies.read;
2041
			break;
2042 2043
		case FSF_DATADIR_DIF_WRITE_INSERT:
		case FSF_DATADIR_DIF_WRITE_CONVERT:
2044
		case FSF_DATADIR_WRITE:
2045
			lat = &zfcp_sdev->latencies.write;
2046 2047
			break;
		case FSF_DATADIR_CMND:
2048
			lat = &zfcp_sdev->latencies.cmd;
2049 2050
			break;
		}
L
Linus Torvalds 已提交
2051

2052
		if (lat) {
2053
			spin_lock(&zfcp_sdev->latencies.lock);
2054 2055 2056
			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
			lat->counter++;
2057
			spin_unlock(&zfcp_sdev->latencies.lock);
2058
		}
S
Stefan Raspl 已提交
2059 2060
	}

2061 2062
	blk_add_driver_data(scsi->request->q, scsi->request, &blktrc,
			    sizeof(blktrc));
S
Stefan Raspl 已提交
2063 2064
}

2065 2066 2067 2068 2069 2070 2071
/**
 * zfcp_fsf_fcp_handler_common() - FCP response handler common to I/O and TMF.
 * @req: Pointer to FSF request.
 * @sdev: Pointer to SCSI device as request context.
 */
static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req,
					struct scsi_device *sdev)
S
Swen Schillig 已提交
2072
{
2073
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
2074 2075 2076
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
2077
		return;
L
Linus Torvalds 已提交
2078

2079 2080
	zfcp_sdev = sdev_to_zfcp(sdev);

S
Swen Schillig 已提交
2081 2082 2083
	switch (header->fsf_status) {
	case FSF_HANDLE_MISMATCH:
	case FSF_PORT_HANDLE_NOT_VALID:
2084
		zfcp_erp_adapter_reopen(req->adapter, 0, "fssfch1");
S
Swen Schillig 已提交
2085 2086 2087 2088
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_FCPLUN_NOT_VALID:
	case FSF_LUN_HANDLE_NOT_VALID:
2089
		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2");
S
Swen Schillig 已提交
2090
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2091
		break;
S
Swen Schillig 已提交
2092 2093
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
2094
		break;
S
Swen Schillig 已提交
2095 2096
	case FSF_DIRECTION_INDICATOR_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2097
			"Incorrect direction %d, LUN 0x%016Lx on port "
2098
			"0x%016Lx closed\n",
S
Swen Schillig 已提交
2099
			req->qtcb->bottom.io.data_direction,
2100 2101
			(unsigned long long)zfcp_scsi_dev_lun(sdev),
			(unsigned long long)zfcp_sdev->port->wwpn);
2102
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fssfch3");
S
Swen Schillig 已提交
2103 2104 2105 2106
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_CMND_LENGTH_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2107
			"Incorrect CDB length %d, LUN 0x%016Lx on "
2108
			"port 0x%016Lx closed\n",
S
Swen Schillig 已提交
2109
			req->qtcb->bottom.io.fcp_cmnd_length,
2110 2111
			(unsigned long long)zfcp_scsi_dev_lun(sdev),
			(unsigned long long)zfcp_sdev->port->wwpn);
2112
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fssfch4");
S
Swen Schillig 已提交
2113 2114 2115
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_PORT_BOXED:
2116 2117 2118
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
2119
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5");
2120
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2121 2122
		break;
	case FSF_LUN_BOXED:
2123 2124
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
2125
				    "fssfch6");
2126
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2127 2128 2129 2130
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		if (header->fsf_status_qual.word[0] ==
		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
2131
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
2132
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2133 2134
		break;
	}
2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148
}

static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
{
	struct scsi_cmnd *scpnt;
	struct fcp_resp_with_ext *fcp_rsp;
	unsigned long flags;

	read_lock_irqsave(&req->adapter->abort_lock, flags);

	scpnt = req->data;
	if (unlikely(!scpnt)) {
		read_unlock_irqrestore(&req->adapter->abort_lock, flags);
		return;
S
Swen Schillig 已提交
2149
	}
2150

2151
	zfcp_fsf_fcp_handler_common(req, scpnt->device);
2152

2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
		set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED);
		goto skip_fsfstatus;
	}

	switch (req->qtcb->header.fsf_status) {
	case FSF_INCONSISTENT_PROT_DATA:
	case FSF_INVALID_PROT_PARM:
		set_host_byte(scpnt, DID_ERROR);
		goto skip_fsfstatus;
	case FSF_BLOCK_GUARD_CHECK_FAILURE:
		zfcp_scsi_dif_sense_error(scpnt, 0x1);
		goto skip_fsfstatus;
	case FSF_APP_TAG_CHECK_FAILURE:
		zfcp_scsi_dif_sense_error(scpnt, 0x2);
		goto skip_fsfstatus;
	case FSF_REF_TAG_CHECK_FAILURE:
		zfcp_scsi_dif_sense_error(scpnt, 0x3);
		goto skip_fsfstatus;
	}
2173 2174
	BUILD_BUG_ON(sizeof(struct fcp_resp_with_ext) > FSF_FCP_RSP_SIZE);
	fcp_rsp = &req->qtcb->bottom.io.fcp_rsp.iu;
2175 2176 2177 2178
	zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt);

skip_fsfstatus:
	zfcp_fsf_req_trace(req, scpnt);
2179
	zfcp_dbf_scsi_result(scpnt, req);
2180 2181 2182 2183 2184 2185 2186 2187 2188 2189

	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!
	 */
	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
L
Linus Torvalds 已提交
2190 2191
}

2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
{
	switch (scsi_get_prot_op(scsi_cmnd)) {
	case SCSI_PROT_NORMAL:
		switch (scsi_cmnd->sc_data_direction) {
		case DMA_NONE:
			*data_dir = FSF_DATADIR_CMND;
			break;
		case DMA_FROM_DEVICE:
			*data_dir = FSF_DATADIR_READ;
			break;
		case DMA_TO_DEVICE:
			*data_dir = FSF_DATADIR_WRITE;
			break;
		case DMA_BIDIRECTIONAL:
			return -EINVAL;
		}
		break;

	case SCSI_PROT_READ_STRIP:
		*data_dir = FSF_DATADIR_DIF_READ_STRIP;
		break;
	case SCSI_PROT_WRITE_INSERT:
		*data_dir = FSF_DATADIR_DIF_WRITE_INSERT;
		break;
	case SCSI_PROT_READ_PASS:
		*data_dir = FSF_DATADIR_DIF_READ_CONVERT;
		break;
	case SCSI_PROT_WRITE_PASS:
		*data_dir = FSF_DATADIR_DIF_WRITE_CONVERT;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

S
Swen Schillig 已提交
2230
/**
2231
 * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
S
Swen Schillig 已提交
2232
 * @scsi_cmnd: scsi command to be sent
L
Linus Torvalds 已提交
2233
 */
2234
int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
L
Linus Torvalds 已提交
2235
{
S
Swen Schillig 已提交
2236
	struct zfcp_fsf_req *req;
2237
	struct fcp_cmnd *fcp_cmnd;
2238
	u8 sbtype = SBAL_SFLAGS0_TYPE_READ;
2239
	int retval = -EIO;
2240 2241 2242
	struct scsi_device *sdev = scsi_cmnd->device;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
2243
	struct zfcp_qdio *qdio = adapter->qdio;
2244
	struct fsf_qtcb_bottom_io *io;
2245
	unsigned long flags;
L
Linus Torvalds 已提交
2246

2247
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2248 2249
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return -EBUSY;
L
Linus Torvalds 已提交
2250

2251
	spin_lock_irqsave(&qdio->req_q_lock, flags);
2252
	if (atomic_read(&qdio->req_q_free) <= 0) {
2253
		atomic_inc(&qdio->req_q_full);
S
Swen Schillig 已提交
2254
		goto out;
2255
	}
2256

2257
	if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE)
2258
		sbtype = SBAL_SFLAGS0_TYPE_WRITE;
2259

2260
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2261
				  sbtype, adapter->pool.scsi_req);
2262

2263
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2264 2265 2266 2267
		retval = PTR_ERR(req);
		goto out;
	}

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

	io = &req->qtcb->bottom.io;
2271
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
S
Swen Schillig 已提交
2272
	req->data = scsi_cmnd;
2273
	req->handler = zfcp_fsf_fcp_cmnd_handler;
2274 2275
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
2276 2277
	io->service_class = FSF_CLASS_3;
	io->fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2278

2279 2280 2281
	if (scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) {
		io->data_block_length = scsi_cmnd->device->sector_size;
		io->ref_tag_value = scsi_get_lba(scsi_cmnd) & 0xFFFFFFFF;
L
Linus Torvalds 已提交
2282 2283
	}

2284 2285
	if (zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction))
		goto failed_scsi_cmnd;
2286

2287 2288
	BUILD_BUG_ON(sizeof(struct fcp_cmnd) > FSF_FCP_CMND_SIZE);
	fcp_cmnd = &req->qtcb->bottom.io.fcp_cmnd.iu;
2289
	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
L
Linus Torvalds 已提交
2290

2291 2292
	if ((scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) &&
	    scsi_prot_sg_count(scsi_cmnd)) {
2293 2294
		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
				       scsi_prot_sg_count(scsi_cmnd));
2295 2296 2297 2298 2299
		retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
						 scsi_prot_sglist(scsi_cmnd));
		if (retval)
			goto failed_scsi_cmnd;
		io->prot_data_length = zfcp_qdio_real_bytes(
2300 2301 2302
						scsi_prot_sglist(scsi_cmnd));
	}

2303 2304 2305
	retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
					 scsi_sglist(scsi_cmnd));
	if (unlikely(retval))
S
Swen Schillig 已提交
2306
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2307

2308
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
2309 2310
	if (zfcp_adapter_multi_buffer_active(adapter))
		zfcp_qdio_set_scount(qdio, &req->qdio_req);
2311

S
Swen Schillig 已提交
2312 2313 2314
	retval = zfcp_fsf_req_send(req);
	if (unlikely(retval))
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2315

S
Swen Schillig 已提交
2316
	goto out;
L
Linus Torvalds 已提交
2317

S
Swen Schillig 已提交
2318 2319 2320 2321
failed_scsi_cmnd:
	zfcp_fsf_req_free(req);
	scsi_cmnd->host_scribble = NULL;
out:
2322
	spin_unlock_irqrestore(&qdio->req_q_lock, flags);
S
Swen Schillig 已提交
2323
	return retval;
L
Linus Torvalds 已提交
2324 2325
}

2326 2327
static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
{
2328
	struct scsi_device *sdev = req->data;
2329 2330 2331
	struct fcp_resp_with_ext *fcp_rsp;
	struct fcp_resp_rsp_info *rsp_info;

2332
	zfcp_fsf_fcp_handler_common(req, sdev);
2333

2334
	fcp_rsp = &req->qtcb->bottom.io.fcp_rsp.iu;
2335 2336 2337 2338 2339 2340 2341
	rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];

	if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
}

L
Linus Torvalds 已提交
2342
/**
2343 2344 2345 2346 2347
 * zfcp_fsf_fcp_task_mgmt() - Send SCSI task management command (TMF).
 * @sdev: Pointer to SCSI device to send the task management command to.
 * @tm_flags: Unsigned byte for task management flags.
 *
 * Return: On success pointer to struct zfcp_fsf_req, %NULL otherwise.
L
Linus Torvalds 已提交
2348
 */
2349
struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev,
2350
					    u8 tm_flags)
L
Linus Torvalds 已提交
2351
{
S
Swen Schillig 已提交
2352
	struct zfcp_fsf_req *req = NULL;
2353
	struct fcp_cmnd *fcp_cmnd;
2354
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
2355
	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
L
Linus Torvalds 已提交
2356

2357
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2358 2359
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return NULL;
L
Linus Torvalds 已提交
2360

2361
	spin_lock_irq(&qdio->req_q_lock);
2362
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
2363
		goto out;
2364

2365
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2366
				  SBAL_SFLAGS0_TYPE_WRITE,
2367
				  qdio->adapter->pool.scsi_req);
2368

2369 2370
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
2371
		goto out;
2372
	}
L
Linus Torvalds 已提交
2373

2374 2375
	req->data = sdev;

2376
	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
2377 2378
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
2379 2380
	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
2381
	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2382

2383
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
2384

2385
	fcp_cmnd = &req->qtcb->bottom.io.fcp_cmnd.iu;
2386
	zfcp_fc_fcp_tm(fcp_cmnd, sdev, tm_flags);
L
Linus Torvalds 已提交
2387

S
Swen Schillig 已提交
2388 2389 2390
	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;
L
Linus Torvalds 已提交
2391

S
Swen Schillig 已提交
2392 2393 2394
	zfcp_fsf_req_free(req);
	req = NULL;
out:
2395
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
2396 2397
	return req;
}
L
Linus Torvalds 已提交
2398

2399 2400 2401 2402 2403
/**
 * zfcp_fsf_reqid_check - validate req_id contained in SBAL returned by QDIO
 * @adapter: pointer to struct zfcp_adapter
 * @sbal_idx: response queue index of SBAL to be processed
 */
2404
void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2405
{
2406
	struct zfcp_adapter *adapter = qdio->adapter;
2407
	struct qdio_buffer *sbal = qdio->res_q[sbal_idx];
2408 2409
	struct qdio_buffer_element *sbale;
	struct zfcp_fsf_req *fsf_req;
2410
	unsigned long req_id;
2411 2412 2413 2414 2415 2416
	int idx;

	for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {

		sbale = &sbal->element[idx];
		req_id = (unsigned long) sbale->addr;
2417
		fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id);
2418

2419
		if (!fsf_req) {
2420 2421 2422 2423
			/*
			 * Unknown request means that we have potentially memory
			 * corruption and must stop the machine immediately.
			 */
2424
			zfcp_qdio_siosl(adapter);
2425 2426
			panic("error: unknown req_id (%lx) on adapter %s.\n",
			      req_id, dev_name(&adapter->ccw_device->dev));
2427
		}
2428 2429 2430

		zfcp_fsf_req_complete(fsf_req);

2431
		if (likely(sbale->eflags & SBAL_EFLAGS_LAST_ENTRY))
2432 2433 2434
			break;
	}
}