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

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

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

21 22
struct kmem_cache *zfcp_fsf_qtcb_cache;

23 24 25
static void zfcp_fsf_request_timeout_handler(unsigned long data)
{
	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
26
	zfcp_qdio_siosl(adapter);
27
	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
28
				"fsrth_1");
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
}

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

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

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

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

87
	if (likely(req->qtcb))
88
		kmem_cache_free(zfcp_fsf_qtcb_cache, req->qtcb);
89
	kfree(req);
L
Linus Torvalds 已提交
90 91
}

S
Swen Schillig 已提交
92
static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
93
{
94
	unsigned long flags;
S
Swen Schillig 已提交
95 96 97
	struct fsf_status_read_buffer *sr_buf = req->data;
	struct zfcp_adapter *adapter = req->adapter;
	struct zfcp_port *port;
98
	int d_id = ntoh24(sr_buf->d_id);
L
Linus Torvalds 已提交
99

100 101
	read_lock_irqsave(&adapter->port_list_lock, flags);
	list_for_each_entry(port, &adapter->port_list, list)
S
Swen Schillig 已提交
102
		if (port->d_id == d_id) {
103
			zfcp_erp_port_reopen(port, 0, "fssrpc1");
104
			break;
S
Swen Schillig 已提交
105
		}
106
	read_unlock_irqrestore(&adapter->port_list_lock, flags);
L
Linus Torvalds 已提交
107 108
}

109
static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req,
S
Swen Schillig 已提交
110
					 struct fsf_link_down_info *link_down)
111
{
S
Swen Schillig 已提交
112
	struct zfcp_adapter *adapter = req->adapter;
113

S
Swen Schillig 已提交
114
	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
115 116
		return;

117
	atomic_or(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
118

119
	zfcp_scsi_schedule_rports_block(adapter);
120

S
Swen Schillig 已提交
121
	if (!link_down)
122
		goto out;
123

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

S
Swen Schillig 已提交
192
static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
193
{
S
Swen Schillig 已提交
194 195 196
	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 已提交
197

S
Swen Schillig 已提交
198 199
	switch (sr_buf->status_subtype) {
	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
200
		zfcp_fsf_link_down_info_eval(req, ldi);
L
Linus Torvalds 已提交
201
		break;
S
Swen Schillig 已提交
202
	case FSF_STATUS_READ_SUB_FDISC_FAILED:
203
		zfcp_fsf_link_down_info_eval(req, ldi);
L
Linus Torvalds 已提交
204
		break;
S
Swen Schillig 已提交
205
	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
206
		zfcp_fsf_link_down_info_eval(req, NULL);
207
	}
S
Swen Schillig 已提交
208
}
L
Linus Torvalds 已提交
209

S
Swen Schillig 已提交
210 211 212 213
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 已提交
214

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

222
	zfcp_dbf_hba_fsf_uss("fssrh_4", req);
L
Linus Torvalds 已提交
223

S
Swen Schillig 已提交
224 225 226
	switch (sr_buf->status_type) {
	case FSF_STATUS_READ_PORT_CLOSED:
		zfcp_fsf_status_read_port_closed(req);
L
Linus Torvalds 已提交
227
		break;
S
Swen Schillig 已提交
228 229
	case FSF_STATUS_READ_INCOMING_ELS:
		zfcp_fc_incoming_els(req);
L
Linus Torvalds 已提交
230
		break;
S
Swen Schillig 已提交
231
	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
L
Linus Torvalds 已提交
232
		break;
S
Swen Schillig 已提交
233
	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
234 235 236
		dev_warn(&adapter->ccw_device->dev,
			 "The error threshold for checksum statistics "
			 "has been exceeded\n");
237
		zfcp_dbf_hba_bit_err("fssrh_3", req);
L
Linus Torvalds 已提交
238
		break;
S
Swen Schillig 已提交
239 240
	case FSF_STATUS_READ_LINK_DOWN:
		zfcp_fsf_status_read_link_down(req);
241
		zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKDOWN, 0);
S
Swen Schillig 已提交
242 243 244
		break;
	case FSF_STATUS_READ_LINK_UP:
		dev_info(&adapter->ccw_device->dev,
245
			 "The local link has been restored\n");
S
Swen Schillig 已提交
246
		/* All ports should be marked as ready to run again */
247 248
		zfcp_erp_set_adapter_status(adapter,
					    ZFCP_STATUS_COMMON_RUNNING);
S
Swen Schillig 已提交
249 250 251
		zfcp_erp_adapter_reopen(adapter,
					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
					ZFCP_STATUS_COMMON_ERP_FAILED,
252
					"fssrh_2");
253 254
		zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0);

S
Swen Schillig 已提交
255 256 257
		break;
	case FSF_STATUS_READ_NOTIFICATION_LOST:
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
258
			zfcp_fc_conditional_port_scan(adapter);
S
Swen Schillig 已提交
259 260 261
		break;
	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
		adapter->adapter_features = sr_buf->payload.word[0];
L
Linus Torvalds 已提交
262 263 264
		break;
	}

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

S
Swen Schillig 已提交
268
	atomic_inc(&adapter->stat_miss);
269
	queue_work(adapter->work_queue, &adapter->stat_work);
S
Swen Schillig 已提交
270
}
L
Linus Torvalds 已提交
271

S
Swen Schillig 已提交
272 273 274 275 276 277 278 279 280 281 282 283
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,
284 285
			"The FCP adapter reported a problem "
			"that cannot be recovered\n");
286
		zfcp_qdio_siosl(req->adapter);
287
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1");
S
Swen Schillig 已提交
288 289 290 291
		break;
	}
	/* all non-return stats set FSFREQ_ERROR*/
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
292 293
}

S
Swen Schillig 已提交
294
static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
295
{
S
Swen Schillig 已提交
296 297
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
		return;
L
Linus Torvalds 已提交
298

S
Swen Schillig 已提交
299 300 301
	switch (req->qtcb->header.fsf_status) {
	case FSF_UNKNOWN_COMMAND:
		dev_err(&req->adapter->ccw_device->dev,
302
			"The FCP adapter does not recognize the command 0x%x\n",
S
Swen Schillig 已提交
303
			req->qtcb->header.fsf_command);
304
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1");
S
Swen Schillig 已提交
305 306 307 308 309 310 311
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		zfcp_fsf_fsfstatus_qual_eval(req);
		break;
	}
}
L
Linus Torvalds 已提交
312

S
Swen Schillig 已提交
313 314 315 316 317
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 已提交
318

S
Swen Schillig 已提交
319
	zfcp_dbf_hba_fsf_response(req);
L
Linus Torvalds 已提交
320

S
Swen Schillig 已提交
321
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
322
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
323 324
		return;
	}
L
Linus Torvalds 已提交
325

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

S
Swen Schillig 已提交
381 382 383 384 385 386 387 388 389
/**
 * 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.
 */
390
static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
391
{
S
Swen Schillig 已提交
392 393 394 395
	if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
		zfcp_fsf_status_read_handler(req);
		return;
	}
L
Linus Torvalds 已提交
396

S
Swen Schillig 已提交
397 398 399 400
	del_timer(&req->timer);
	zfcp_fsf_protstatus_eval(req);
	zfcp_fsf_fsfstatus_eval(req);
	req->handler(req);
L
Linus Torvalds 已提交
401

S
Swen Schillig 已提交
402
	if (req->erp_action)
403
		zfcp_erp_notify(req->erp_action, 0);
L
Linus Torvalds 已提交
404

S
Swen Schillig 已提交
405 406 407
	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
		zfcp_fsf_req_free(req);
	else
408
		complete(&req->completion);
S
Swen Schillig 已提交
409
}
L
Linus Torvalds 已提交
410

