zfcp_fsf.c 68.2 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, 2010
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 117
		return;

	atomic_set_mask(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);
S
Swen Schillig 已提交
207 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_ACT_UPDATED)
258
			zfcp_cfdc_adapter_access_changed(adapter);
S
Swen Schillig 已提交
259
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
260
			zfcp_fc_conditional_port_scan(adapter);
S
Swen Schillig 已提交
261 262
		break;
	case FSF_STATUS_READ_CFDC_UPDATED:
263
		zfcp_cfdc_adapter_access_changed(adapter);
S
Swen Schillig 已提交
264 265 266
		break;
	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
		adapter->adapter_features = sr_buf->payload.word[0];
L
Linus Torvalds 已提交
267 268 269
		break;
	}

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

S
Swen Schillig 已提交
273
	atomic_inc(&adapter->stat_miss);
274
	queue_work(adapter->work_queue, &adapter->stat_work);
S
Swen Schillig 已提交
275
}
L
Linus Torvalds 已提交
276

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

S
Swen Schillig 已提交
299
static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
300
{
S
Swen Schillig 已提交
301 302
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
		return;
L
Linus Torvalds 已提交
303

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

S
Swen Schillig 已提交
318 319 320 321 322
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 已提交
323

S
Swen Schillig 已提交
324
	zfcp_dbf_hba_fsf_response(req);
L
Linus Torvalds 已提交
325

S
Swen Schillig 已提交
326
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
327
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
328 329
		return;
	}
L
Linus Torvalds 已提交
330

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

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

S
Swen Schillig 已提交
402 403 404 405
	del_timer(&req->timer);
	zfcp_fsf_protstatus_eval(req);
	zfcp_fsf_fsfstatus_eval(req);
	req->handler(req);
L
Linus Torvalds 已提交
406

S
Swen Schillig 已提交
407
	if (req->erp_action)
408
		zfcp_erp_notify(req->erp_action, 0);
L
Linus Torvalds 已提交
409

S
Swen Schillig 已提交
410 411 412
	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
		zfcp_fsf_req_free(req);
	else
413
		complete(&req->completion);
S
Swen Schillig 已提交
414
}
L
Linus Torvalds 已提交
415

416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
/**
 * 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);
431
	zfcp_reqlist_move(adapter->req_list, &remove_queue);
432 433 434 435 436 437 438 439

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

440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
#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 已提交
468 469
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
{
470
	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
S
Swen Schillig 已提交
471 472
	struct zfcp_adapter *adapter = req->adapter;
	struct Scsi_Host *shost = adapter->scsi_host;
473
	struct fc_els_flogi *nsp, *plogi;
L
Linus Torvalds 已提交
474

475 476 477 478 479
	/* 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 已提交
480

S
Swen Schillig 已提交
481 482 483
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));

484 485
	fc_host_port_name(shost) = nsp->fl_wwpn;
	fc_host_node_name(shost) = nsp->fl_wwnn;
486
	fc_host_port_id(shost) = ntoh24(bottom->s_id);
487 488
	fc_host_speed(shost) =
		zfcp_fsf_convert_portspeed(bottom->fc_link_speed);
S
Swen Schillig 已提交
489 490 491
	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;

	adapter->hydra_version = bottom->adapter_type;
492
	adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK;
493 494
	adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
					 (u16)FSF_STATUS_READS_RECOM);
S
Swen Schillig 已提交
495 496 497 498 499 500

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

	switch (bottom->fc_topology) {
	case FSF_TOPO_P2P:
501
		adapter->peer_d_id = ntoh24(bottom->peer_d_id);
502 503
		adapter->peer_wwpn = plogi->fl_wwpn;
		adapter->peer_wwnn = plogi->fl_wwnn;
S
Swen Schillig 已提交
504 505 506 507 508 509 510
		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
		break;
	case FSF_TOPO_FABRIC:
		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
		break;
	case FSF_TOPO_AL:
		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
511
		/* fall through */
S
Swen Schillig 已提交
512 513
	default:
		dev_err(&adapter->ccw_device->dev,
514 515
			"Unknown or unsupported arbitrated loop "
			"fibre channel topology detected\n");
516
		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1");
S
Swen Schillig 已提交
517
		return -EIO;
L
Linus Torvalds 已提交
518
	}
S
Swen Schillig 已提交
519

520 521
	zfcp_scsi_set_prot(adapter);

L
Linus Torvalds 已提交
522 523 524
	return 0;
}

S
Swen Schillig 已提交
525
static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
C
Christof Schmitt 已提交
526 527
{
	struct zfcp_adapter *adapter = req->adapter;
S
Swen Schillig 已提交
528 529 530
	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 已提交
531

S
Swen Schillig 已提交
532 533
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;
L
Linus Torvalds 已提交
534

S
Swen Schillig 已提交
535 536 537 538 539 540
	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;
541

S
Swen Schillig 已提交
542 543 544 545
	switch (qtcb->header.fsf_status) {
	case FSF_GOOD:
		if (zfcp_fsf_exchange_config_evaluate(req))
			return;
L
Linus Torvalds 已提交
546

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

566
		zfcp_fsf_link_down_info_eval(req,
S
Swen Schillig 已提交
567
			&qtcb->header.fsf_status_qual.link_down_info);
L
Linus Torvalds 已提交
568
		break;
S
Swen Schillig 已提交
569
	default:
570
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3");
S
Swen Schillig 已提交
571 572
		return;
	}
L
Linus Torvalds 已提交
573

S
Swen Schillig 已提交
574 575 576 577 578 579 580
	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 已提交
581

S
Swen Schillig 已提交
582 583
	if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
		dev_err(&adapter->ccw_device->dev,
584 585
			"The FCP adapter only supports newer "
			"control block versions\n");
586
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4");
S
Swen Schillig 已提交
587 588 589 590
		return;
	}
	if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
		dev_err(&adapter->ccw_device->dev,
591 592
			"The FCP adapter only supports older "
			"control block versions\n");