411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
/**
 * 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);
426
	zfcp_reqlist_move(adapter->req_list, &remove_queue);
427 428 429 430 431 432 433 434

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

435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
#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)
#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;
	if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED)
		fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED;
	return fdmi_speed;
}

S
Swen Schillig 已提交
463 464
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
{
465
	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
S
Swen Schillig 已提交
466 467
	struct zfcp_adapter *adapter = req->adapter;
	struct Scsi_Host *shost = adapter->scsi_host;
468
	struct fc_els_flogi *nsp, *plogi;
L
Linus Torvalds 已提交
469

470 471 472 473 474
	/* 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 已提交
475

S
Swen Schillig 已提交
476 477 478
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));

479 480
	fc_host_port_name(shost) = nsp->fl_wwpn;
	fc_host_node_name(shost) = nsp->fl_wwnn;
S
Swen Schillig 已提交
481 482
	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;

483
	adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK;
484 485
	adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
					 (u16)FSF_STATUS_READS_RECOM);
S
Swen Schillig 已提交
486 487 488 489

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

490 491 492 493 494 495 496 497 498 499 500 501 502
	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 已提交
503 504
	switch (bottom->fc_topology) {
	case FSF_TOPO_P2P:
505
		adapter->peer_d_id = ntoh24(bottom->peer_d_id);
506 507
		adapter->peer_wwpn = plogi->fl_wwpn;
		adapter->peer_wwnn = plogi->fl_wwnn;
S
Swen Schillig 已提交
508 509 510
		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
		break;
	case FSF_TOPO_FABRIC:
511 512 513 514
		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 已提交
515 516 517
		break;
	case FSF_TOPO_AL:
		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
518
		/* fall through */
S
Swen Schillig 已提交
519 520
	default:
		dev_err(&adapter->ccw_device->dev,
521 522
			"Unknown or unsupported arbitrated loop "
			"fibre channel topology detected\n");
523
		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1");
S
Swen Schillig 已提交
524
		return -EIO;
L
Linus Torvalds 已提交
525
	}
S
Swen Schillig 已提交
526

L
Linus Torvalds 已提交
527 528 529
	return 0;
}

S
Swen Schillig 已提交
530
static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
C
Christof Schmitt 已提交
531 532
{
	struct zfcp_adapter *adapter = req->adapter;
S
Swen Schillig 已提交
533 534 535
	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 已提交
536

S
Swen Schillig 已提交
537 538
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;
L
Linus Torvalds 已提交
539

S
Swen Schillig 已提交
540 541 542 543 544 545
	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;
546

S
Swen Schillig 已提交
547 548 549 550
	switch (qtcb->header.fsf_status) {
	case FSF_GOOD:
		if (zfcp_fsf_exchange_config_evaluate(req))
			return;
L
Linus Torvalds 已提交
551

S
Swen Schillig 已提交
552 553
		if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
			dev_err(&adapter->ccw_device->dev,
554 555 556
				"FCP adapter maximum QTCB size (%d bytes) "
				"is too small\n",
				bottom->max_qtcb_size);
557
			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1");
S
Swen Schillig 已提交
558 559
			return;
		}
560
		atomic_or(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
S
Swen Schillig 已提交
561
				&adapter->status);
L
Linus Torvalds 已提交
562
		break;
S
Swen Schillig 已提交
563 564 565 566 567 568 569
	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 已提交
570

571 572
		/* avoids adapter shutdown to be able to recognize
		 * events such as LINK UP */
573
		atomic_or(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
574
				&adapter->status);
575
		zfcp_fsf_link_down_info_eval(req,
S
Swen Schillig 已提交
576
			&qtcb->header.fsf_status_qual.link_down_info);
577 578
		if (zfcp_fsf_exchange_config_evaluate(req))
			return;
L
Linus Torvalds 已提交
579
		break;
S
Swen Schillig 已提交
580
	default:
581
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3");
S
Swen Schillig 已提交
582 583
		return;
	}
L
Linus Torvalds 已提交
584

S
Swen Schillig 已提交
585 586 587 588 589 590 591
	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 已提交
592

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

S
Swen Schillig 已提交
608 609 610 611 612
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 已提交
613

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

617
	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
S
Swen Schillig 已提交
618
		fc_host_permanent_port_name(shost) = bottom->wwpn;
619
	} else
S
Swen Schillig 已提交
620 621
		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
622 623
	fc_host_supported_speeds(shost) =
		zfcp_fsf_convert_portspeed(bottom->supported_speed);
624 625 626 627
	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 已提交
628
}
L
Linus Torvalds 已提交
629

S
Swen Schillig 已提交
630 631 632 633 634 635 636 637 638 639 640 641 642
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);
643
		zfcp_fsf_link_down_info_eval(req,
S
Swen Schillig 已提交
644
			&qtcb->header.fsf_status_qual.link_down_info);
645
		break;
L
Linus Torvalds 已提交
646
	}
S
Swen Schillig 已提交
647
}
648

649
static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
S
Swen Schillig 已提交
650 651
{
	struct zfcp_fsf_req *req;
652 653 654 655 656 657 658

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

	if (unlikely(!req))
S
Swen Schillig 已提交
659
		return NULL;
660

S
Swen Schillig 已提交
661
	memset(req, 0, sizeof(*req));
662
	req->pool = pool;
S
Swen Schillig 已提交
663 664 665
	return req;
}

666
static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
S
Swen Schillig 已提交
667
{
668
	struct fsf_qtcb *qtcb;
S
Swen Schillig 已提交
669 670 671 672

	if (likely(pool))
		qtcb = mempool_alloc(pool, GFP_ATOMIC);
	else
673
		qtcb = kmem_cache_alloc(zfcp_fsf_qtcb_cache, GFP_ATOMIC);
674

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

	memset(qtcb, 0, sizeof(*qtcb));
679
	return qtcb;
S
Swen Schillig 已提交
680 681
}

682
static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
683
						u32 fsf_cmd, u8 sbtype,
684
						mempool_t *pool)
L
Linus Torvalds 已提交
685
{
686
	struct zfcp_adapter *adapter = qdio->adapter;
687
	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
L
Linus Torvalds 已提交
688

S
Swen Schillig 已提交
689
	if (unlikely(!req))
690
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
691

S
Swen Schillig 已提交
692 693
	if (adapter->req_no == 0)
		adapter->req_no++;
L
Linus Torvalds 已提交
694

S
Swen Schillig 已提交
695 696
	INIT_LIST_HEAD(&req->list);
	init_timer(&req->timer);
697
	init_completion(&req->completion);
L
Linus Torvalds 已提交
698

S
Swen Schillig 已提交
699 700
	req->adapter = adapter;
	req->fsf_command = fsf_cmd;
701
	req->req_id = adapter->req_no;
S
Swen Schillig 已提交
702

703 704 705 706 707 708 709 710 711 712 713
	if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
		if (likely(pool))
			req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool);
		else
			req->qtcb = zfcp_qtcb_alloc(NULL);

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

714
		req->seq_no = adapter->fsf_req_seq_no;
715
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
S
Swen Schillig 已提交
716 717 718 719 720 721 722 723
		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;
	}

724 725 726
	zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,
			   req->qtcb, sizeof(struct fsf_qtcb));

S
Swen Schillig 已提交
727
	return req;
L
Linus Torvalds 已提交
728 729
}

S
Swen Schillig 已提交
730 731 732
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
733
	struct zfcp_qdio *qdio = adapter->qdio;
734
	int with_qtcb = (req->qtcb != NULL);
735
	int req_id = req->req_id;
S
Swen Schillig 已提交
736

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

739
	req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free);
740
	req->issued = get_tod_clock();
741
	if (zfcp_qdio_send(qdio, &req->qdio_req)) {
S
Swen Schillig 已提交
742
		del_timer(&req->timer);
743
		/* lookup request again, list might have changed */
744
		zfcp_reqlist_find_rm(adapter->req_list, req_id);
745
		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1");
S
Swen Schillig 已提交
746 747 748 749
		return -EIO;
	}

	/* Don't increase for unsolicited status */
750
	if (with_qtcb)
S
Swen Schillig 已提交
751
		adapter->fsf_req_seq_no++;
752
	adapter->req_no++;
S
Swen Schillig 已提交
753 754 755 756 757 758 759 760 761

	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 已提交
762
 */
763
int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
L
Linus Torvalds 已提交
764
{
765
	struct zfcp_adapter *adapter = qdio->adapter;
S
Swen Schillig 已提交
766 767
	struct zfcp_fsf_req *req;
	struct fsf_status_read_buffer *sr_buf;
768
	struct page *page;
S
Swen Schillig 已提交
769
	int retval = -EIO;
L
Linus Torvalds 已提交
770

771
	spin_lock_irq(&qdio->req_q_lock);
772
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
773 774
		goto out;

775 776
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS,
				  SBAL_SFLAGS0_TYPE_STATUS,
777
				  adapter->pool.status_read_req);
778
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
779 780
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
781 782
	}

783 784
	page = mempool_alloc(adapter->pool.sr_data, GFP_ATOMIC);
	if (!page) {
S
Swen Schillig 已提交
785 786 787
		retval = -ENOMEM;
		goto failed_buf;
	}
788
	sr_buf = page_address(page);
S
Swen Schillig 已提交
789 790
	memset(sr_buf, 0, sizeof(*sr_buf));
	req->data = sr_buf;
791 792 793

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

S
Swen Schillig 已提交
795 796 797
	retval = zfcp_fsf_req_send(req);
	if (retval)
		goto failed_req_send;
L
Linus Torvalds 已提交
798

S
Swen Schillig 已提交
799 800 801
	goto out;

failed_req_send:
802
	req->data = NULL;
803
	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
S
Swen Schillig 已提交
804
failed_buf:
805
	zfcp_dbf_hba_fsf_uss("fssr__1", req);
S
Swen Schillig 已提交
806 807
	zfcp_fsf_req_free(req);
out:
808
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
809 810 811 812 813
	return retval;
}

static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
814
	struct scsi_device *sdev = req->data;
815
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
816 817 818 819 820
	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;

821 822
	zfcp_sdev = sdev_to_zfcp(sdev);

S
Swen Schillig 已提交
823
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
824
	case FSF_PORT_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
825
		if (fsq->word[0] == fsq->word[1]) {
826
			zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
827
						"fsafch1");
S
Swen Schillig 已提交
828
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
829 830 831
		}
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
832
		if (fsq->word[0] == fsq->word[1]) {
833
			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2");
S
Swen Schillig 已提交
834
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
835 836 837
		}
		break;
	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
S
Swen Schillig 已提交
838
		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
L
Linus Torvalds 已提交
839 840
		break;
	case FSF_PORT_BOXED:
841 842 843
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
844
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3");
845
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
846 847
		break;
	case FSF_LUN_BOXED:
848 849
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
850
				    "fsafch4");
851
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
852 853
                break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
854
		switch (fsq->word[0]) {
L
Linus Torvalds 已提交
855
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
856
			zfcp_fc_test_link(zfcp_sdev->port);
857
			/* fall through */
L
Linus Torvalds 已提交
858
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
859
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
860 861 862 863
			break;
		}
		break;
	case FSF_GOOD:
S
Swen Schillig 已提交
864
		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
L
Linus Torvalds 已提交
865 866 867 868 869
		break;
	}
}

/**
870 871
 * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
 * @scmnd: The SCSI command to abort
S
Swen Schillig 已提交
872
 * Returns: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
873 874
 */

875
struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
L
Linus Torvalds 已提交
876
{
S
Swen Schillig 已提交
877
	struct zfcp_fsf_req *req = NULL;
878 879 880 881
	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;
882

883
	spin_lock_irq(&qdio->req_q_lock);
884
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
885
		goto out;
886
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
887
				  SBAL_SFLAGS0_TYPE_READ,
888
				  qdio->adapter->pool.scsi_abort);
889 890
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
891
		goto out;
892
	}
893

894
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
895 896
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		goto out_error_free;
L
Linus Torvalds 已提交
897

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

900
	req->data = sdev;
S
Swen Schillig 已提交
901
	req->handler = zfcp_fsf_abort_fcp_command_handler;
902 903
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
904 905 906 907 908 909 910 911 912 913
	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:
914
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
915
	return req;
L
Linus Torvalds 已提交
916 917
}

S
Swen Schillig 已提交
918
static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
919
{
S
Swen Schillig 已提交
920
	struct zfcp_adapter *adapter = req->adapter;
921
	struct zfcp_fsf_ct_els *ct = req->data;
S
Swen Schillig 已提交
922
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
923

924
	ct->status = -EINVAL;
L
Linus Torvalds 已提交
925

S
Swen Schillig 已提交
926
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
927 928 929 930
		goto skip_fsfstatus;

	switch (header->fsf_status) {
        case FSF_GOOD:
931
		zfcp_dbf_san_res("fsscth2", req);
932
		ct->status = 0;
L
Linus Torvalds 已提交
933 934
		break;
        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
935
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
936 937 938 939 940
		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 已提交
941
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
942 943 944 945
			break;
                }
                break;
        case FSF_PORT_BOXED:
946
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
947
		break;
S
Swen Schillig 已提交
948
	case FSF_PORT_HANDLE_NOT_VALID:
949
		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1");
950
		/* fall through */
S
Swen Schillig 已提交
951
	case FSF_GENERIC_COMMAND_REJECTED:
L
Linus Torvalds 已提交
952 953 954 955
	case FSF_PAYLOAD_SIZE_MISMATCH:
	case FSF_REQUEST_SIZE_TOO_LARGE:
	case FSF_RESPONSE_SIZE_TOO_LARGE:
	case FSF_SBAL_MISMATCH:
S
Swen Schillig 已提交
956
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
957 958 959 960
		break;
	}

skip_fsfstatus:
961 962
	if (ct->handler)
		ct->handler(ct->handler_data);
S
Swen Schillig 已提交
963
}
L
Linus Torvalds 已提交
964

965 966
static void zfcp_fsf_setup_ct_els_unchained(struct zfcp_qdio *qdio,
					    struct zfcp_qdio_req *q_req,
967 968 969
					    struct scatterlist *sg_req,
					    struct scatterlist *sg_resp)
{
970 971 972
	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);
973 974
}

975 976
static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
				       struct scatterlist *sg_req,
977
				       struct scatterlist *sg_resp)
S
Swen Schillig 已提交
978
{
979
	struct zfcp_adapter *adapter = req->adapter;
980 981
	struct zfcp_qdio *qdio = adapter->qdio;
	struct fsf_qtcb *qtcb = req->qtcb;
982
	u32 feat = adapter->adapter_features;
S
Swen Schillig 已提交
983

984 985 986 987 988
	if (zfcp_adapter_multi_buffer_active(adapter)) {
		if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req))
			return -EIO;
		if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp))
			return -EIO;
989

990 991 992 993
		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
					zfcp_qdio_sbale_count(sg_req));
		zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
		zfcp_qdio_set_scount(qdio, &req->qdio_req);
994 995 996 997
		return 0;
	}

	/* use single, unchained SBAL if it can hold the request */
998
	if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
999
		zfcp_fsf_setup_ct_els_unchained(qdio, &req->qdio_req,
1000
						sg_req, sg_resp);
1001 1002 1003
		return 0;
	}

1004 1005 1006 1007
	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS))
		return -EOPNOTSUPP;

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

1010 1011 1012 1013 1014 1015
	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))
1016
		return -EIO;
1017 1018 1019 1020

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

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

1022 1023 1024 1025 1026 1027
	return 0;
}