593
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5");
S
Swen Schillig 已提交
594 595
	}
}
L
Linus Torvalds 已提交
596

S
Swen Schillig 已提交
597 598 599 600 601
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 已提交
602

S
Swen Schillig 已提交
603 604
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));
605

606
	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
S
Swen Schillig 已提交
607
		fc_host_permanent_port_name(shost) = bottom->wwpn;
608 609
		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
	} else
S
Swen Schillig 已提交
610 611
		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
612 613
	fc_host_supported_speeds(shost) =
		zfcp_fsf_convert_portspeed(bottom->supported_speed);
614 615 616 617
	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 已提交
618
}
L
Linus Torvalds 已提交
619

S
Swen Schillig 已提交
620 621 622 623 624 625 626 627 628 629 630 631 632
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);
633
		zfcp_fsf_link_down_info_eval(req,
S
Swen Schillig 已提交
634
			&qtcb->header.fsf_status_qual.link_down_info);
635
		break;
L
Linus Torvalds 已提交
636
	}
S
Swen Schillig 已提交
637
}
638

639
static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
S
Swen Schillig 已提交
640 641
{
	struct zfcp_fsf_req *req;
642 643 644 645 646 647 648

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

	if (unlikely(!req))
S
Swen Schillig 已提交
649
		return NULL;
650

S
Swen Schillig 已提交
651
	memset(req, 0, sizeof(*req));
652
	req->pool = pool;
S
Swen Schillig 已提交
653 654 655
	return req;
}

656
static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
S
Swen Schillig 已提交
657
{
658
	struct fsf_qtcb *qtcb;
S
Swen Schillig 已提交
659 660 661 662

	if (likely(pool))
		qtcb = mempool_alloc(pool, GFP_ATOMIC);
	else
663
		qtcb = kmem_cache_alloc(zfcp_fsf_qtcb_cache, GFP_ATOMIC);
664

S
Swen Schillig 已提交
665 666 667 668
	if (unlikely(!qtcb))
		return NULL;

	memset(qtcb, 0, sizeof(*qtcb));
669
	return qtcb;
S
Swen Schillig 已提交
670 671
}

672
static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
673
						u32 fsf_cmd, u8 sbtype,
674
						mempool_t *pool)
L
Linus Torvalds 已提交
675
{
676
	struct zfcp_adapter *adapter = qdio->adapter;
677
	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
L
Linus Torvalds 已提交
678

S
Swen Schillig 已提交
679
	if (unlikely(!req))
680
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
681

S
Swen Schillig 已提交
682 683
	if (adapter->req_no == 0)
		adapter->req_no++;
L
Linus Torvalds 已提交
684

S
Swen Schillig 已提交
685 686
	INIT_LIST_HEAD(&req->list);
	init_timer(&req->timer);
687
	init_completion(&req->completion);
L
Linus Torvalds 已提交
688

S
Swen Schillig 已提交
689 690
	req->adapter = adapter;
	req->fsf_command = fsf_cmd;
691
	req->req_id = adapter->req_no;
S
Swen Schillig 已提交
692

693 694 695 696 697 698 699 700 701 702 703
	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);
		}

704
		req->seq_no = adapter->fsf_req_seq_no;
705
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
S
Swen Schillig 已提交
706 707 708 709 710 711 712 713
		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;
	}

714 715 716
	zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,
			   req->qtcb, sizeof(struct fsf_qtcb));

S
Swen Schillig 已提交
717
	return req;
L
Linus Torvalds 已提交
718 719
}

S
Swen Schillig 已提交
720 721 722
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
723
	struct zfcp_qdio *qdio = adapter->qdio;
724
	int with_qtcb = (req->qtcb != NULL);
725
	int req_id = req->req_id;
S
Swen Schillig 已提交
726

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

729
	req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free);
S
Swen Schillig 已提交
730
	req->issued = get_clock();
731
	if (zfcp_qdio_send(qdio, &req->qdio_req)) {
S
Swen Schillig 已提交
732
		del_timer(&req->timer);
733
		/* lookup request again, list might have changed */
734
		zfcp_reqlist_find_rm(adapter->req_list, req_id);
735
		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1");
S
Swen Schillig 已提交
736 737 738 739
		return -EIO;
	}

	/* Don't increase for unsolicited status */
740
	if (with_qtcb)
S
Swen Schillig 已提交
741
		adapter->fsf_req_seq_no++;
742
	adapter->req_no++;
S
Swen Schillig 已提交
743 744 745 746 747 748 749 750 751

	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 已提交
752
 */
753
int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
L
Linus Torvalds 已提交
754
{
755
	struct zfcp_adapter *adapter = qdio->adapter;
S
Swen Schillig 已提交
756 757
	struct zfcp_fsf_req *req;
	struct fsf_status_read_buffer *sr_buf;
758
	struct page *page;
S
Swen Schillig 已提交
759
	int retval = -EIO;
L
Linus Torvalds 已提交
760

761
	spin_lock_irq(&qdio->req_q_lock);
762
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
763 764
		goto out;

765
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, 0,
766
				  adapter->pool.status_read_req);
767
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
768 769
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
770 771
	}

772 773
	page = mempool_alloc(adapter->pool.sr_data, GFP_ATOMIC);
	if (!page) {
S
Swen Schillig 已提交
774 775 776
		retval = -ENOMEM;
		goto failed_buf;
	}
777
	sr_buf = page_address(page);
S
Swen Schillig 已提交
778 779
	memset(sr_buf, 0, sizeof(*sr_buf));
	req->data = sr_buf;
780 781 782

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

S
Swen Schillig 已提交
784 785 786
	retval = zfcp_fsf_req_send(req);
	if (retval)
		goto failed_req_send;
L
Linus Torvalds 已提交
787