static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
				 struct scatterlist *sg_req,
				 struct scatterlist *sg_resp,
1028
				 unsigned int timeout)
1029 1030 1031
{
	int ret;

1032
	ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp);
1033 1034 1035
	if (ret)
		return ret;

1036
	/* common settings for ct/gs and els requests */
1037 1038
	if (timeout > 255)
		timeout = 255; /* max value accepted by hardware */
1039
	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
1040 1041
	req->qtcb->bottom.support.timeout = timeout;
	zfcp_fsf_start_timer(req, (timeout + 10) * HZ);
S
Swen Schillig 已提交
1042 1043

	return 0;
L
Linus Torvalds 已提交
1044 1045 1046
}

/**
S
Swen Schillig 已提交
1047 1048 1049
 * 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 已提交
1050
 */
1051
int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
1052 1053
		     struct zfcp_fsf_ct_els *ct, mempool_t *pool,
		     unsigned int timeout)
L
Linus Torvalds 已提交
1054
{
1055
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
S
Swen Schillig 已提交
1056 1057
	struct zfcp_fsf_req *req;
	int ret = -EIO;
L
Linus Torvalds 已提交
1058

1059
	spin_lock_irq(&qdio->req_q_lock);
1060
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1061
		goto out;
L
Linus Torvalds 已提交
1062

1063
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC,
1064
				  SBAL_SFLAGS0_TYPE_WRITE_READ, pool);
1065

1066
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1067 1068
		ret = PTR_ERR(req);
		goto out;
1069 1070
	}

1071
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1072
	ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout);
C
Christof Schmitt 已提交
1073
	if (ret)
L
Linus Torvalds 已提交
1074 1075
		goto failed_send;

S
Swen Schillig 已提交
1076
	req->handler = zfcp_fsf_send_ct_handler;
1077
	req->qtcb->header.port_handle = wka_port->handle;
S
Swen Schillig 已提交
1078 1079
	req->data = ct;

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

S
Swen Schillig 已提交
1082 1083 1084
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;
L
Linus Torvalds 已提交
1085

S
Swen Schillig 已提交
1086
	goto out;
L
Linus Torvalds 已提交
1087

S
Swen Schillig 已提交
1088 1089 1090
failed_send:
	zfcp_fsf_req_free(req);
out:
1091
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1092
	return ret;
L
Linus Torvalds 已提交
1093 1094
}

S
Swen Schillig 已提交
1095
static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1096
{
1097
	struct zfcp_fsf_ct_els *send_els = req->data;
S
Swen Schillig 已提交
1098
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1099

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

S
Swen Schillig 已提交
1102
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
1103 1104 1105 1106
		goto skip_fsfstatus;

	switch (header->fsf_status) {
	case FSF_GOOD:
1107
		zfcp_dbf_san_res("fsselh1", req);
S
Swen Schillig 已提交
1108
		send_els->status = 0;
L
Linus Torvalds 已提交
1109 1110
		break;
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
1111
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
1112 1113 1114 1115 1116 1117
		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 已提交
1118
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1119 1120 1121 1122 1123 1124 1125 1126
			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 已提交
1127
	case FSF_SBAL_MISMATCH:
L
Lucas De Marchi 已提交
1128
		/* should never occur, avoided in zfcp_fsf_send_els */
S
Swen Schillig 已提交
1129
		/* fall through */
L
Linus Torvalds 已提交
1130
	default:
S
Swen Schillig 已提交
1131
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1132 1133 1134
		break;
	}
skip_fsfstatus:
H
Heiko Carstens 已提交
1135
	if (send_els->handler)
L
Linus Torvalds 已提交
1136
		send_els->handler(send_els->handler_data);
S
Swen Schillig 已提交
1137
}
L
Linus Torvalds 已提交
1138

S
Swen Schillig 已提交
1139 1140 1141 1142
/**
 * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
 * @els: pointer to struct zfcp_send_els with data for the command
 */
1143
int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
1144
		      struct zfcp_fsf_ct_els *els, unsigned int timeout)
S
Swen Schillig 已提交
1145 1146
{
	struct zfcp_fsf_req *req;
1147
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1148 1149
	int ret = -EIO;

1150
	spin_lock_irq(&qdio->req_q_lock);
1151
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1152
		goto out;
1153

1154
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS,
1155
				  SBAL_SFLAGS0_TYPE_WRITE_READ, NULL);
1156

1157
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1158 1159 1160 1161
		ret = PTR_ERR(req);
		goto out;
	}

1162
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1163

1164 1165
	if (!zfcp_adapter_multi_buffer_active(adapter))
		zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
1166 1167

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

S
Swen Schillig 已提交
1169 1170 1171
	if (ret)
		goto failed_send;

1172
	hton24(req->qtcb->bottom.support.d_id, d_id);
S
Swen Schillig 已提交
1173 1174 1175
	req->handler = zfcp_fsf_send_els_handler;
	req->data = els;

1176
	zfcp_dbf_san_req("fssels1", req, d_id);
S
Swen Schillig 已提交
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186

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

	goto out;

failed_send:
	zfcp_fsf_req_free(req);
out:
1187
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1188
	return ret;
L
Linus Torvalds 已提交
1189 1190
}

S
Swen Schillig 已提交
1191
int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1192
{
S
Swen Schillig 已提交
1193
	struct zfcp_fsf_req *req;
1194
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1195 1196
	int retval = -EIO;

1197
	spin_lock_irq(&qdio->req_q_lock);
1198
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1199
		goto out;
1200

1201
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
1202
				  SBAL_SFLAGS0_TYPE_READ,
1203
				  qdio->adapter->pool.erp_req);
1204

1205
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1206 1207
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
1208 1209
	}

1210
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1211
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1212

S
Swen Schillig 已提交
1213
	req->qtcb->bottom.config.feature_selection =
1214
			FSF_FEATURE_NOTIFICATION_LOST |
1215
			FSF_FEATURE_UPDATE_ALERT;
S
Swen Schillig 已提交
1216 1217
	req->erp_action = erp_action;
	req->handler = zfcp_fsf_exchange_config_data_handler;
1218
	erp_action->fsf_req_id = req->req_id;
L
Linus Torvalds 已提交
1219

1220
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1221
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1222
	if (retval) {
S
Swen Schillig 已提交
1223
		zfcp_fsf_req_free(req);
1224
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1225
	}
S
Swen Schillig 已提交
1226
out:
1227
	spin_unlock_irq(&qdio->req_q_lock);
1228 1229
	return retval;
}
L
Linus Torvalds 已提交
1230

1231
int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
S
Swen Schillig 已提交
1232
				       struct fsf_qtcb_bottom_config *data)
1233
{
S
Swen Schillig 已提交
1234 1235 1236
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;

1237
	spin_lock_irq(&qdio->req_q_lock);
1238
	if (zfcp_qdio_sbal_get(qdio))
1239
		goto out_unlock;
S
Swen Schillig 已提交
1240

1241
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
1242
				  SBAL_SFLAGS0_TYPE_READ, NULL);
1243

1244
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1245
		retval = PTR_ERR(req);
1246
		goto out_unlock;
1247 1248
	}

1249
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
S
Swen Schillig 已提交
1250
	req->handler = zfcp_fsf_exchange_config_data_handler;
1251

S
Swen Schillig 已提交
1252
	req->qtcb->bottom.config.feature_selection =
1253 1254 1255 1256
			FSF_FEATURE_NOTIFICATION_LOST |
			FSF_FEATURE_UPDATE_ALERT;

	if (data)
S
Swen Schillig 已提交
1257
		req->data = data;
1258

S
Swen Schillig 已提交
1259 1260
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
1261
	spin_unlock_irq(&qdio->req_q_lock);
C
Christof Schmitt 已提交
1262
	if (!retval)
1263
		wait_for_completion(&req->completion);
1264

S
Swen Schillig 已提交
1265
	zfcp_fsf_req_free(req);
1266
	return retval;
1267

1268
out_unlock:
1269
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1270 1271 1272 1273 1274
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data - request information about local port
1275
 * @erp_action: ERP action for the adapter for which port data is requested
S
Swen Schillig 已提交
1276
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1277
 */
S
Swen Schillig 已提交
1278
int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1279
{
1280
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1281 1282
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1283

1284
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1285
		return -EOPNOTSUPP;
L
Linus Torvalds 已提交
1286

1287
	spin_lock_irq(&qdio->req_q_lock);
1288
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1289
		goto out;
1290

1291
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
1292
				  SBAL_SFLAGS0_TYPE_READ,
1293
				  qdio->adapter->pool.erp_req);
1294

1295
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1296 1297
		retval = PTR_ERR(req);
		goto out;
1298 1299
	}

1300
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1301
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1302

S
Swen Schillig 已提交
1303 1304
	req->handler = zfcp_fsf_exchange_port_data_handler;
	req->erp_action = erp_action;
1305
	erp_action->fsf_req_id = req->req_id;
1306

1307
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1308
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1309
	if (retval) {
S
Swen Schillig 已提交
1310
		zfcp_fsf_req_free(req);
1311
		erp_action->fsf_req_id = 0;
1312
	}
S
Swen Schillig 已提交
1313
out:
1314
	spin_unlock_irq(&qdio->req_q_lock);
1315 1316 1317 1318 1319
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data_sync - request information about local port
1320
 * @qdio: pointer to struct zfcp_qdio
S
Swen Schillig 已提交
1321 1322
 * @data: pointer to struct fsf_qtcb_bottom_port
 * Returns: 0 on success, error otherwise
1323
 */
1324
int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
S
Swen Schillig 已提交
1325
				     struct fsf_qtcb_bottom_port *data)
1326
{
S
Swen Schillig 已提交
1327 1328
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;
1329

1330
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1331 1332
		return -EOPNOTSUPP;

1333
	spin_lock_irq(&qdio->req_q_lock);
1334
	if (zfcp_qdio_sbal_get(qdio))
1335
		goto out_unlock;
S
Swen Schillig 已提交
1336

1337
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
1338
				  SBAL_SFLAGS0_TYPE_READ, NULL);
1339

1340
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1341
		retval = PTR_ERR(req);
1342
		goto out_unlock;
L
Linus Torvalds 已提交
1343 1344
	}

1345
	if (data)
S
Swen Schillig 已提交
1346
		req->data = data;
1347

1348
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1349

S
Swen Schillig 已提交
1350 1351 1352
	req->handler = zfcp_fsf_exchange_port_data_handler;
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
1353
	spin_unlock_irq(&qdio->req_q_lock);
1354

C
Christof Schmitt 已提交
1355
	if (!retval)
1356 1357
		wait_for_completion(&req->completion);

S
Swen Schillig 已提交
1358
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1359 1360

	return retval;
1361 1362

out_unlock:
1363
	spin_unlock_irq(&qdio->req_q_lock);
1364
	return retval;
L
Linus Torvalds 已提交
1365 1366
}

S
Swen Schillig 已提交
1367
static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1368
{
S
Swen Schillig 已提交
1369 1370
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
1371
	struct fc_els_flogi *plogi;
L
Linus Torvalds 已提交
1372

S
Swen Schillig 已提交
1373
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1374
		goto out;
L
Linus Torvalds 已提交
1375 1376 1377 1378 1379

	switch (header->fsf_status) {
	case FSF_PORT_ALREADY_OPEN:
		break;
	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
S
Swen Schillig 已提交
1380
		dev_warn(&req->adapter->ccw_device->dev,
1381
			 "Not enough FCP adapter resources to open "
1382 1383
			 "remote port 0x%016Lx\n",
			 (unsigned long long)port->wwpn);
1384 1385
		zfcp_erp_set_port_status(port,
					 ZFCP_STATUS_COMMON_ERP_FAILED);
S
Swen Schillig 已提交
1386
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1387 1388 1389 1390 1391 1392
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
		case FSF_SQ_NO_RETRY_POSSIBLE:
S
Swen Schillig 已提交
1393
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1394 1395 1396 1397 1398
			break;
		}
		break;
	case FSF_GOOD:
		port->handle = header->port_handle;
1399
		atomic_or(ZFCP_STATUS_COMMON_OPEN |
L
Linus Torvalds 已提交
1400
				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1401
		atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_BOXED,
1402
		                  &port->status);
L
Linus Torvalds 已提交
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
		/* 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.
		 */
1418
		plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els;
1419
		if (req->qtcb->bottom.support.els1_length >=
1420
		    FSF_PLOGI_MIN_LEN)
S
Swen Schillig 已提交
1421
				zfcp_fc_plogi_evaluate(port, plogi);
L
Linus Torvalds 已提交
1422 1423
		break;
	case FSF_UNKNOWN_OP_SUBTYPE:
S
Swen Schillig 已提交
1424
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1425 1426
		break;
	}
1427 1428

out:
1429
	put_device(&port->dev);
L
Linus Torvalds 已提交
1430 1431
}

S
Swen Schillig 已提交
1432 1433 1434 1435
/**
 * 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 已提交
1436
 */
S
Swen Schillig 已提交
1437
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1438
{
1439
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1440
	struct zfcp_port *port = erp_action->port;
1441
	struct zfcp_fsf_req *req;
S
Swen Schillig 已提交
1442 1443
	int retval = -EIO;

1444
	spin_lock_irq(&qdio->req_q_lock);
1445
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1446 1447
		goto out;

1448
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1449
				  SBAL_SFLAGS0_TYPE_READ,
1450
				  qdio->adapter->pool.erp_req);
1451

1452
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1453
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1454
		goto out;
S
Swen Schillig 已提交
1455
	}
L
Linus Torvalds 已提交
1456

1457
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1458
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1459

S
Swen Schillig 已提交
1460
	req->handler = zfcp_fsf_open_port_handler;
1461
	hton24(req->qtcb->bottom.support.d_id, port->d_id);
1462
	req->data = port;
S
Swen Schillig 已提交
1463
	req->erp_action = erp_action;
1464
	erp_action->fsf_req_id = req->req_id;
1465
	get_device(&port->dev);
S
Swen Schillig 已提交
1466

1467
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1468
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1469
	if (retval) {
S
Swen Schillig 已提交
1470
		zfcp_fsf_req_free(req);
1471
		erp_action->fsf_req_id = 0;
1472
		put_device(&port->dev);
L
Linus Torvalds 已提交
1473
	}
S
Swen Schillig 已提交
1474
out:
1475
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1476 1477 1478
	return retval;
}

S
Swen Schillig 已提交
1479
static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1480
{
S
Swen Schillig 已提交
1481
	struct zfcp_port *port = req->data;
L
Linus Torvalds 已提交
1482

S
Swen Schillig 已提交
1483
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1484
		return;
L
Linus Torvalds 已提交
1485

S
Swen Schillig 已提交
1486
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1487
	case FSF_PORT_HANDLE_NOT_VALID:
1488
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1");
S
Swen Schillig 已提交
1489
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1490 1491 1492 1493
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		break;
	case FSF_GOOD:
1494
		zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN);
L
Linus Torvalds 已提交
1495 1496 1497 1498
		break;
	}
}

S
Swen Schillig 已提交
1499 1500 1501 1502
/**
 * 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 已提交
1503
 */
S
Swen Schillig 已提交
1504
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1505
{
1506
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1507 1508 1509
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1510
	spin_lock_irq(&qdio->req_q_lock);
1511
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1512 1513
		goto out;

1514
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1515
				  SBAL_SFLAGS0_TYPE_READ,
1516
				  qdio->adapter->pool.erp_req);
1517