S
Swen Schillig 已提交
788 789 790
	goto out;

failed_req_send:
791
	req->data = NULL;
792
	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
S
Swen Schillig 已提交
793
failed_buf:
794
	zfcp_dbf_hba_fsf_uss("fssr__1", req);
S
Swen Schillig 已提交
795 796
	zfcp_fsf_req_free(req);
out:
797
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
798 799 800 801 802
	return retval;
}

static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
803
	struct scsi_device *sdev = req->data;
804
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
805 806 807 808 809
	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;

810 811
	zfcp_sdev = sdev_to_zfcp(sdev);

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

/**
859 860
 * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
 * @scmnd: The SCSI command to abort
S
Swen Schillig 已提交
861
 * Returns: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
862 863
 */

864
struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
L
Linus Torvalds 已提交
865
{
S
Swen Schillig 已提交
866
	struct zfcp_fsf_req *req = NULL;
867 868 869 870
	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;
871

872
	spin_lock_irq(&qdio->req_q_lock);
873
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
874
		goto out;
875
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
876
				  SBAL_SFLAGS0_TYPE_READ,
877
				  qdio->adapter->pool.scsi_abort);
878 879
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
880
		goto out;
881
	}
882

883
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
884 885
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		goto out_error_free;
L
Linus Torvalds 已提交
886

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

889
	req->data = sdev;
S
Swen Schillig 已提交
890
	req->handler = zfcp_fsf_abort_fcp_command_handler;
891 892
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
893 894 895 896 897 898 899 900 901 902
	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:
903
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
904
	return req;
L
Linus Torvalds 已提交
905 906
}

S
Swen Schillig 已提交
907
static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
908
{
S
Swen Schillig 已提交
909
	struct zfcp_adapter *adapter = req->adapter;
910
	struct zfcp_fsf_ct_els *ct = req->data;
S
Swen Schillig 已提交
911
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
912

913
	ct->status = -EINVAL;
L
Linus Torvalds 已提交
914

S
Swen Schillig 已提交
915
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
916 917 918 919
		goto skip_fsfstatus;

	switch (header->fsf_status) {
        case FSF_GOOD:
920
		zfcp_dbf_san_res("fsscth2", req);
921
		ct->status = 0;
L
Linus Torvalds 已提交
922 923
		break;
        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
924
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
925 926 927 928 929
		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 已提交
930
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
931 932 933 934 935 936
			break;
                }
                break;
	case FSF_ACCESS_DENIED:
		break;
        case FSF_PORT_BOXED:
937
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
938
		break;
S
Swen Schillig 已提交
939
	case FSF_PORT_HANDLE_NOT_VALID:
940
		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1");
941
		/* fall through */
S
Swen Schillig 已提交
942
	case FSF_GENERIC_COMMAND_REJECTED:
L
Linus Torvalds 已提交
943 944 945 946
	case FSF_PAYLOAD_SIZE_MISMATCH:
	case FSF_REQUEST_SIZE_TOO_LARGE:
	case FSF_RESPONSE_SIZE_TOO_LARGE:
	case FSF_SBAL_MISMATCH:
S
Swen Schillig 已提交
947
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
948 949 950 951
		break;
	}

skip_fsfstatus:
952 953
	if (ct->handler)
		ct->handler(ct->handler_data);
S
Swen Schillig 已提交
954
}
L
Linus Torvalds 已提交
955

956 957
static void zfcp_fsf_setup_ct_els_unchained(struct zfcp_qdio *qdio,
					    struct zfcp_qdio_req *q_req,
958 959 960
					    struct scatterlist *sg_req,
					    struct scatterlist *sg_resp)
{
961 962 963
	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);
964 965
}

966 967
static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
				       struct scatterlist *sg_req,
968
				       struct scatterlist *sg_resp)
S
Swen Schillig 已提交
969
{
970
	struct zfcp_adapter *adapter = req->adapter;
971 972
	struct zfcp_qdio *qdio = adapter->qdio;
	struct fsf_qtcb *qtcb = req->qtcb;
973
	u32 feat = adapter->adapter_features;
S
Swen Schillig 已提交
974

975 976 977 978 979
	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;
980

981 982 983 984
		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);
985 986 987 988
		return 0;
	}

	/* use single, unchained SBAL if it can hold the request */
989
	if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
990
		zfcp_fsf_setup_ct_els_unchained(qdio, &req->qdio_req,
991
						sg_req, sg_resp);
992 993 994
		return 0;
	}

995 996 997 998
	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS))
		return -EOPNOTSUPP;

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

1001 1002 1003 1004 1005 1006
	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))
1007
		return -EIO;
1008 1009 1010 1011

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

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

1013 1014 1015 1016 1017 1018
	return 0;
}

static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
				 struct scatterlist *sg_req,
				 struct scatterlist *sg_resp,
1019
				 unsigned int timeout)
1020 1021 1022
{
	int ret;

1023
	ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp);
1024 1025 1026
	if (ret)
		return ret;

1027
	/* common settings for ct/gs and els requests */
1028 1029
	if (timeout > 255)
		timeout = 255; /* max value accepted by hardware */
1030
	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
1031 1032
	req->qtcb->bottom.support.timeout = timeout;
	zfcp_fsf_start_timer(req, (timeout + 10) * HZ);
S
Swen Schillig 已提交
1033 1034

	return 0;
L
Linus Torvalds 已提交
1035 1036 1037
}

/**
S
Swen Schillig 已提交
1038 1039 1040
 * 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 已提交
1041
 */
1042
int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
1043 1044
		     struct zfcp_fsf_ct_els *ct, mempool_t *pool,
		     unsigned int timeout)