1518
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1519
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1520
		goto out;
S
Swen Schillig 已提交
1521
	}
L
Linus Torvalds 已提交
1522

1523
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1524
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1525

S
Swen Schillig 已提交
1526 1527 1528 1529
	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;
1530
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1531

1532
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1533
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1534
	if (retval) {
S
Swen Schillig 已提交
1535
		zfcp_fsf_req_free(req);
1536
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1537
	}
S
Swen Schillig 已提交
1538
out:
1539
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1540 1541 1542
	return retval;
}

1543 1544
static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
{
1545
	struct zfcp_fc_wka_port *wka_port = req->data;
1546 1547 1548
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
1549
		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1550 1551 1552 1553 1554 1555 1556
		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);
1557
		/* fall through */
1558 1559
	case FSF_ADAPTER_STATUS_AVAILABLE:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1560
		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1561 1562 1563
		break;
	case FSF_GOOD:
		wka_port->handle = header->port_handle;
1564 1565
		/* fall through */
	case FSF_PORT_ALREADY_OPEN:
1566
		wka_port->status = ZFCP_FC_WKA_PORT_ONLINE;
1567 1568 1569 1570 1571 1572 1573
	}
out:
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_open_wka_port - create and send open wka-port request
1574
 * @wka_port: pointer to struct zfcp_fc_wka_port
1575 1576
 * Returns: 0 on success, error otherwise
 */
1577
int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
1578
{
1579
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1580 1581 1582
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1583
	spin_lock_irq(&qdio->req_q_lock);
1584
	if (zfcp_qdio_sbal_get(qdio))
1585 1586
		goto out;

1587
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1588
				  SBAL_SFLAGS0_TYPE_READ,
1589
				  qdio->adapter->pool.erp_req);
1590

1591
	if (IS_ERR(req)) {
1592 1593 1594 1595
		retval = PTR_ERR(req);
		goto out;
	}

1596
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1597
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1598 1599

	req->handler = zfcp_fsf_open_wka_port_handler;
1600
	hton24(req->qtcb->bottom.support.d_id, wka_port->d_id);
1601 1602 1603 1604 1605 1606 1607
	req->data = wka_port;

	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
	if (retval)
		zfcp_fsf_req_free(req);
out:
1608
	spin_unlock_irq(&qdio->req_q_lock);
1609 1610 1611 1612 1613
	return retval;
}

static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
{
1614
	struct zfcp_fc_wka_port *wka_port = req->data;
1615 1616 1617

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

1621
	wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1622 1623 1624 1625 1626
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_close_wka_port - create and send close wka port request
1627
 * @wka_port: WKA port to open
1628 1629
 * Returns: 0 on success, error otherwise
 */
1630
int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
1631
{
1632
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1633 1634 1635
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1636
	spin_lock_irq(&qdio->req_q_lock);
1637
	if (zfcp_qdio_sbal_get(qdio))
1638 1639
		goto out;

1640
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1641
				  SBAL_SFLAGS0_TYPE_READ,
1642
				  qdio->adapter->pool.erp_req);
1643

1644
	if (IS_ERR(req)) {
1645 1646 1647 1648
		retval = PTR_ERR(req);
		goto out;
	}

1649
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1650
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660

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

	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
	if (retval)
		zfcp_fsf_req_free(req);
out:
1661
	spin_unlock_irq(&qdio->req_q_lock);
1662 1663 1664
	return retval;
}

S
Swen Schillig 已提交
1665
static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1666
{
S
Swen Schillig 已提交
1667 1668
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
1669
	struct scsi_device *sdev;
L
Linus Torvalds 已提交
1670

S
Swen Schillig 已提交
1671
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1672
		return;
L
Linus Torvalds 已提交
1673 1674 1675

	switch (header->fsf_status) {
	case FSF_PORT_HANDLE_NOT_VALID:
1676
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1");
S
Swen Schillig 已提交
1677
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1678 1679
		break;
	case FSF_PORT_BOXED:
1680 1681
		/* can't use generic zfcp_erp_modify_port_status because
		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
1682
		atomic_andnot(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1683 1684
		shost_for_each_device(sdev, port->adapter->scsi_host)
			if (sdev_to_zfcp(sdev)->port == port)
1685
				atomic_andnot(ZFCP_STATUS_COMMON_OPEN,
1686
						  &sdev_to_zfcp(sdev)->status);
1687 1688
		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
1689
				     "fscpph2");
1690
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1691 1692 1693 1694
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
S
Swen Schillig 已提交
1695
			/* fall through */
L
Linus Torvalds 已提交
1696
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1697
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1698 1699 1700 1701 1702 1703 1704
			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
		 */
1705
		atomic_andnot(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1706 1707
		shost_for_each_device(sdev, port->adapter->scsi_host)
			if (sdev_to_zfcp(sdev)->port == port)
1708
				atomic_andnot(ZFCP_STATUS_COMMON_OPEN,
1709
						  &sdev_to_zfcp(sdev)->status);
L
Linus Torvalds 已提交
1710 1711 1712 1713
		break;
	}
}

S
Swen Schillig 已提交
1714 1715 1716 1717
/**
 * zfcp_fsf_close_physical_port - close physical port
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success
L
Linus Torvalds 已提交
1718
 */
S
Swen Schillig 已提交
1719
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1720
{
1721
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1722 1723 1724
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1725
	spin_lock_irq(&qdio->req_q_lock);
1726
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1727 1728
		goto out;

1729
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
1730
				  SBAL_SFLAGS0_TYPE_READ,
1731
				  qdio->adapter->pool.erp_req);
1732

1733
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1734 1735 1736
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1737

1738
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1739
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1740

S
Swen Schillig 已提交
1741 1742 1743 1744
	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;
1745
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1746

1747
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1748
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1749
	if (retval) {
S
Swen Schillig 已提交
1750
		zfcp_fsf_req_free(req);
1751
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1752
	}
S
Swen Schillig 已提交
1753
out:
1754
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1755 1756 1757
	return retval;
}

1758
static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1759
{
S
Swen Schillig 已提交
1760
	struct zfcp_adapter *adapter = req->adapter;
1761
	struct scsi_device *sdev = req->data;
1762
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
1763
	struct fsf_qtcb_header *header = &req->qtcb->header;
1764
	union fsf_status_qual *qual = &header->fsf_status_qual;
L
Linus Torvalds 已提交
1765

S
Swen Schillig 已提交
1766
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1767
		return;
L
Linus Torvalds 已提交
1768

1769 1770
	zfcp_sdev = sdev_to_zfcp(sdev);

1771
	atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1772
			  ZFCP_STATUS_COMMON_ACCESS_BOXED,
1773
			  &zfcp_sdev->status);
L
Linus Torvalds 已提交
1774 1775 1776 1777

	switch (header->fsf_status) {

	case FSF_PORT_HANDLE_NOT_VALID:
1778
		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
S
Swen Schillig 已提交
1779
		/* fall through */
L
Linus Torvalds 已提交
1780 1781 1782
	case FSF_LUN_ALREADY_OPEN:
		break;
	case FSF_PORT_BOXED:
1783 1784 1785
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
1786
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2");
1787
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1788 1789
		break;
	case FSF_LUN_SHARING_VIOLATION:
1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
		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 已提交
1801
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1802 1803
		break;
	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
S
Swen Schillig 已提交
1804
		dev_warn(&adapter->ccw_device->dev,
1805 1806
			 "No handle is available for LUN "
			 "0x%016Lx on port 0x%016Lx\n",
1807 1808
			 (unsigned long long)zfcp_scsi_dev_lun(sdev),
			 (unsigned long long)zfcp_sdev->port->wwpn);
1809
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
S
Swen Schillig 已提交
1810 1811 1812
		/* fall through */
	case FSF_INVALID_COMMAND_OPTION:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1813 1814 1815 1816
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1817
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
1818
			/* fall through */
L
Linus Torvalds 已提交
1819
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1820
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1821 1822 1823 1824 1825
			break;
		}
		break;

	case FSF_GOOD:
1826
		zfcp_sdev->lun_handle = header->lun_handle;
1827
		atomic_or(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
L
Linus Torvalds 已提交
1828 1829 1830 1831
		break;
	}
}

S
Swen Schillig 已提交
1832
/**
1833
 * zfcp_fsf_open_lun - open LUN
S
Swen Schillig 已提交
1834 1835
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1836
 */
1837
int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1838
{
S
Swen Schillig 已提交
1839
	struct zfcp_adapter *adapter = erp_action->adapter;
1840
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1841 1842 1843
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1844
	spin_lock_irq(&qdio->req_q_lock);
1845
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1846 1847
		goto out;

1848
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1849
				  SBAL_SFLAGS0_TYPE_READ,
1850
				  adapter->pool.erp_req);
1851

1852
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1853 1854 1855 1856
		retval = PTR_ERR(req);
		goto out;
	}

1857
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1858
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1859

S
Swen Schillig 已提交
1860
	req->qtcb->header.port_handle = erp_action->port->handle;
1861 1862 1863
	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 已提交
1864
	req->erp_action = erp_action;
1865
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1866 1867 1868 1869

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

1870
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1871
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1872
	if (retval) {
S
Swen Schillig 已提交
1873
		zfcp_fsf_req_free(req);
1874
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1875
	}
S
Swen Schillig 已提交
1876
out:
1877
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1878 1879 1880
	return retval;
}

1881
static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1882
{
1883
	struct scsi_device *sdev = req->data;
1884
	struct zfcp_scsi_dev *zfcp_sdev;
L
Linus Torvalds 已提交
1885

S
Swen Schillig 已提交
1886
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1887
		return;
L
Linus Torvalds 已提交
1888

1889 1890
	zfcp_sdev = sdev_to_zfcp(sdev);

S
Swen Schillig 已提交
1891
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1892
	case FSF_PORT_HANDLE_NOT_VALID:
1893
		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1");
S
Swen Schillig 已提交
1894
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1895 1896
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
1897
		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2");
S
Swen Schillig 已提交
1898
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1899 1900
		break;
	case FSF_PORT_BOXED:
1901 1902 1903
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
1904
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3");
1905
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1906 1907
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
1908
		switch (req->qtcb->header.fsf_status_qual.word[0]) {
L
Linus Torvalds 已提交
1909
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1910
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
1911
			/* fall through */
L
Linus Torvalds 已提交
1912
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1913
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1914 1915 1916 1917
			break;
		}
		break;
	case FSF_GOOD:
1918
		atomic_andnot(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
L
Linus Torvalds 已提交
1919 1920 1921 1922 1923
		break;
	}
}

/**
1924 1925
 * zfcp_fsf_close_LUN - close LUN
 * @erp_action: pointer to erp_action triggering the "close LUN"
S
Swen Schillig 已提交
1926
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1927
 */
1928
int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1929
{
1930
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1931
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
S
Swen Schillig 已提交
1932 1933
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1934

1935
	spin_lock_irq(&qdio->req_q_lock);
1936
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1937
		goto out;
1938

1939
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
1940
				  SBAL_SFLAGS0_TYPE_READ,
1941
				  qdio->adapter->pool.erp_req);
1942

1943
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1944 1945 1946
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1947

1948
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1949
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1950

S
Swen Schillig 已提交
1951
	req->qtcb->header.port_handle = erp_action->port->handle;
1952 1953 1954
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->handler = zfcp_fsf_close_lun_handler;
	req->data = erp_action->sdev;
S
Swen Schillig 已提交
1955
	req->erp_action = erp_action;
1956
	erp_action->fsf_req_id = req->req_id;
1957

1958
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1959 1960 1961
	retval = zfcp_fsf_req_send(req);
	if (retval) {
		zfcp_fsf_req_free(req);
1962
		erp_action->fsf_req_id = 0;
S
Swen Schillig 已提交
1963 1964
	}
out:
1965
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1966
	return retval;
L
Linus Torvalds 已提交
1967 1968
}

1969 1970 1971
static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
{
	lat_rec->sum += lat;
S
Swen Schillig 已提交
1972 1973
	lat_rec->min = min(lat_rec->min, lat);
	lat_rec->max = max(lat_rec->max, lat);
1974 1975
}

1976
static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
1977
{
1978 1979
	struct fsf_qual_latency_info *lat_in;
	struct latency_cont *lat = NULL;
1980
	struct zfcp_scsi_dev *zfcp_sdev;
1981 1982
	struct zfcp_blk_drv_data blktrc;
	int ticks = req->adapter->timer_ticks;
1983

1984
	lat_in = &req->qtcb->prefix.prot_status_qual.latency_info;
1985

1986 1987 1988 1989
	blktrc.flags = 0;
	blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		blktrc.flags |= ZFCP_BLK_REQ_ERROR;
1990
	blktrc.inb_usage = 0;
1991
	blktrc.outb_usage = req->qdio_req.qdio_outb_usage;
1992

1993 1994
	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
	    !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
1995
		zfcp_sdev = sdev_to_zfcp(scsi->device);
1996 1997 1998 1999 2000
		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) {
2001 2002
		case FSF_DATADIR_DIF_READ_STRIP:
		case FSF_DATADIR_DIF_READ_CONVERT:
2003
		case FSF_DATADIR_READ:
2004
			lat = &zfcp_sdev->latencies.read;
2005
			break;
2006 2007
		case FSF_DATADIR_DIF_WRITE_INSERT:
		case FSF_DATADIR_DIF_WRITE_CONVERT:
2008
		case FSF_DATADIR_WRITE:
2009
			lat = &zfcp_sdev->latencies.write;
2010 2011
			break;
		case FSF_DATADIR_CMND:
2012
			lat = &zfcp_sdev->latencies.cmd;
2013 2014
			break;
		}
L
Linus Torvalds 已提交
2015

2016
		if (lat) {
2017
			spin_lock(&zfcp_sdev->latencies.lock);
2018 2019 2020
			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
			lat->counter++;
2021
			spin_unlock(&zfcp_sdev->latencies.lock);
2022
		}
S
Stefan Raspl 已提交
2023 2024
	}

2025 2026
	blk_add_driver_data(scsi->request->q, scsi->request, &blktrc,
			    sizeof(blktrc));
S
Stefan Raspl 已提交
2027 2028
}

2029
static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
S
Swen Schillig 已提交
2030
{
2031 2032
	struct scsi_cmnd *scmnd = req->data;
	struct scsi_device *sdev = scmnd->device;
2033
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
2034 2035 2036
	struct fsf_qtcb_header *header = &req->qtcb->header;

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

2039 2040
	zfcp_sdev = sdev_to_zfcp(sdev);

S
Swen Schillig 已提交
2041 2042 2043
	switch (header->fsf_status) {
	case FSF_HANDLE_MISMATCH:
	case FSF_PORT_HANDLE_NOT_VALID:
2044
		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1");
S
Swen Schillig 已提交
2045 2046 2047 2048
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_FCPLUN_NOT_VALID:
	case FSF_LUN_HANDLE_NOT_VALID:
2049
		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2");
S
Swen Schillig 已提交
2050
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2051
		break;
S
Swen Schillig 已提交
2052 2053
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
2054
		break;
S
Swen Schillig 已提交
2055 2056
	case FSF_DIRECTION_INDICATOR_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2057
			"Incorrect direction %d, LUN 0x%016Lx on port "
2058
			"0x%016Lx closed\n",
S
Swen Schillig 已提交
2059
			req->qtcb->bottom.io.data_direction,
2060 2061 2062
			(unsigned long long)zfcp_scsi_dev_lun(sdev),
			(unsigned long long)zfcp_sdev->port->wwpn);
		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
2063
					  "fssfch3");
S
Swen Schillig 已提交
2064 2065 2066 2067
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_CMND_LENGTH_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2068
			"Incorrect CDB length %d, LUN 0x%016Lx on "
2069
			"port 0x%016Lx closed\n",
S
Swen Schillig 已提交
2070
			req->qtcb->bottom.io.fcp_cmnd_length,
2071 2072 2073
			(unsigned long long)zfcp_scsi_dev_lun(sdev),
			(unsigned long long)zfcp_sdev->port->wwpn);
		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
2074
					  "fssfch4");
S
Swen Schillig 已提交
2075 2076 2077
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_PORT_BOXED:
2078 2079 2080
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
2081
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5");
2082
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2083 2084
		break;
	case FSF_LUN_BOXED:
2085 2086
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
2087
				    "fssfch6");
2088
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2089 2090 2091 2092
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		if (header->fsf_status_qual.word[0] ==
		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
2093
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
2094
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2095 2096
		break;
	}
2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110
}

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 已提交
2111
	}
2112

2113 2114
	zfcp_fsf_fcp_handler_common(req);

2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139
	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;
	}
	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
	zfcp_fc_eval_fcp_rsp(fcp_rsp, scpnt);

skip_fsfstatus:
	zfcp_fsf_req_trace(req, scpnt);
2140
	zfcp_dbf_scsi_result(scpnt, req);
2141 2142 2143 2144 2145 2146 2147 2148 2149 2150

	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 已提交
2151 2152
}

2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
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 已提交
2191
/**
2192
 * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
S
Swen Schillig 已提交
2193
 * @scsi_cmnd: scsi command to be sent
L
Linus Torvalds 已提交
2194
 */
2195
int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
L
Linus Torvalds 已提交
2196
{
S
Swen Schillig 已提交
2197
	struct zfcp_fsf_req *req;
2198
	struct fcp_cmnd *fcp_cmnd;
2199
	u8 sbtype = SBAL_SFLAGS0_TYPE_READ;
2200
	int retval = -EIO;
2201 2202 2203
	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;
2204
	struct zfcp_qdio *qdio = adapter->qdio;
2205
	struct fsf_qtcb_bottom_io *io;
2206
	unsigned long flags;
L
Linus Torvalds 已提交
2207

2208
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2209 2210
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return -EBUSY;
L
Linus Torvalds 已提交
2211

2212
	spin_lock_irqsave(&qdio->req_q_lock, flags);
2213
	if (atomic_read(&qdio->req_q_free) <= 0) {
2214
		atomic_inc(&qdio->req_q_full);
S
Swen Schillig 已提交
2215
		goto out;
2216
	}
2217

2218
	if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE)
2219
		sbtype = SBAL_SFLAGS0_TYPE_WRITE;
2220

2221
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2222
				  sbtype, adapter->pool.scsi_req);
2223

2224
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2225 2226 2227 2228
		retval = PTR_ERR(req);
		goto out;
	}

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

	io = &req->qtcb->bottom.io;
2232
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
S
Swen Schillig 已提交
2233
	req->data = scsi_cmnd;
2234
	req->handler = zfcp_fsf_fcp_cmnd_handler;
2235 2236
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
2237 2238
	io->service_class = FSF_CLASS_3;
	io->fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2239

2240 2241 2242
	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 已提交
2243 2244
	}

2245 2246
	if (zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction))
		goto failed_scsi_cmnd;
2247

2248
	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
2249
	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
L
Linus Torvalds 已提交
2250

2251 2252 2253
	if (scsi_prot_sg_count(scsi_cmnd)) {
		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
				       scsi_prot_sg_count(scsi_cmnd));
2254 2255 2256 2257 2258
		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(
2259 2260 2261
						scsi_prot_sglist(scsi_cmnd));
	}

2262 2263 2264
	retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
					 scsi_sglist(scsi_cmnd));
	if (unlikely(retval))
S
Swen Schillig 已提交
2265
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2266

2267
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
2268 2269
	if (zfcp_adapter_multi_buffer_active(adapter))
		zfcp_qdio_set_scount(qdio, &req->qdio_req);
2270

S
Swen Schillig 已提交
2271 2272 2273
	retval = zfcp_fsf_req_send(req);
	if (unlikely(retval))
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2274

S
Swen Schillig 已提交
2275
	goto out;
L
Linus Torvalds 已提交
2276

S
Swen Schillig 已提交
2277 2278 2279 2280
failed_scsi_cmnd:
	zfcp_fsf_req_free(req);
	scsi_cmnd->host_scribble = NULL;
out:
2281
	spin_unlock_irqrestore(&qdio->req_q_lock, flags);
S
Swen Schillig 已提交
2282
	return retval;
L
Linus Torvalds 已提交
2283 2284
}

2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299
static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
{
	struct fcp_resp_with_ext *fcp_rsp;
	struct fcp_resp_rsp_info *rsp_info;

	zfcp_fsf_fcp_handler_common(req);

	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
	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 已提交
2300
/**
2301 2302
 * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
 * @scmnd: SCSI command to send the task management command for
S
Swen Schillig 已提交
2303 2304
 * @tm_flags: unsigned byte for task management flags
 * Returns: on success pointer to struct fsf_req, NULL otherwise
L
Linus Torvalds 已提交
2305
 */
2306 2307
struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
					    u8 tm_flags)
L
Linus Torvalds 已提交
2308
{
S
Swen Schillig 已提交
2309
	struct zfcp_fsf_req *req = NULL;
2310
	struct fcp_cmnd *fcp_cmnd;
2311 2312
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
L
Linus Torvalds 已提交
2313

2314
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2315 2316
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return NULL;
L
Linus Torvalds 已提交
2317

2318
	spin_lock_irq(&qdio->req_q_lock);
2319
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
2320
		goto out;
2321

2322
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2323
				  SBAL_SFLAGS0_TYPE_WRITE,
2324
				  qdio->adapter->pool.scsi_req);
2325

2326 2327
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
2328
		goto out;
2329
	}
L
Linus Torvalds 已提交
2330

2331
	req->data = scmnd;
2332
	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
2333 2334
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
2335 2336
	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
2337
	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2338

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

2341
	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
2342
	zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags);
L
Linus Torvalds 已提交
2343

S
Swen Schillig 已提交
2344 2345 2346
	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;
L
Linus Torvalds 已提交
2347

S
Swen Schillig 已提交
2348 2349 2350
	zfcp_fsf_req_free(req);
	req = NULL;
out:
2351
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
2352 2353
	return req;
}
L
Linus Torvalds 已提交
2354

2355 2356 2357 2358 2359
/**
 * 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
 */
2360
void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2361
{
2362
	struct zfcp_adapter *adapter = qdio->adapter;
2363
	struct qdio_buffer *sbal = qdio->res_q[sbal_idx];
2364 2365
	struct qdio_buffer_element *sbale;
	struct zfcp_fsf_req *fsf_req;
2366
	unsigned long req_id;
2367 2368 2369 2370 2371 2372
	int idx;

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

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

2375
		if (!fsf_req) {
2376 2377 2378 2379
			/*
			 * Unknown request means that we have potentially memory
			 * corruption and must stop the machine immediately.
			 */
2380
			zfcp_qdio_siosl(adapter);
2381 2382
			panic("error: unknown req_id (%lx) on adapter %s.\n",
			      req_id, dev_name(&adapter->ccw_device->dev));
2383
		}
2384

2385
		fsf_req->qdio_req.sbal_response = sbal_idx;
2386 2387
		zfcp_fsf_req_complete(fsf_req);

2388
		if (likely(sbale->eflags & SBAL_EFLAGS_LAST_ENTRY))
2389 2390 2391
			break;
	}
}