L
Linus Torvalds 已提交
1045
{
1046
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
S
Swen Schillig 已提交
1047 1048
	struct zfcp_fsf_req *req;
	int ret = -EIO;
L
Linus Torvalds 已提交
1049

1050
	spin_lock_irq(&qdio->req_q_lock);
1051
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1052
		goto out;
L
Linus Torvalds 已提交
1053

1054
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC,
1055
				  SBAL_SFLAGS0_TYPE_WRITE_READ, pool);
1056

1057
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1058 1059
		ret = PTR_ERR(req);
		goto out;
1060 1061
	}

1062
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1063
	ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout);
C
Christof Schmitt 已提交
1064
	if (ret)
L
Linus Torvalds 已提交
1065 1066
		goto failed_send;

S
Swen Schillig 已提交
1067
	req->handler = zfcp_fsf_send_ct_handler;
1068
	req->qtcb->header.port_handle = wka_port->handle;
S
Swen Schillig 已提交
1069 1070
	req->data = ct;

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

S
Swen Schillig 已提交
1073 1074 1075
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;
L
Linus Torvalds 已提交
1076

S
Swen Schillig 已提交
1077
	goto out;
L
Linus Torvalds 已提交
1078

S
Swen Schillig 已提交
1079 1080 1081
failed_send:
	zfcp_fsf_req_free(req);
out:
1082
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1083
	return ret;
L
Linus Torvalds 已提交
1084 1085
}

S
Swen Schillig 已提交
1086
static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1087
{
1088
	struct zfcp_fsf_ct_els *send_els = req->data;
S
Swen Schillig 已提交
1089 1090
	struct zfcp_port *port = send_els->port;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1091

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

S
Swen Schillig 已提交
1094
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
1095 1096 1097 1098
		goto skip_fsfstatus;

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

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

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

1152
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS,
1153
				  SBAL_SFLAGS0_TYPE_WRITE_READ, NULL);
1154

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

1160
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1161

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

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

S
Swen Schillig 已提交
1167 1168 1169
	if (ret)
		goto failed_send;

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

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

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

	goto out;

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

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

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

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

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

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

S
Swen Schillig 已提交
1211
	req->qtcb->bottom.config.feature_selection =
1212 1213
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
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 1257 1258
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
			FSF_FEATURE_NOTIFICATION_LOST |
			FSF_FEATURE_UPDATE_ALERT;

	if (data)
S
Swen Schillig 已提交
1259
		req->data = data;
1260

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

S
Swen Schillig 已提交
1267
	zfcp_fsf_req_free(req);
1268
	return retval;
1269

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

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

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

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

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

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

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

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

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

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

1332
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1333 1334
		return -EOPNOTSUPP;

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

1339
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
1340
				  SBAL_SFLAGS0_TYPE_READ, NULL);
1341

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

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

1350
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1351

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

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

S
Swen Schillig 已提交
1360
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1361 1362

	return retval;
1363 1364

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

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

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

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

out:
1436
	put_device(&port->dev);
L
Linus Torvalds 已提交
1437 1438
}

S
Swen Schillig 已提交
1439 1440 1441 1442
/**
 * 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 已提交
1443
 */
S
Swen Schillig 已提交
1444
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1445
{
1446
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1447
	struct zfcp_port *port = erp_action->port;
1448
	struct zfcp_fsf_req *req;
S
Swen Schillig 已提交
1449 1450
	int retval = -EIO;

1451
	spin_lock_irq(&qdio->req_q_lock);
1452
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1453 1454
		goto out;

1455
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1456
				  SBAL_SFLAGS0_TYPE_READ,
1457
				  qdio->adapter->pool.erp_req);
1458

1459
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1460
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1461
		goto out;
S
Swen Schillig 已提交
1462
	}
L
Linus Torvalds 已提交
1463

1464
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1465
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1466

S
Swen Schillig 已提交
1467
	req->handler = zfcp_fsf_open_port_handler;
1468
	hton24(req->qtcb->bottom.support.d_id, port->d_id);
1469
	req->data = port;
S
Swen Schillig 已提交
1470
	req->erp_action = erp_action;
1471
	erp_action->fsf_req_id = req->req_id;
1472
	get_device(&port->dev);
S
Swen Schillig 已提交
1473

1474
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1475
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1476
	if (retval) {
S
Swen Schillig 已提交
1477
		zfcp_fsf_req_free(req);
1478
		erp_action->fsf_req_id = 0;
1479
		put_device(&port->dev);
L
Linus Torvalds 已提交
1480
	}
S
Swen Schillig 已提交
1481
out:
1482
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1483 1484 1485
	return retval;
}

S
Swen Schillig 已提交
1486
static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1487
{
S
Swen Schillig 已提交
1488
	struct zfcp_port *port = req->data;
L
Linus Torvalds 已提交
1489

S
Swen Schillig 已提交
1490
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1491
		return;
L
Linus Torvalds 已提交
1492

S
Swen Schillig 已提交
1493
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1494
	case FSF_PORT_HANDLE_NOT_VALID:
1495
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1");
S
Swen Schillig 已提交
1496
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1497 1498 1499 1500
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		break;
	case FSF_GOOD:
1501
		zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN);
L
Linus Torvalds 已提交
1502 1503 1504 1505
		break;
	}
}

S
Swen Schillig 已提交
1506 1507 1508 1509
/**
 * 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 已提交
1510
 */
S
Swen Schillig 已提交
1511
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1512
{
1513
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1514 1515 1516
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1517
	spin_lock_irq(&qdio->req_q_lock);
1518
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1519 1520
		goto out;

1521
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1522
				  SBAL_SFLAGS0_TYPE_READ,
1523
				  qdio->adapter->pool.erp_req);
1524

1525
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1526
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1527
		goto out;
S
Swen Schillig 已提交
1528
	}
L
Linus Torvalds 已提交
1529

1530
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1531
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1532

S
Swen Schillig 已提交
1533 1534 1535 1536
	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;
1537
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1538

1539
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1540
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1541
	if (retval) {
S
Swen Schillig 已提交
1542
		zfcp_fsf_req_free(req);
1543
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1544
	}
S
Swen Schillig 已提交
1545
out:
1546
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1547 1548 1549
	return retval;
}

1550 1551
static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
{
1552
	struct zfcp_fc_wka_port *wka_port = req->data;
1553 1554 1555
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
1556
		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1557 1558 1559 1560 1561 1562 1563
		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);
1564
		/* fall through */
1565 1566
	case FSF_ADAPTER_STATUS_AVAILABLE:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1567
		/* fall through */
1568
	case FSF_ACCESS_DENIED:
1569
		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1570 1571 1572
		break;
	case FSF_GOOD:
		wka_port->handle = header->port_handle;
1573 1574
		/* fall through */
	case FSF_PORT_ALREADY_OPEN:
1575
		wka_port->status = ZFCP_FC_WKA_PORT_ONLINE;
1576 1577 1578 1579 1580 1581 1582
	}
out:
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_open_wka_port - create and send open wka-port request
1583
 * @wka_port: pointer to struct zfcp_fc_wka_port
1584 1585
 * Returns: 0 on success, error otherwise
 */
1586
int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
1587
{
1588
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1589 1590 1591
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1592
	spin_lock_irq(&qdio->req_q_lock);
1593
	if (zfcp_qdio_sbal_get(qdio))
1594 1595
		goto out;

1596
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1597
				  SBAL_SFLAGS0_TYPE_READ,
1598
				  qdio->adapter->pool.erp_req);
1599

1600
	if (IS_ERR(req)) {
1601 1602 1603 1604
		retval = PTR_ERR(req);
		goto out;
	}

1605
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1606
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1607 1608

	req->handler = zfcp_fsf_open_wka_port_handler;
1609
	hton24(req->qtcb->bottom.support.d_id, wka_port->d_id);
1610 1611 1612 1613 1614 1615 1616
	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:
1617
	spin_unlock_irq(&qdio->req_q_lock);
1618 1619 1620 1621 1622
	return retval;
}

static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
{
1623
	struct zfcp_fc_wka_port *wka_port = req->data;
1624 1625 1626

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

1630
	wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1631 1632 1633 1634 1635
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_close_wka_port - create and send close wka port request
1636
 * @wka_port: WKA port to open
1637 1638
 * Returns: 0 on success, error otherwise
 */
1639
int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
1640
{
1641
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1642 1643 1644
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1645
	spin_lock_irq(&qdio->req_q_lock);
1646
	if (zfcp_qdio_sbal_get(qdio))
1647 1648
		goto out;

1649
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1650
				  SBAL_SFLAGS0_TYPE_READ,
1651
				  qdio->adapter->pool.erp_req);
1652

1653
	if (IS_ERR(req)) {
1654 1655 1656 1657
		retval = PTR_ERR(req);
		goto out;
	}

1658
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1659
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669

	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:
1670
	spin_unlock_irq(&qdio->req_q_lock);
1671 1672 1673
	return retval;
}

S
Swen Schillig 已提交
1674
static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1675
{
S
Swen Schillig 已提交
1676 1677
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
1678
	struct scsi_device *sdev;
L
Linus Torvalds 已提交
1679

S
Swen Schillig 已提交
1680
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1681
		return;
L
Linus Torvalds 已提交
1682 1683 1684

	switch (header->fsf_status) {
	case FSF_PORT_HANDLE_NOT_VALID:
1685
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1");
S
Swen Schillig 已提交
1686
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1687 1688
		break;
	case FSF_ACCESS_DENIED:
1689
		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
L
Linus Torvalds 已提交
1690 1691
		break;
	case FSF_PORT_BOXED:
1692 1693 1694
		/* can't use generic zfcp_erp_modify_port_status because
		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1695 1696 1697 1698
		shost_for_each_device(sdev, port->adapter->scsi_host)
			if (sdev_to_zfcp(sdev)->port == port)
				atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
						  &sdev_to_zfcp(sdev)->status);
1699 1700
		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
1701
				     "fscpph2");
1702
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1703 1704 1705 1706
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
S
Swen Schillig 已提交
1707
			/* fall through */
L
Linus Torvalds 已提交
1708
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1709
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1710 1711 1712 1713 1714 1715 1716 1717
			break;
		}
		break;
	case FSF_GOOD:
		/* can't use generic zfcp_erp_modify_port_status because
		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
		 */
		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1718 1719 1720 1721
		shost_for_each_device(sdev, port->adapter->scsi_host)
			if (sdev_to_zfcp(sdev)->port == port)
				atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
						  &sdev_to_zfcp(sdev)->status);
L
Linus Torvalds 已提交
1722 1723 1724 1725
		break;
	}
}

S
Swen Schillig 已提交
1726 1727 1728 1729
/**
 * zfcp_fsf_close_physical_port - close physical port
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success
L
Linus Torvalds 已提交
1730
 */
S
Swen Schillig 已提交
1731
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1732
{
1733
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1734 1735 1736
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1737
	spin_lock_irq(&qdio->req_q_lock);
1738
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1739 1740
		goto out;

1741
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
1742
				  SBAL_SFLAGS0_TYPE_READ,
1743
				  qdio->adapter->pool.erp_req);
1744

1745
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1746 1747 1748
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1749

1750
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1751
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1752

S
Swen Schillig 已提交
1753 1754 1755 1756
	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;
1757
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1758

1759
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1760
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1761
	if (retval) {
S
Swen Schillig 已提交
1762
		zfcp_fsf_req_free(req);
1763
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1764
	}
S
Swen Schillig 已提交
1765
out:
1766
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1767 1768 1769
	return retval;
}

1770
static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1771
{
S
Swen Schillig 已提交
1772
	struct zfcp_adapter *adapter = req->adapter;
1773
	struct scsi_device *sdev = req->data;
1774
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
1775 1776
	struct fsf_qtcb_header *header = &req->qtcb->header;
	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
L
Linus Torvalds 已提交
1777

S
Swen Schillig 已提交
1778
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1779
		return;
L
Linus Torvalds 已提交
1780

1781 1782
	zfcp_sdev = sdev_to_zfcp(sdev);

L
Linus Torvalds 已提交
1783
	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1784
			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
1785 1786 1787
			  ZFCP_STATUS_LUN_SHARED |
			  ZFCP_STATUS_LUN_READONLY,
			  &zfcp_sdev->status);
L
Linus Torvalds 已提交
1788 1789 1790 1791

	switch (header->fsf_status) {

	case FSF_PORT_HANDLE_NOT_VALID:
1792
		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
S
Swen Schillig 已提交
1793
		/* fall through */
L
Linus Torvalds 已提交
1794 1795 1796
	case FSF_LUN_ALREADY_OPEN:
		break;
	case FSF_ACCESS_DENIED:
1797 1798
		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1799 1800
		break;
	case FSF_PORT_BOXED:
1801 1802 1803
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
1804
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2");
1805
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1806 1807
		break;
	case FSF_LUN_SHARING_VIOLATION:
1808
		zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual);
S
Swen Schillig 已提交
1809
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1810 1811
		break;
	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
S
Swen Schillig 已提交
1812
		dev_warn(&adapter->ccw_device->dev,
1813 1814
			 "No handle is available for LUN "
			 "0x%016Lx on port 0x%016Lx\n",
1815 1816
			 (unsigned long long)zfcp_scsi_dev_lun(sdev),
			 (unsigned long long)zfcp_sdev->port->wwpn);
1817
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
S
Swen Schillig 已提交
1818 1819 1820
		/* fall through */
	case FSF_INVALID_COMMAND_OPTION:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1821 1822 1823 1824
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1825
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
1826
			/* fall through */
L
Linus Torvalds 已提交
1827
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1828
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1829 1830 1831 1832 1833
			break;
		}
		break;

	case FSF_GOOD:
1834 1835
		zfcp_sdev->lun_handle = header->lun_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
1836
		zfcp_cfdc_open_lun_eval(sdev, bottom);
L
Linus Torvalds 已提交
1837 1838 1839 1840
		break;
	}
}

S
Swen Schillig 已提交
1841
/**
1842
 * zfcp_fsf_open_lun - open LUN
S
Swen Schillig 已提交
1843 1844
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1845
 */
1846
int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1847
{
S
Swen Schillig 已提交
1848
	struct zfcp_adapter *adapter = erp_action->adapter;
1849
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1850 1851 1852
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1853
	spin_lock_irq(&qdio->req_q_lock);
1854
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1855 1856
		goto out;

1857
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1858
				  SBAL_SFLAGS0_TYPE_READ,
1859
				  adapter->pool.erp_req);
1860

1861
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1862 1863 1864 1865
		retval = PTR_ERR(req);
		goto out;
	}

1866
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1867
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1868

S
Swen Schillig 已提交
1869
	req->qtcb->header.port_handle = erp_action->port->handle;
1870 1871 1872
	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 已提交
1873
	req->erp_action = erp_action;
1874
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1875 1876 1877 1878

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

1879
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1880
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1881
	if (retval) {
S
Swen Schillig 已提交
1882
		zfcp_fsf_req_free(req);
1883
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1884
	}
S
Swen Schillig 已提交
1885
out:
1886
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1887 1888 1889
	return retval;
}

1890
static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1891
{
1892
	struct scsi_device *sdev = req->data;
1893
	struct zfcp_scsi_dev *zfcp_sdev;
L
Linus Torvalds 已提交
1894

S
Swen Schillig 已提交
1895
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1896
		return;
L
Linus Torvalds 已提交
1897

1898 1899
	zfcp_sdev = sdev_to_zfcp(sdev);

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

/**
1933 1934
 * zfcp_fsf_close_LUN - close LUN
 * @erp_action: pointer to erp_action triggering the "close LUN"
S
Swen Schillig 已提交
1935
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1936
 */
1937
int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1938
{
1939
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1940
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
S
Swen Schillig 已提交
1941 1942
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1943

1944
	spin_lock_irq(&qdio->req_q_lock);
1945
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1946
		goto out;
1947

1948
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
1949
				  SBAL_SFLAGS0_TYPE_READ,
1950
				  qdio->adapter->pool.erp_req);
1951

1952
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1953 1954 1955
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1956

1957
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1958
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1959

S
Swen Schillig 已提交
1960
	req->qtcb->header.port_handle = erp_action->port->handle;
1961 1962 1963
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->handler = zfcp_fsf_close_lun_handler;
	req->data = erp_action->sdev;
S
Swen Schillig 已提交
1964
	req->erp_action = erp_action;
1965
	erp_action->fsf_req_id = req->req_id;
1966

1967
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1968 1969 1970
	retval = zfcp_fsf_req_send(req);
	if (retval) {
		zfcp_fsf_req_free(req);
1971
		erp_action->fsf_req_id = 0;
S
Swen Schillig 已提交
1972 1973
	}
out:
1974
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1975
	return retval;
L
Linus Torvalds 已提交
1976 1977
}

1978 1979 1980
static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
{
	lat_rec->sum += lat;
S
Swen Schillig 已提交
1981 1982
	lat_rec->min = min(lat_rec->min, lat);
	lat_rec->max = max(lat_rec->max, lat);
1983 1984
}

1985
static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
1986
{
1987 1988
	struct fsf_qual_latency_info *lat_in;
	struct latency_cont *lat = NULL;
1989
	struct zfcp_scsi_dev *zfcp_sdev;
1990 1991
	struct zfcp_blk_drv_data blktrc;
	int ticks = req->adapter->timer_ticks;
1992

1993
	lat_in = &req->qtcb->prefix.prot_status_qual.latency_info;
1994

1995 1996 1997 1998
	blktrc.flags = 0;
	blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		blktrc.flags |= ZFCP_BLK_REQ_ERROR;
1999
	blktrc.inb_usage = 0;
2000
	blktrc.outb_usage = req->qdio_req.qdio_outb_usage;
2001

2002 2003
	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
	    !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2004
		zfcp_sdev = sdev_to_zfcp(scsi->device);
2005 2006 2007 2008 2009
		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) {
2010 2011
		case FSF_DATADIR_DIF_READ_STRIP:
		case FSF_DATADIR_DIF_READ_CONVERT:
2012
		case FSF_DATADIR_READ:
2013
			lat = &zfcp_sdev->latencies.read;
2014
			break;
2015 2016
		case FSF_DATADIR_DIF_WRITE_INSERT:
		case FSF_DATADIR_DIF_WRITE_CONVERT:
2017
		case FSF_DATADIR_WRITE:
2018
			lat = &zfcp_sdev->latencies.write;
2019 2020
			break;
		case FSF_DATADIR_CMND:
2021
			lat = &zfcp_sdev->latencies.cmd;
2022 2023
			break;
		}
L
Linus Torvalds 已提交
2024

2025
		if (lat) {
2026
			spin_lock(&zfcp_sdev->latencies.lock);
2027 2028 2029
			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
			lat->counter++;
2030
			spin_unlock(&zfcp_sdev->latencies.lock);
2031
		}
S
Stefan Raspl 已提交
2032 2033
	}

2034 2035
	blk_add_driver_data(scsi->request->q, scsi->request, &blktrc,
			    sizeof(blktrc));
S
Stefan Raspl 已提交
2036 2037
}

2038
static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
S
Swen Schillig 已提交
2039
{
2040 2041
	struct scsi_cmnd *scmnd = req->data;
	struct scsi_device *sdev = scmnd->device;
2042
	struct zfcp_scsi_dev *zfcp_sdev;
S
Swen Schillig 已提交
2043 2044 2045
	struct fsf_qtcb_header *header = &req->qtcb->header;

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

2048 2049
	zfcp_sdev = sdev_to_zfcp(sdev);

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

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 已提交
2124
	}
2125

2126 2127
	zfcp_fsf_fcp_handler_common(req);

2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152
	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);
2153
	zfcp_dbf_scsi_result(scpnt, req);
2154 2155 2156 2157 2158 2159 2160 2161 2162 2163

	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 已提交
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 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203
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 已提交
2204
/**
2205
 * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
S
Swen Schillig 已提交
2206
 * @scsi_cmnd: scsi command to be sent
L
Linus Torvalds 已提交
2207
 */
2208
int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
L
Linus Torvalds 已提交
2209
{
S
Swen Schillig 已提交
2210
	struct zfcp_fsf_req *req;
2211
	struct fcp_cmnd *fcp_cmnd;
2212
	u8 sbtype = SBAL_SFLAGS0_TYPE_READ;
2213
	int retval = -EIO;
2214 2215 2216
	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;
2217
	struct zfcp_qdio *qdio = adapter->qdio;
2218
	struct fsf_qtcb_bottom_io *io;
2219
	unsigned long flags;
L
Linus Torvalds 已提交
2220

2221
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2222 2223
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return -EBUSY;
L
Linus Torvalds 已提交
2224

2225
	spin_lock_irqsave(&qdio->req_q_lock, flags);
2226
	if (atomic_read(&qdio->req_q_free) <= 0) {
2227
		atomic_inc(&qdio->req_q_full);
S
Swen Schillig 已提交
2228
		goto out;
2229
	}
2230

2231
	if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE)
2232
		sbtype = SBAL_SFLAGS0_TYPE_WRITE;
2233

2234
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2235
				  sbtype, adapter->pool.scsi_req);
2236

2237
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2238 2239 2240 2241
		retval = PTR_ERR(req);
		goto out;
	}

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

	io = &req->qtcb->bottom.io;
2245
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
S
Swen Schillig 已提交
2246
	req->data = scsi_cmnd;
2247
	req->handler = zfcp_fsf_fcp_cmnd_handler;
2248 2249
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
2250 2251
	io->service_class = FSF_CLASS_3;
	io->fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2252

2253 2254 2255
	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 已提交
2256 2257
	}

2258 2259
	if (zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction))
		goto failed_scsi_cmnd;
2260

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

2264 2265 2266
	if (scsi_prot_sg_count(scsi_cmnd)) {
		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
				       scsi_prot_sg_count(scsi_cmnd));
2267 2268 2269 2270 2271
		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(
2272 2273 2274
						scsi_prot_sglist(scsi_cmnd));
	}

2275 2276 2277
	retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
					 scsi_sglist(scsi_cmnd));
	if (unlikely(retval))
S
Swen Schillig 已提交
2278
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2279

2280
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
2281 2282
	if (zfcp_adapter_multi_buffer_active(adapter))
		zfcp_qdio_set_scount(qdio, &req->qdio_req);
2283

S
Swen Schillig 已提交
2284 2285 2286
	retval = zfcp_fsf_req_send(req);
	if (unlikely(retval))
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2287

S
Swen Schillig 已提交
2288
	goto out;
L
Linus Torvalds 已提交
2289

S
Swen Schillig 已提交
2290 2291 2292 2293
failed_scsi_cmnd:
	zfcp_fsf_req_free(req);
	scsi_cmnd->host_scribble = NULL;
out:
2294
	spin_unlock_irqrestore(&qdio->req_q_lock, flags);
S
Swen Schillig 已提交
2295
	return retval;
L
Linus Torvalds 已提交
2296 2297
}

2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312
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 已提交
2313
/**
2314 2315
 * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
 * @scmnd: SCSI command to send the task management command for
S
Swen Schillig 已提交
2316 2317
 * @tm_flags: unsigned byte for task management flags
 * Returns: on success pointer to struct fsf_req, NULL otherwise
L
Linus Torvalds 已提交
2318
 */
2319 2320
struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
					    u8 tm_flags)
L
Linus Torvalds 已提交
2321
{
S
Swen Schillig 已提交
2322
	struct zfcp_fsf_req *req = NULL;
2323
	struct fcp_cmnd *fcp_cmnd;
2324 2325
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
L
Linus Torvalds 已提交
2326

2327
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2328 2329
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return NULL;
L
Linus Torvalds 已提交
2330

2331
	spin_lock_irq(&qdio->req_q_lock);
2332
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
2333
		goto out;
2334

2335
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2336
				  SBAL_SFLAGS0_TYPE_WRITE,
2337
				  qdio->adapter->pool.scsi_req);
2338

2339 2340
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
2341
		goto out;
2342
	}
L
Linus Torvalds 已提交
2343

2344
	req->data = scmnd;
2345
	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
2346 2347
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
2348 2349
	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
2350
	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2351

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

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

S
Swen Schillig 已提交
2357 2358 2359
	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;
L
Linus Torvalds 已提交
2360

S
Swen Schillig 已提交
2361 2362 2363
	zfcp_fsf_req_free(req);
	req = NULL;
out:
2364
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
2365 2366
	return req;
}
L
Linus Torvalds 已提交
2367

S
Swen Schillig 已提交
2368 2369
static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
{
L
Linus Torvalds 已提交
2370 2371
}

S
Swen Schillig 已提交
2372 2373 2374 2375 2376
/**
 * zfcp_fsf_control_file - control file upload/download
 * @adapter: pointer to struct zfcp_adapter
 * @fsf_cfdc: pointer to struct zfcp_fsf_cfdc
 * Returns: on success pointer to struct zfcp_fsf_req, NULL otherwise
L
Linus Torvalds 已提交
2377
 */
S
Swen Schillig 已提交
2378 2379
struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
					   struct zfcp_fsf_cfdc *fsf_cfdc)
L
Linus Torvalds 已提交
2380
{
2381
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
2382 2383
	struct zfcp_fsf_req *req = NULL;
	struct fsf_qtcb_bottom_support *bottom;
2384
	int retval = -EIO;
2385
	u8 direction;
S
Swen Schillig 已提交
2386 2387 2388 2389 2390 2391

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

	switch (fsf_cfdc->command) {
	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
2392
		direction = SBAL_SFLAGS0_TYPE_WRITE;
S
Swen Schillig 已提交
2393 2394
		break;
	case FSF_QTCB_UPLOAD_CONTROL_FILE:
2395
		direction = SBAL_SFLAGS0_TYPE_READ;
S
Swen Schillig 已提交
2396 2397 2398 2399
		break;
	default:
		return ERR_PTR(-EINVAL);
	}
L
Linus Torvalds 已提交
2400

2401
	spin_lock_irq(&qdio->req_q_lock);
2402
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
2403
		goto out;
L
Linus Torvalds 已提交
2404

2405
	req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, direction, NULL);
2406
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2407 2408 2409
		retval = -EPERM;
		goto out;
	}
L
Linus Torvalds 已提交
2410

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

S
Swen Schillig 已提交
2413 2414 2415
	bottom = &req->qtcb->bottom.support;
	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
	bottom->option = fsf_cfdc->option;
2416

2417
	retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);
2418

2419 2420
	if (retval ||
		(zfcp_qdio_real_bytes(fsf_cfdc->sg) != ZFCP_CFDC_MAX_SIZE)) {
S
Swen Schillig 已提交
2421
		zfcp_fsf_req_free(req);
2422
		retval = -EIO;
S
Swen Schillig 已提交
2423 2424
		goto out;
	}
2425 2426 2427
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
	if (zfcp_adapter_multi_buffer_active(adapter))
		zfcp_qdio_set_scount(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
2428

S
Swen Schillig 已提交
2429 2430 2431
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
out:
2432
	spin_unlock_irq(&qdio->req_q_lock);
2433

S
Swen Schillig 已提交
2434
	if (!retval) {
2435
		wait_for_completion(&req->completion);
S
Swen Schillig 已提交
2436
		return req;
L
Linus Torvalds 已提交
2437
	}
S
Swen Schillig 已提交
2438
	return ERR_PTR(retval);
L
Linus Torvalds 已提交
2439
}
2440 2441 2442 2443 2444 2445

/**
 * 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
 */
2446
void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2447
{
2448
	struct zfcp_adapter *adapter = qdio->adapter;
2449
	struct qdio_buffer *sbal = qdio->res_q[sbal_idx];
2450 2451
	struct qdio_buffer_element *sbale;
	struct zfcp_fsf_req *fsf_req;
2452
	unsigned long req_id;
2453 2454 2455 2456 2457 2458
	int idx;

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

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

2461
		if (!fsf_req) {
2462 2463 2464 2465
			/*
			 * Unknown request means that we have potentially memory
			 * corruption and must stop the machine immediately.
			 */
2466
			zfcp_qdio_siosl(adapter);
2467 2468
			panic("error: unknown req_id (%lx) on adapter %s.\n",
			      req_id, dev_name(&adapter->ccw_device->dev));
2469
		}
2470

2471
		fsf_req->qdio_req.sbal_response = sbal_idx;
2472 2473
		zfcp_fsf_req_complete(fsf_req);

2474
		if (likely(sbale->eflags & SBAL_EFLAGS_LAST_ENTRY))
2475 2476 2477
			break;
	}
}
2478 2479 2480 2481 2482 2483 2484 2485 2486

struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *qdio,
				      struct qdio_buffer *sbal)
{
	struct qdio_buffer_element *sbale = &sbal->element[0];
	u64 req_id = (unsigned long) sbale->addr;

	return zfcp_reqlist_find(qdio->adapter->req_list, req_id);
}