zfcp_fsf.c 65.9 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 Corporation 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 23
static void zfcp_fsf_request_timeout_handler(unsigned long data)
{
	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
24
	zfcp_qdio_siosl(adapter);
25 26
	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
				"fsrth_1", NULL);
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
}

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

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

85 86 87
	if (likely(req->qtcb))
		kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb);
	kfree(req);
L
Linus Torvalds 已提交
88 89
}

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

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

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

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

	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
116

117
	zfcp_scsi_schedule_rports_block(adapter);
118

S
Swen Schillig 已提交
119
	if (!link_down)
120
		goto out;
121

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

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

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

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

S
Swen Schillig 已提交
213
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
S
Swen Schillig 已提交
214
		zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf);
215
		mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
216 217 218
		zfcp_fsf_req_free(req);
		return;
	}
L
Linus Torvalds 已提交
219

S
Swen Schillig 已提交
220
	zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf);
L
Linus Torvalds 已提交
221

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

S
Swen Schillig 已提交
254 255 256
		break;
	case FSF_STATUS_READ_NOTIFICATION_LOST:
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
257
			zfcp_cfdc_adapter_access_changed(adapter);
S
Swen Schillig 已提交
258
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
259
			queue_work(adapter->work_queue, &adapter->scan_work);
S
Swen Schillig 已提交
260 261
		break;
	case FSF_STATUS_READ_CFDC_UPDATED:
262
		zfcp_cfdc_adapter_access_changed(adapter);
S
Swen Schillig 已提交
263 264 265
		break;
	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
		adapter->adapter_features = sr_buf->payload.word[0];
L
Linus Torvalds 已提交
266 267 268
		break;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

S
Swen Schillig 已提交
441 442
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
{
443
	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
S
Swen Schillig 已提交
444 445
	struct zfcp_adapter *adapter = req->adapter;
	struct Scsi_Host *shost = adapter->scsi_host;
446
	struct fc_els_flogi *nsp, *plogi;
L
Linus Torvalds 已提交
447

448 449 450 451 452
	/* 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 已提交
453

S
Swen Schillig 已提交
454 455 456
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));

457 458
	fc_host_port_name(shost) = nsp->fl_wwpn;
	fc_host_node_name(shost) = nsp->fl_wwnn;
459
	fc_host_port_id(shost) = ntoh24(bottom->s_id);
S
Swen Schillig 已提交
460 461 462 463
	fc_host_speed(shost) = bottom->fc_link_speed;
	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;

	adapter->hydra_version = bottom->adapter_type;
464
	adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK;
465 466
	adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
					 (u16)FSF_STATUS_READS_RECOM);
S
Swen Schillig 已提交
467 468 469 470 471 472

	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:
473
		adapter->peer_d_id = ntoh24(bottom->peer_d_id);
474 475
		adapter->peer_wwpn = plogi->fl_wwpn;
		adapter->peer_wwnn = plogi->fl_wwnn;
S
Swen Schillig 已提交
476 477 478 479 480 481 482
		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;
483
		/* fall through */
S
Swen Schillig 已提交
484 485
	default:
		dev_err(&adapter->ccw_device->dev,
486 487
			"Unknown or unsupported arbitrated loop "
			"fibre channel topology detected\n");
488
		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req);
S
Swen Schillig 已提交
489
		return -EIO;
L
Linus Torvalds 已提交
490
	}
S
Swen Schillig 已提交
491

492 493
	zfcp_scsi_set_prot(adapter);

L
Linus Torvalds 已提交
494 495 496
	return 0;
}

S
Swen Schillig 已提交
497
static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
C
Christof Schmitt 已提交
498 499
{
	struct zfcp_adapter *adapter = req->adapter;
S
Swen Schillig 已提交
500 501 502
	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 已提交
503

S
Swen Schillig 已提交
504 505
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;
L
Linus Torvalds 已提交
506

S
Swen Schillig 已提交
507 508 509 510 511 512
	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;
513

S
Swen Schillig 已提交
514 515 516 517
	switch (qtcb->header.fsf_status) {
	case FSF_GOOD:
		if (zfcp_fsf_exchange_config_evaluate(req))
			return;
L
Linus Torvalds 已提交
518

S
Swen Schillig 已提交
519 520
		if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
			dev_err(&adapter->ccw_device->dev,
521 522 523
				"FCP adapter maximum QTCB size (%d bytes) "
				"is too small\n",
				bottom->max_qtcb_size);
524
			zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1", req);
S
Swen Schillig 已提交
525 526 527 528
			return;
		}
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
				&adapter->status);
L
Linus Torvalds 已提交
529
		break;
S
Swen Schillig 已提交
530 531 532 533 534 535 536
	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 已提交
537

S
Swen Schillig 已提交
538 539
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
				&adapter->status);
L
Linus Torvalds 已提交
540

541
		zfcp_fsf_link_down_info_eval(req, "fsecdh2",
S
Swen Schillig 已提交
542
			&qtcb->header.fsf_status_qual.link_down_info);
L
Linus Torvalds 已提交
543
		break;
S
Swen Schillig 已提交
544
	default:
545
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req);
S
Swen Schillig 已提交
546 547
		return;
	}
L
Linus Torvalds 已提交
548

S
Swen Schillig 已提交
549 550 551 552 553 554 555
	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 已提交
556

S
Swen Schillig 已提交
557 558
	if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
		dev_err(&adapter->ccw_device->dev,
559 560
			"The FCP adapter only supports newer "
			"control block versions\n");
561
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4", req);
S
Swen Schillig 已提交
562 563 564 565
		return;
	}
	if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
		dev_err(&adapter->ccw_device->dev,
566 567
			"The FCP adapter only supports older "
			"control block versions\n");
568
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5", req);
S
Swen Schillig 已提交
569 570
	}
}
L
Linus Torvalds 已提交
571

S
Swen Schillig 已提交
572 573 574 575 576
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 已提交
577

S
Swen Schillig 已提交
578 579
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));
580

581
	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
S
Swen Schillig 已提交
582
		fc_host_permanent_port_name(shost) = bottom->wwpn;
583 584
		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
	} else
S
Swen Schillig 已提交
585 586 587
		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
	fc_host_supported_speeds(shost) = bottom->supported_speed;
588 589 590 591
	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 已提交
592
}
L
Linus Torvalds 已提交
593

S
Swen Schillig 已提交
594 595 596 597 598 599 600 601 602 603 604 605 606
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);
607
		zfcp_fsf_link_down_info_eval(req, "fsepdh1",
S
Swen Schillig 已提交
608
			&qtcb->header.fsf_status_qual.link_down_info);
609
		break;
L
Linus Torvalds 已提交
610
	}
S
Swen Schillig 已提交
611
}
612

613
static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
S
Swen Schillig 已提交
614 615
{
	struct zfcp_fsf_req *req;
616 617 618 619 620 621 622

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

	if (unlikely(!req))
S
Swen Schillig 已提交
623
		return NULL;
624

S
Swen Schillig 已提交
625
	memset(req, 0, sizeof(*req));
626
	req->pool = pool;
S
Swen Schillig 已提交
627 628 629
	return req;
}

630
static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
S
Swen Schillig 已提交
631
{
632
	struct fsf_qtcb *qtcb;
S
Swen Schillig 已提交
633 634 635 636

	if (likely(pool))
		qtcb = mempool_alloc(pool, GFP_ATOMIC);
	else
637 638
		qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC);

S
Swen Schillig 已提交
639 640 641 642
	if (unlikely(!qtcb))
		return NULL;

	memset(qtcb, 0, sizeof(*qtcb));
643
	return qtcb;
S
Swen Schillig 已提交
644 645
}

646
static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
647 648
						u32 fsf_cmd, u32 sbtype,
						mempool_t *pool)
L
Linus Torvalds 已提交
649
{
650
	struct zfcp_adapter *adapter = qdio->adapter;
651
	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
L
Linus Torvalds 已提交
652

S
Swen Schillig 已提交
653
	if (unlikely(!req))
654
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
655

S
Swen Schillig 已提交
656 657
	if (adapter->req_no == 0)
		adapter->req_no++;
L
Linus Torvalds 已提交
658

S
Swen Schillig 已提交
659 660
	INIT_LIST_HEAD(&req->list);
	init_timer(&req->timer);
661
	init_completion(&req->completion);
L
Linus Torvalds 已提交
662

S
Swen Schillig 已提交
663 664
	req->adapter = adapter;
	req->fsf_command = fsf_cmd;
665
	req->req_id = adapter->req_no;
S
Swen Schillig 已提交
666

667 668 669 670 671 672 673 674 675 676 677
	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);
		}

678
		req->seq_no = adapter->fsf_req_seq_no;
679
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
S
Swen Schillig 已提交
680 681 682 683 684 685 686 687
		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;
	}

688 689 690
	zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,
			   req->qtcb, sizeof(struct fsf_qtcb));

S
Swen Schillig 已提交
691
	return req;
L
Linus Torvalds 已提交
692 693
}

S
Swen Schillig 已提交
694 695 696
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
697
	struct zfcp_qdio *qdio = adapter->qdio;
698
	int with_qtcb = (req->qtcb != NULL);
699
	int req_id = req->req_id;
S
Swen Schillig 已提交
700

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

703
	req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free);
S
Swen Schillig 已提交
704
	req->issued = get_clock();
705
	if (zfcp_qdio_send(qdio, &req->qdio_req)) {
S
Swen Schillig 已提交
706
		del_timer(&req->timer);
707
		/* lookup request again, list might have changed */
708
		zfcp_reqlist_find_rm(adapter->req_list, req_id);
709
		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req);
S
Swen Schillig 已提交
710 711 712 713
		return -EIO;
	}

	/* Don't increase for unsolicited status */
714
	if (with_qtcb)
S
Swen Schillig 已提交
715
		adapter->fsf_req_seq_no++;
716
	adapter->req_no++;
S
Swen Schillig 已提交
717 718 719 720 721 722 723 724 725

	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 已提交
726
 */
727
int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
L
Linus Torvalds 已提交
728
{
729
	struct zfcp_adapter *adapter = qdio->adapter;
S
Swen Schillig 已提交
730 731 732
	struct zfcp_fsf_req *req;
	struct fsf_status_read_buffer *sr_buf;
	int retval = -EIO;
L
Linus Torvalds 已提交
733

734
	spin_lock_irq(&qdio->req_q_lock);
735
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
736 737
		goto out;

738
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, 0,
739
				  adapter->pool.status_read_req);
740
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
741 742
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
743 744
	}

745
	sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
S
Swen Schillig 已提交
746 747 748 749 750 751
	if (!sr_buf) {
		retval = -ENOMEM;
		goto failed_buf;
	}
	memset(sr_buf, 0, sizeof(*sr_buf));
	req->data = sr_buf;
752 753 754

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

S
Swen Schillig 已提交
756 757 758
	retval = zfcp_fsf_req_send(req);
	if (retval)
		goto failed_req_send;
L
Linus Torvalds 已提交
759

S
Swen Schillig 已提交
760 761 762
	goto out;

failed_req_send:
763
	mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
764 765
failed_buf:
	zfcp_fsf_req_free(req);
S
Swen Schillig 已提交
766
	zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
S
Swen Schillig 已提交
767
out:
768
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
769 770 771 772 773
	return retval;
}

static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
774 775
	struct scsi_device *sdev = req->data;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
S
Swen Schillig 已提交
776 777 778 779 780 781
	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;

	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
782
	case FSF_PORT_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
783
		if (fsq->word[0] == fsq->word[1]) {
784
			zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
785
						"fsafch1", req);
S
Swen Schillig 已提交
786
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
787 788 789
		}
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
790
		if (fsq->word[0] == fsq->word[1]) {
791 792
			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2",
					     req);
S
Swen Schillig 已提交
793
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
794 795 796
		}
		break;
	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
S
Swen Schillig 已提交
797
		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
L
Linus Torvalds 已提交
798 799
		break;
	case FSF_PORT_BOXED:
800
		zfcp_erp_port_boxed(zfcp_sdev->port, "fsafch3", req);
801
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
802 803
		break;
	case FSF_LUN_BOXED:
804
		zfcp_erp_lun_boxed(sdev, "fsafch4", req);
805
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
806 807
                break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
808
		switch (fsq->word[0]) {
L
Linus Torvalds 已提交
809
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
810
			zfcp_fc_test_link(zfcp_sdev->port);
811
			/* fall through */
L
Linus Torvalds 已提交
812
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
813
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
814 815 816 817
			break;
		}
		break;
	case FSF_GOOD:
S
Swen Schillig 已提交
818
		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
L
Linus Torvalds 已提交
819 820 821 822 823
		break;
	}
}

/**
824 825
 * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
 * @scmnd: The SCSI command to abort
S
Swen Schillig 已提交
826
 * Returns: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
827 828
 */

829
struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
L
Linus Torvalds 已提交
830
{
S
Swen Schillig 已提交
831
	struct zfcp_fsf_req *req = NULL;
832 833 834 835
	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;
836

837
	spin_lock_irq(&qdio->req_q_lock);
838
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
839
		goto out;
840
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
841
				  SBAL_FLAGS0_TYPE_READ,
842
				  qdio->adapter->pool.scsi_abort);
843 844
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
845
		goto out;
846
	}
847

848
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
849 850
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		goto out_error_free;
L
Linus Torvalds 已提交
851

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

854
	req->data = zfcp_sdev;
S
Swen Schillig 已提交
855
	req->handler = zfcp_fsf_abort_fcp_command_handler;
856 857
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
858 859 860 861 862 863 864 865 866 867
	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:
868
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
869
	return req;
L
Linus Torvalds 已提交
870 871
}

S
Swen Schillig 已提交
872
static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
873
{
S
Swen Schillig 已提交
874
	struct zfcp_adapter *adapter = req->adapter;
875
	struct zfcp_fsf_ct_els *ct = req->data;
S
Swen Schillig 已提交
876
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
877

878
	ct->status = -EINVAL;
L
Linus Torvalds 已提交
879

S
Swen Schillig 已提交
880
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
881 882 883 884
		goto skip_fsfstatus;

	switch (header->fsf_status) {
        case FSF_GOOD:
S
Swen Schillig 已提交
885
		zfcp_dbf_san_ct_response(req);
886
		ct->status = 0;
L
Linus Torvalds 已提交
887 888
		break;
        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
889
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
890 891 892 893 894
		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 已提交
895
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
896 897 898 899 900 901
			break;
                }
                break;
	case FSF_ACCESS_DENIED:
		break;
        case FSF_PORT_BOXED:
902
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
903
		break;
S
Swen Schillig 已提交
904
	case FSF_PORT_HANDLE_NOT_VALID:
905
		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req);
906
		/* fall through */
S
Swen Schillig 已提交
907
	case FSF_GENERIC_COMMAND_REJECTED:
L
Linus Torvalds 已提交
908 909 910 911
	case FSF_PAYLOAD_SIZE_MISMATCH:
	case FSF_REQUEST_SIZE_TOO_LARGE:
	case FSF_RESPONSE_SIZE_TOO_LARGE:
	case FSF_SBAL_MISMATCH:
S
Swen Schillig 已提交
912
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
913 914 915 916
		break;
	}

skip_fsfstatus:
917 918
	if (ct->handler)
		ct->handler(ct->handler_data);
S
Swen Schillig 已提交
919
}
L
Linus Torvalds 已提交
920

921 922
static void zfcp_fsf_setup_ct_els_unchained(struct zfcp_qdio *qdio,
					    struct zfcp_qdio_req *q_req,
923 924 925
					    struct scatterlist *sg_req,
					    struct scatterlist *sg_resp)
{
926 927 928
	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);
929 930
}

931 932
static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
				       struct scatterlist *sg_req,
933
				       struct scatterlist *sg_resp)
S
Swen Schillig 已提交
934
{
935 936
	struct zfcp_adapter *adapter = req->adapter;
	u32 feat = adapter->adapter_features;
S
Swen Schillig 已提交
937 938
	int bytes;

939
	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
940 941
		if (!zfcp_qdio_sg_one_sbale(sg_req) ||
		    !zfcp_qdio_sg_one_sbale(sg_resp))
942 943
			return -EOPNOTSUPP;

944 945
		zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
						sg_req, sg_resp);
946 947 948 949
		return 0;
	}

	/* use single, unchained SBAL if it can hold the request */
950
	if (zfcp_qdio_sg_one_sbale(sg_req) && zfcp_qdio_sg_one_sbale(sg_resp)) {
951 952
		zfcp_fsf_setup_ct_els_unchained(adapter->qdio, &req->qdio_req,
						sg_req, sg_resp);
953 954 955
		return 0;
	}

956
	bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req, sg_req);
S
Swen Schillig 已提交
957
	if (bytes <= 0)
958
		return -EIO;
959
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
S
Swen Schillig 已提交
960
	req->qtcb->bottom.support.req_buf_length = bytes;
961
	zfcp_qdio_skip_to_last_sbale(&req->qdio_req);
S
Swen Schillig 已提交
962

963
	bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->qdio_req,
964
					sg_resp);
965
	req->qtcb->bottom.support.resp_buf_length = bytes;
S
Swen Schillig 已提交
966
	if (bytes <= 0)
967
		return -EIO;
968
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
969

970 971 972 973 974 975
	return 0;
}

static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
				 struct scatterlist *sg_req,
				 struct scatterlist *sg_resp,
976
				 unsigned int timeout)
977 978 979
{
	int ret;

980
	ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp);
981 982 983
	if (ret)
		return ret;

984
	/* common settings for ct/gs and els requests */
985 986
	if (timeout > 255)
		timeout = 255; /* max value accepted by hardware */
987
	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
988 989
	req->qtcb->bottom.support.timeout = timeout;
	zfcp_fsf_start_timer(req, (timeout + 10) * HZ);
S
Swen Schillig 已提交
990 991

	return 0;
L
Linus Torvalds 已提交
992 993 994
}

/**
S
Swen Schillig 已提交
995 996 997
 * 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 已提交
998
 */
999
int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
1000 1001
		     struct zfcp_fsf_ct_els *ct, mempool_t *pool,
		     unsigned int timeout)
L
Linus Torvalds 已提交
1002
{
1003
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
S
Swen Schillig 已提交
1004 1005
	struct zfcp_fsf_req *req;
	int ret = -EIO;
L
Linus Torvalds 已提交
1006

1007
	spin_lock_irq(&qdio->req_q_lock);
1008
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1009
		goto out;
L
Linus Torvalds 已提交
1010

1011 1012
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC,
				  SBAL_FLAGS0_TYPE_WRITE_READ, pool);
1013

1014
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1015 1016
		ret = PTR_ERR(req);
		goto out;
1017 1018
	}

1019
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1020
	ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout);
C
Christof Schmitt 已提交
1021
	if (ret)
L
Linus Torvalds 已提交
1022 1023
		goto failed_send;

S
Swen Schillig 已提交
1024
	req->handler = zfcp_fsf_send_ct_handler;
1025
	req->qtcb->header.port_handle = wka_port->handle;
S
Swen Schillig 已提交
1026 1027
	req->data = ct;

1028
	zfcp_dbf_san_ct_request(req, wka_port->d_id);
L
Linus Torvalds 已提交
1029

S
Swen Schillig 已提交
1030 1031 1032
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;
L
Linus Torvalds 已提交
1033

S
Swen Schillig 已提交
1034
	goto out;
L
Linus Torvalds 已提交
1035

S
Swen Schillig 已提交
1036 1037 1038
failed_send:
	zfcp_fsf_req_free(req);
out:
1039
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1040
	return ret;
L
Linus Torvalds 已提交
1041 1042
}

S
Swen Schillig 已提交
1043
static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1044
{
1045
	struct zfcp_fsf_ct_els *send_els = req->data;
S
Swen Schillig 已提交
1046 1047
	struct zfcp_port *port = send_els->port;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1048

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

S
Swen Schillig 已提交
1051
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
1052 1053 1054 1055
		goto skip_fsfstatus;

	switch (header->fsf_status) {
	case FSF_GOOD:
S
Swen Schillig 已提交
1056
		zfcp_dbf_san_els_response(req);
S
Swen Schillig 已提交
1057
		send_els->status = 0;
L
Linus Torvalds 已提交
1058 1059
		break;
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
1060
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
1061 1062 1063 1064 1065 1066
		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 已提交
1067
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1068 1069 1070 1071 1072 1073 1074 1075 1076
			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:
1077 1078 1079 1080
		if (port) {
			zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		}
L
Linus Torvalds 已提交
1081
		break;
S
Swen Schillig 已提交
1082 1083 1084
	case FSF_SBAL_MISMATCH:
		/* should never occure, avoided in zfcp_fsf_send_els */
		/* fall through */
L
Linus Torvalds 已提交
1085
	default:
S
Swen Schillig 已提交
1086
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1087 1088 1089
		break;
	}
skip_fsfstatus:
H
Heiko Carstens 已提交
1090
	if (send_els->handler)
L
Linus Torvalds 已提交
1091
		send_els->handler(send_els->handler_data);
S
Swen Schillig 已提交
1092
}
L
Linus Torvalds 已提交
1093

S
Swen Schillig 已提交
1094 1095 1096 1097
/**
 * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
 * @els: pointer to struct zfcp_send_els with data for the command
 */
1098
int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
1099
		      struct zfcp_fsf_ct_els *els, unsigned int timeout)
S
Swen Schillig 已提交
1100 1101
{
	struct zfcp_fsf_req *req;
1102
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1103 1104
	int ret = -EIO;

1105
	spin_lock_irq(&qdio->req_q_lock);
1106
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1107
		goto out;
1108

1109 1110
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS,
				  SBAL_FLAGS0_TYPE_WRITE_READ, NULL);
1111

1112
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1113 1114 1115 1116
		ret = PTR_ERR(req);
		goto out;
	}

1117
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1118 1119 1120 1121

	zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);

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

S
Swen Schillig 已提交
1123 1124 1125
	if (ret)
		goto failed_send;

1126
	hton24(req->qtcb->bottom.support.d_id, d_id);
S
Swen Schillig 已提交
1127 1128 1129
	req->handler = zfcp_fsf_send_els_handler;
	req->data = els;

S
Swen Schillig 已提交
1130
	zfcp_dbf_san_els_request(req);
S
Swen Schillig 已提交
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140

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

	goto out;

failed_send:
	zfcp_fsf_req_free(req);
out:
1141
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1142
	return ret;
L
Linus Torvalds 已提交
1143 1144
}

S
Swen Schillig 已提交
1145
int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1146
{
S
Swen Schillig 已提交
1147
	struct zfcp_fsf_req *req;
1148
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1149 1150
	int retval = -EIO;

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

1155
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
1156
				  SBAL_FLAGS0_TYPE_READ,
1157
				  qdio->adapter->pool.erp_req);
1158

1159
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1160 1161
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
1162 1163
	}

1164
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1165
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1166

S
Swen Schillig 已提交
1167
	req->qtcb->bottom.config.feature_selection =
1168 1169
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
1170
			FSF_FEATURE_NOTIFICATION_LOST |
1171
			FSF_FEATURE_UPDATE_ALERT;
S
Swen Schillig 已提交
1172 1173
	req->erp_action = erp_action;
	req->handler = zfcp_fsf_exchange_config_data_handler;
1174
	erp_action->fsf_req_id = req->req_id;
L
Linus Torvalds 已提交
1175

1176
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1177
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1178
	if (retval) {
S
Swen Schillig 已提交
1179
		zfcp_fsf_req_free(req);
1180
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1181
	}
S
Swen Schillig 已提交
1182
out:
1183
	spin_unlock_irq(&qdio->req_q_lock);
1184 1185
	return retval;
}
L
Linus Torvalds 已提交
1186

1187
int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
S
Swen Schillig 已提交
1188
				       struct fsf_qtcb_bottom_config *data)
1189
{
S
Swen Schillig 已提交
1190 1191 1192
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;

1193
	spin_lock_irq(&qdio->req_q_lock);
1194
	if (zfcp_qdio_sbal_get(qdio))
1195
		goto out_unlock;
S
Swen Schillig 已提交
1196

1197 1198
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
				  SBAL_FLAGS0_TYPE_READ, NULL);
1199

1200
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1201
		retval = PTR_ERR(req);
1202
		goto out_unlock;
1203 1204
	}

1205
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
S
Swen Schillig 已提交
1206
	req->handler = zfcp_fsf_exchange_config_data_handler;
1207

S
Swen Schillig 已提交
1208
	req->qtcb->bottom.config.feature_selection =
1209 1210 1211 1212 1213 1214
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
			FSF_FEATURE_NOTIFICATION_LOST |
			FSF_FEATURE_UPDATE_ALERT;

	if (data)
S
Swen Schillig 已提交
1215
		req->data = data;
1216

S
Swen Schillig 已提交
1217 1218
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
1219
	spin_unlock_irq(&qdio->req_q_lock);
C
Christof Schmitt 已提交
1220
	if (!retval)
1221
		wait_for_completion(&req->completion);
1222

S
Swen Schillig 已提交
1223
	zfcp_fsf_req_free(req);
1224
	return retval;
1225

1226
out_unlock:
1227
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1228 1229 1230 1231 1232
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data - request information about local port
1233
 * @erp_action: ERP action for the adapter for which port data is requested
S
Swen Schillig 已提交
1234
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1235
 */
S
Swen Schillig 已提交
1236
int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1237
{
1238
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1239 1240
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1241

1242
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1243
		return -EOPNOTSUPP;
L
Linus Torvalds 已提交
1244

1245
	spin_lock_irq(&qdio->req_q_lock);
1246
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1247
		goto out;
1248

1249
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
1250
				  SBAL_FLAGS0_TYPE_READ,
1251
				  qdio->adapter->pool.erp_req);
1252

1253
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1254 1255
		retval = PTR_ERR(req);
		goto out;
1256 1257
	}

1258
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1259
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1260

S
Swen Schillig 已提交
1261 1262
	req->handler = zfcp_fsf_exchange_port_data_handler;
	req->erp_action = erp_action;
1263
	erp_action->fsf_req_id = req->req_id;
1264

1265
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1266
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1267
	if (retval) {
S
Swen Schillig 已提交
1268
		zfcp_fsf_req_free(req);
1269
		erp_action->fsf_req_id = 0;
1270
	}
S
Swen Schillig 已提交
1271
out:
1272
	spin_unlock_irq(&qdio->req_q_lock);
1273 1274 1275 1276 1277
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data_sync - request information about local port
1278
 * @qdio: pointer to struct zfcp_qdio
S
Swen Schillig 已提交
1279 1280
 * @data: pointer to struct fsf_qtcb_bottom_port
 * Returns: 0 on success, error otherwise
1281
 */
1282
int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
S
Swen Schillig 已提交
1283
				     struct fsf_qtcb_bottom_port *data)
1284
{
S
Swen Schillig 已提交
1285 1286
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;
1287

1288
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1289 1290
		return -EOPNOTSUPP;

1291
	spin_lock_irq(&qdio->req_q_lock);
1292
	if (zfcp_qdio_sbal_get(qdio))
1293
		goto out_unlock;
S
Swen Schillig 已提交
1294

1295 1296
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
				  SBAL_FLAGS0_TYPE_READ, NULL);
1297

1298
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1299
		retval = PTR_ERR(req);
1300
		goto out_unlock;
L
Linus Torvalds 已提交
1301 1302
	}

1303
	if (data)
S
Swen Schillig 已提交
1304
		req->data = data;
1305

1306
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1307

S
Swen Schillig 已提交
1308 1309 1310
	req->handler = zfcp_fsf_exchange_port_data_handler;
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
1311
	spin_unlock_irq(&qdio->req_q_lock);
1312

C
Christof Schmitt 已提交
1313
	if (!retval)
1314 1315
		wait_for_completion(&req->completion);

S
Swen Schillig 已提交
1316
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1317 1318

	return retval;
1319 1320

out_unlock:
1321
	spin_unlock_irq(&qdio->req_q_lock);
1322
	return retval;
L
Linus Torvalds 已提交
1323 1324
}

S
Swen Schillig 已提交
1325
static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1326
{
S
Swen Schillig 已提交
1327 1328
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
1329
	struct fc_els_flogi *plogi;
L
Linus Torvalds 已提交
1330

S
Swen Schillig 已提交
1331
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1332
		goto out;
L
Linus Torvalds 已提交
1333 1334 1335 1336 1337

	switch (header->fsf_status) {
	case FSF_PORT_ALREADY_OPEN:
		break;
	case FSF_ACCESS_DENIED:
1338 1339
		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1340 1341
		break;
	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
S
Swen Schillig 已提交
1342
		dev_warn(&req->adapter->ccw_device->dev,
1343
			 "Not enough FCP adapter resources to open "
1344 1345
			 "remote port 0x%016Lx\n",
			 (unsigned long long)port->wwpn);
1346
		zfcp_erp_port_failed(port, "fsoph_1", req);
S
Swen Schillig 已提交
1347
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1348 1349 1350 1351 1352 1353
		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 已提交
1354
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1355 1356 1357 1358 1359 1360 1361
			break;
		}
		break;
	case FSF_GOOD:
		port->handle = header->port_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1362 1363 1364
		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
		                  &port->status);
L
Linus Torvalds 已提交
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
		/* 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.
		 */
1380
		plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els;
1381
		if (req->qtcb->bottom.support.els1_length >=
1382
		    FSF_PLOGI_MIN_LEN)
S
Swen Schillig 已提交
1383
				zfcp_fc_plogi_evaluate(port, plogi);
L
Linus Torvalds 已提交
1384 1385
		break;
	case FSF_UNKNOWN_OP_SUBTYPE:
S
Swen Schillig 已提交
1386
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1387 1388
		break;
	}
1389 1390

out:
1391
	put_device(&port->dev);
L
Linus Torvalds 已提交
1392 1393
}

S
Swen Schillig 已提交
1394 1395 1396 1397
/**
 * 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 已提交
1398
 */
S
Swen Schillig 已提交
1399
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1400
{
1401
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1402
	struct zfcp_port *port = erp_action->port;
1403
	struct zfcp_fsf_req *req;
S
Swen Schillig 已提交
1404 1405
	int retval = -EIO;

1406
	spin_lock_irq(&qdio->req_q_lock);
1407
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1408 1409
		goto out;

1410
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1411
				  SBAL_FLAGS0_TYPE_READ,
1412
				  qdio->adapter->pool.erp_req);
1413

1414
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1415
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1416
		goto out;
S
Swen Schillig 已提交
1417
	}
L
Linus Torvalds 已提交
1418

1419
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1420
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1421

S
Swen Schillig 已提交
1422
	req->handler = zfcp_fsf_open_port_handler;
1423
	hton24(req->qtcb->bottom.support.d_id, port->d_id);
1424
	req->data = port;
S
Swen Schillig 已提交
1425
	req->erp_action = erp_action;
1426
	erp_action->fsf_req_id = req->req_id;
1427
	get_device(&port->dev);
S
Swen Schillig 已提交
1428

1429
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1430
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1431
	if (retval) {
S
Swen Schillig 已提交
1432
		zfcp_fsf_req_free(req);
1433
		erp_action->fsf_req_id = 0;
1434
		put_device(&port->dev);
L
Linus Torvalds 已提交
1435
	}
S
Swen Schillig 已提交
1436
out:
1437
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1438 1439 1440
	return retval;
}

S
Swen Schillig 已提交
1441
static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1442
{
S
Swen Schillig 已提交
1443
	struct zfcp_port *port = req->data;
L
Linus Torvalds 已提交
1444

S
Swen Schillig 已提交
1445
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1446
		return;
L
Linus Torvalds 已提交
1447

S
Swen Schillig 已提交
1448
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1449
	case FSF_PORT_HANDLE_NOT_VALID:
1450
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req);
S
Swen Schillig 已提交
1451
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1452 1453 1454 1455
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		break;
	case FSF_GOOD:
1456
		zfcp_erp_modify_port_status(port, "fscph_2", req,
L
Linus Torvalds 已提交
1457 1458 1459 1460 1461 1462
					    ZFCP_STATUS_COMMON_OPEN,
					    ZFCP_CLEAR);
		break;
	}
}

S
Swen Schillig 已提交
1463 1464 1465 1466
/**
 * 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 已提交
1467
 */
S
Swen Schillig 已提交
1468
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1469
{
1470
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1471 1472 1473
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1474
	spin_lock_irq(&qdio->req_q_lock);
1475
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
1476 1477
		goto out;

1478
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1479
				  SBAL_FLAGS0_TYPE_READ,
1480
				  qdio->adapter->pool.erp_req);
1481

1482
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1483
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1484
		goto out;
S
Swen Schillig 已提交
1485
	}
L
Linus Torvalds 已提交
1486

1487
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1488
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1489

S
Swen Schillig 已提交
1490 1491 1492 1493
	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;
1494
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1495

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

1507 1508
static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
{
1509
	struct zfcp_fc_wka_port *wka_port = req->data;
1510 1511 1512
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
1513
		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1514 1515 1516 1517 1518 1519 1520
		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);
1521
		/* fall through */
1522 1523
	case FSF_ADAPTER_STATUS_AVAILABLE:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1524
		/* fall through */
1525
	case FSF_ACCESS_DENIED:
1526
		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1527 1528 1529
		break;
	case FSF_GOOD:
		wka_port->handle = header->port_handle;
1530 1531
		/* fall through */
	case FSF_PORT_ALREADY_OPEN:
1532
		wka_port->status = ZFCP_FC_WKA_PORT_ONLINE;
1533 1534 1535 1536 1537 1538 1539
	}
out:
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_open_wka_port - create and send open wka-port request
1540
 * @wka_port: pointer to struct zfcp_fc_wka_port
1541 1542
 * Returns: 0 on success, error otherwise
 */
1543
int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
1544
{
1545
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1546 1547 1548
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1549
	spin_lock_irq(&qdio->req_q_lock);
1550
	if (zfcp_qdio_sbal_get(qdio))
1551 1552
		goto out;

1553
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
1554
				  SBAL_FLAGS0_TYPE_READ,
1555
				  qdio->adapter->pool.erp_req);
1556

1557 1558 1559 1560 1561
	if (unlikely(IS_ERR(req))) {
		retval = PTR_ERR(req);
		goto out;
	}

1562
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1563
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1564 1565

	req->handler = zfcp_fsf_open_wka_port_handler;
1566
	hton24(req->qtcb->bottom.support.d_id, wka_port->d_id);
1567 1568 1569 1570 1571 1572 1573
	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:
1574
	spin_unlock_irq(&qdio->req_q_lock);
1575 1576 1577 1578 1579
	return retval;
}

static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
{
1580
	struct zfcp_fc_wka_port *wka_port = req->data;
1581 1582 1583

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

1587
	wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
1588 1589 1590 1591 1592
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_close_wka_port - create and send close wka port request
1593
 * @wka_port: WKA port to open
1594 1595
 * Returns: 0 on success, error otherwise
 */
1596
int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
1597
{
1598
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1599 1600 1601
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1602
	spin_lock_irq(&qdio->req_q_lock);
1603
	if (zfcp_qdio_sbal_get(qdio))
1604 1605
		goto out;

1606
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
1607
				  SBAL_FLAGS0_TYPE_READ,
1608
				  qdio->adapter->pool.erp_req);
1609

1610 1611 1612 1613 1614
	if (unlikely(IS_ERR(req))) {
		retval = PTR_ERR(req);
		goto out;
	}

1615
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1616
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626

	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:
1627
	spin_unlock_irq(&qdio->req_q_lock);
1628 1629 1630
	return retval;
}

S
Swen Schillig 已提交
1631
static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1632
{
S
Swen Schillig 已提交
1633 1634
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
1635
	struct scsi_device *sdev;
L
Linus Torvalds 已提交
1636

S
Swen Schillig 已提交
1637
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1638
		return;
L
Linus Torvalds 已提交
1639 1640 1641

	switch (header->fsf_status) {
	case FSF_PORT_HANDLE_NOT_VALID:
1642
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req);
S
Swen Schillig 已提交
1643
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1644 1645
		break;
	case FSF_ACCESS_DENIED:
1646
		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
L
Linus Torvalds 已提交
1647 1648
		break;
	case FSF_PORT_BOXED:
1649 1650 1651
		/* 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);
1652 1653 1654 1655
		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);
1656
		zfcp_erp_port_boxed(port, "fscpph2", req);
1657
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1658 1659 1660 1661
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
S
Swen Schillig 已提交
1662
			/* fall through */
L
Linus Torvalds 已提交
1663
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1664
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1665 1666 1667 1668 1669 1670 1671 1672
			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);
1673 1674 1675 1676
		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 已提交
1677 1678 1679 1680
		break;
	}
}

S
Swen Schillig 已提交
1681 1682 1683 1684
/**
 * zfcp_fsf_close_physical_port - close physical port
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success
L
Linus Torvalds 已提交
1685
 */
S
Swen Schillig 已提交
1686
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1687
{
1688
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1689 1690 1691
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1692
	spin_lock_irq(&qdio->req_q_lock);
1693
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1694 1695
		goto out;

1696
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
1697
				  SBAL_FLAGS0_TYPE_READ,
1698
				  qdio->adapter->pool.erp_req);
1699

1700
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1701 1702 1703
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1704

1705
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1706
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1707

S
Swen Schillig 已提交
1708 1709 1710 1711
	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;
1712
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1713

1714
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1715
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1716
	if (retval) {
S
Swen Schillig 已提交
1717
		zfcp_fsf_req_free(req);
1718
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1719
	}
S
Swen Schillig 已提交
1720
out:
1721
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1722 1723 1724
	return retval;
}

1725
static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1726
{
S
Swen Schillig 已提交
1727
	struct zfcp_adapter *adapter = req->adapter;
1728 1729
	struct scsi_device *sdev = req->data;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
S
Swen Schillig 已提交
1730 1731
	struct fsf_qtcb_header *header = &req->qtcb->header;
	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
L
Linus Torvalds 已提交
1732

S
Swen Schillig 已提交
1733
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1734
		return;
L
Linus Torvalds 已提交
1735 1736

	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1737
			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
1738 1739 1740
			  ZFCP_STATUS_LUN_SHARED |
			  ZFCP_STATUS_LUN_READONLY,
			  &zfcp_sdev->status);
L
Linus Torvalds 已提交
1741 1742 1743 1744

	switch (header->fsf_status) {

	case FSF_PORT_HANDLE_NOT_VALID:
1745
		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1", req);
S
Swen Schillig 已提交
1746
		/* fall through */
L
Linus Torvalds 已提交
1747 1748 1749
	case FSF_LUN_ALREADY_OPEN:
		break;
	case FSF_ACCESS_DENIED:
1750 1751
		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1752 1753
		break;
	case FSF_PORT_BOXED:
1754
		zfcp_erp_port_boxed(zfcp_sdev->port, "fsouh_2", req);
1755
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1756 1757
		break;
	case FSF_LUN_SHARING_VIOLATION:
1758
		zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual);
S
Swen Schillig 已提交
1759
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1760 1761
		break;
	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
S
Swen Schillig 已提交
1762
		dev_warn(&adapter->ccw_device->dev,
1763 1764
			 "No handle is available for LUN "
			 "0x%016Lx on port 0x%016Lx\n",
1765 1766 1767
			 (unsigned long long)zfcp_scsi_dev_lun(sdev),
			 (unsigned long long)zfcp_sdev->port->wwpn);
		zfcp_erp_lun_failed(sdev, "fsolh_4", req);
S
Swen Schillig 已提交
1768 1769 1770
		/* fall through */
	case FSF_INVALID_COMMAND_OPTION:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1771 1772 1773 1774
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1775
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
1776
			/* fall through */
L
Linus Torvalds 已提交
1777
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1778
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1779 1780 1781 1782 1783
			break;
		}
		break;

	case FSF_GOOD:
1784 1785
		zfcp_sdev->lun_handle = header->lun_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
1786
		zfcp_cfdc_open_lun_eval(sdev, bottom);
L
Linus Torvalds 已提交
1787 1788 1789 1790
		break;
	}
}

S
Swen Schillig 已提交
1791
/**
1792
 * zfcp_fsf_open_lun - open LUN
S
Swen Schillig 已提交
1793 1794
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1795
 */
1796
int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1797
{
S
Swen Schillig 已提交
1798
	struct zfcp_adapter *adapter = erp_action->adapter;
1799
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1800 1801 1802
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1803
	spin_lock_irq(&qdio->req_q_lock);
1804
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1805 1806
		goto out;

1807
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1808
				  SBAL_FLAGS0_TYPE_READ,
1809
				  adapter->pool.erp_req);
1810

1811
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1812 1813 1814 1815
		retval = PTR_ERR(req);
		goto out;
	}

1816
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1817
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1818

S
Swen Schillig 已提交
1819
	req->qtcb->header.port_handle = erp_action->port->handle;
1820 1821 1822
	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 已提交
1823
	req->erp_action = erp_action;
1824
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1825 1826 1827 1828

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

1829
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1830
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1831
	if (retval) {
S
Swen Schillig 已提交
1832
		zfcp_fsf_req_free(req);
1833
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1834
	}
S
Swen Schillig 已提交
1835
out:
1836
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1837 1838 1839
	return retval;
}

1840
static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1841
{
1842 1843
	struct scsi_device *sdev = req->data;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
L
Linus Torvalds 已提交
1844

S
Swen Schillig 已提交
1845
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1846
		return;
L
Linus Torvalds 已提交
1847

S
Swen Schillig 已提交
1848
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1849
	case FSF_PORT_HANDLE_NOT_VALID:
1850 1851
		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1",
					req);
S
Swen Schillig 已提交
1852
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1853 1854
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
1855
		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2", req);
S
Swen Schillig 已提交
1856
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1857 1858
		break;
	case FSF_PORT_BOXED:
1859
		zfcp_erp_port_boxed(zfcp_sdev->port, "fscuh_3", req);
1860
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1861 1862
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
1863
		switch (req->qtcb->header.fsf_status_qual.word[0]) {
L
Linus Torvalds 已提交
1864
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1865
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
1866
			/* fall through */
L
Linus Torvalds 已提交
1867
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1868
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1869 1870 1871 1872
			break;
		}
		break;
	case FSF_GOOD:
1873
		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
L
Linus Torvalds 已提交
1874 1875 1876 1877 1878
		break;
	}
}

/**
1879 1880
 * zfcp_fsf_close_LUN - close LUN
 * @erp_action: pointer to erp_action triggering the "close LUN"
S
Swen Schillig 已提交
1881
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1882
 */
1883
int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1884
{
1885
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1886
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
S
Swen Schillig 已提交
1887 1888
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1889

1890
	spin_lock_irq(&qdio->req_q_lock);
1891
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1892
		goto out;
1893

1894
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
1895
				  SBAL_FLAGS0_TYPE_READ,
1896
				  qdio->adapter->pool.erp_req);
1897

1898
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1899 1900 1901
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1902

1903
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1904
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1905

S
Swen Schillig 已提交
1906
	req->qtcb->header.port_handle = erp_action->port->handle;
1907 1908 1909
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->handler = zfcp_fsf_close_lun_handler;
	req->data = erp_action->sdev;
S
Swen Schillig 已提交
1910
	req->erp_action = erp_action;
1911
	erp_action->fsf_req_id = req->req_id;
1912

1913
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1914 1915 1916
	retval = zfcp_fsf_req_send(req);
	if (retval) {
		zfcp_fsf_req_free(req);
1917
		erp_action->fsf_req_id = 0;
S
Swen Schillig 已提交
1918 1919
	}
out:
1920
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1921
	return retval;
L
Linus Torvalds 已提交
1922 1923
}

1924 1925 1926
static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
{
	lat_rec->sum += lat;
S
Swen Schillig 已提交
1927 1928
	lat_rec->min = min(lat_rec->min, lat);
	lat_rec->max = max(lat_rec->max, lat);
1929 1930
}

1931
static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
1932
{
1933 1934
	struct fsf_qual_latency_info *lat_in;
	struct latency_cont *lat = NULL;
1935
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
1936 1937
	struct zfcp_blk_drv_data blktrc;
	int ticks = req->adapter->timer_ticks;
1938

1939
	lat_in = &req->qtcb->prefix.prot_status_qual.latency_info;
1940

1941 1942 1943 1944
	blktrc.flags = 0;
	blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		blktrc.flags |= ZFCP_BLK_REQ_ERROR;
1945
	blktrc.inb_usage = 0;
1946
	blktrc.outb_usage = req->qdio_req.qdio_outb_usage;
1947

1948 1949
	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
	    !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
1950 1951 1952 1953 1954
		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) {
1955 1956
		case FSF_DATADIR_DIF_READ_STRIP:
		case FSF_DATADIR_DIF_READ_CONVERT:
1957
		case FSF_DATADIR_READ:
1958
			lat = &zfcp_sdev->latencies.read;
1959
			break;
1960 1961
		case FSF_DATADIR_DIF_WRITE_INSERT:
		case FSF_DATADIR_DIF_WRITE_CONVERT:
1962
		case FSF_DATADIR_WRITE:
1963
			lat = &zfcp_sdev->latencies.write;
1964 1965
			break;
		case FSF_DATADIR_CMND:
1966
			lat = &zfcp_sdev->latencies.cmd;
1967 1968
			break;
		}
L
Linus Torvalds 已提交
1969

1970
		if (lat) {
1971
			spin_lock(&zfcp_sdev->latencies.lock);
1972 1973 1974
			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
			lat->counter++;
1975
			spin_unlock(&zfcp_sdev->latencies.lock);
1976
		}
S
Stefan Raspl 已提交
1977 1978
	}

1979 1980
	blk_add_driver_data(scsi->request->q, scsi->request, &blktrc,
			    sizeof(blktrc));
S
Stefan Raspl 已提交
1981 1982
}

1983
static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
S
Swen Schillig 已提交
1984
{
1985 1986 1987
	struct scsi_cmnd *scmnd = req->data;
	struct scsi_device *sdev = scmnd->device;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
S
Swen Schillig 已提交
1988 1989 1990
	struct fsf_qtcb_header *header = &req->qtcb->header;

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

S
Swen Schillig 已提交
1993 1994 1995
	switch (header->fsf_status) {
	case FSF_HANDLE_MISMATCH:
	case FSF_PORT_HANDLE_NOT_VALID:
1996 1997
		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1",
					req);
S
Swen Schillig 已提交
1998 1999 2000 2001
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_FCPLUN_NOT_VALID:
	case FSF_LUN_HANDLE_NOT_VALID:
2002
		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2", req);
S
Swen Schillig 已提交
2003
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2004
		break;
S
Swen Schillig 已提交
2005 2006
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
2007
		break;
S
Swen Schillig 已提交
2008
	case FSF_ACCESS_DENIED:
2009 2010
		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2011 2012 2013
		break;
	case FSF_DIRECTION_INDICATOR_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2014
			"Incorrect direction %d, LUN 0x%016Lx on port "
2015
			"0x%016Lx closed\n",
S
Swen Schillig 已提交
2016
			req->qtcb->bottom.io.data_direction,
2017 2018 2019 2020
			(unsigned long long)zfcp_scsi_dev_lun(sdev),
			(unsigned long long)zfcp_sdev->port->wwpn);
		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
					  "fssfch3", req);
S
Swen Schillig 已提交
2021 2022 2023 2024
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_CMND_LENGTH_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2025
			"Incorrect CDB length %d, LUN 0x%016Lx on "
2026
			"port 0x%016Lx closed\n",
S
Swen Schillig 已提交
2027
			req->qtcb->bottom.io.fcp_cmnd_length,
2028 2029 2030 2031
			(unsigned long long)zfcp_scsi_dev_lun(sdev),
			(unsigned long long)zfcp_sdev->port->wwpn);
		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
					  "fssfch4", req);
S
Swen Schillig 已提交
2032 2033 2034
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_PORT_BOXED:
2035
		zfcp_erp_port_boxed(zfcp_sdev->port, "fssfch5", req);
2036
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2037 2038
		break;
	case FSF_LUN_BOXED:
2039
		zfcp_erp_lun_boxed(sdev, "fssfch6", req);
2040
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2041 2042 2043 2044
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		if (header->fsf_status_qual.word[0] ==
		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
2045
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
2046
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2047 2048
		break;
	}
2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
}

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;

	zfcp_fsf_fcp_handler_common(req);

	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 已提交
2065
	}
2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102

	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);
	zfcp_dbf_scsi_result(req->adapter->dbf, scpnt, req);

	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 已提交
2103 2104
}

2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142
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 已提交
2143
/**
2144
 * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
S
Swen Schillig 已提交
2145
 * @scsi_cmnd: scsi command to be sent
L
Linus Torvalds 已提交
2146
 */
2147
int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
L
Linus Torvalds 已提交
2148
{
S
Swen Schillig 已提交
2149
	struct zfcp_fsf_req *req;
2150
	struct fcp_cmnd *fcp_cmnd;
2151
	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
2152
	int real_bytes, retval = -EIO, dix_bytes = 0;
2153 2154 2155
	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;
2156
	struct zfcp_qdio *qdio = adapter->qdio;
2157
	struct fsf_qtcb_bottom_io *io;
L
Linus Torvalds 已提交
2158

2159
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2160 2161
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return -EBUSY;
L
Linus Torvalds 已提交
2162

2163
	spin_lock(&qdio->req_q_lock);
2164
	if (atomic_read(&qdio->req_q_free) <= 0) {
2165
		atomic_inc(&qdio->req_q_full);
S
Swen Schillig 已提交
2166
		goto out;
2167
	}
2168

2169 2170 2171
	if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE)
		sbtype = SBAL_FLAGS0_TYPE_WRITE;

2172
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2173
				  sbtype, adapter->pool.scsi_req);
2174

2175
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2176 2177 2178 2179
		retval = PTR_ERR(req);
		goto out;
	}

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

	io = &req->qtcb->bottom.io;
2183
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
S
Swen Schillig 已提交
2184
	req->data = scsi_cmnd;
2185
	req->handler = zfcp_fsf_fcp_cmnd_handler;
2186 2187
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
2188 2189
	io->service_class = FSF_CLASS_3;
	io->fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2190

2191 2192 2193
	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 已提交
2194 2195
	}

2196 2197
	zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);

2198 2199
	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
L
Linus Torvalds 已提交
2200

2201 2202 2203 2204 2205 2206 2207 2208
	if (scsi_prot_sg_count(scsi_cmnd)) {
		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
				       scsi_prot_sg_count(scsi_cmnd));
		dix_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
						scsi_prot_sglist(scsi_cmnd));
		io->prot_data_length = dix_bytes;
	}

2209
	real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
2210
					     scsi_sglist(scsi_cmnd));
2211 2212

	if (unlikely(real_bytes < 0) || unlikely(dix_bytes < 0))
S
Swen Schillig 已提交
2213
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2214

2215 2216
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);

S
Swen Schillig 已提交
2217 2218 2219
	retval = zfcp_fsf_req_send(req);
	if (unlikely(retval))
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2220

S
Swen Schillig 已提交
2221
	goto out;
L
Linus Torvalds 已提交
2222

S
Swen Schillig 已提交
2223 2224 2225 2226
failed_scsi_cmnd:
	zfcp_fsf_req_free(req);
	scsi_cmnd->host_scribble = NULL;
out:
2227
	spin_unlock(&qdio->req_q_lock);
S
Swen Schillig 已提交
2228
	return retval;
L
Linus Torvalds 已提交
2229 2230
}

2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245
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 已提交
2246
/**
2247 2248
 * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
 * @scmnd: SCSI command to send the task management command for
S
Swen Schillig 已提交
2249 2250
 * @tm_flags: unsigned byte for task management flags
 * Returns: on success pointer to struct fsf_req, NULL otherwise
L
Linus Torvalds 已提交
2251
 */
2252 2253
struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
					    u8 tm_flags)
L
Linus Torvalds 已提交
2254
{
S
Swen Schillig 已提交
2255
	struct zfcp_fsf_req *req = NULL;
2256
	struct fcp_cmnd *fcp_cmnd;
2257 2258
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
L
Linus Torvalds 已提交
2259

2260
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2261 2262
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return NULL;
L
Linus Torvalds 已提交
2263

2264
	spin_lock_irq(&qdio->req_q_lock);
2265
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
2266
		goto out;
2267

2268
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2269
				  SBAL_FLAGS0_TYPE_WRITE,
2270
				  qdio->adapter->pool.scsi_req);
2271

2272 2273
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
2274
		goto out;
2275
	}
L
Linus Torvalds 已提交
2276

S
Swen Schillig 已提交
2277
	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
2278
	req->data = scmnd;
2279
	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
2280 2281
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
2282 2283
	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
2284
	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2285

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

2288
	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
2289
	zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags);
L
Linus Torvalds 已提交
2290

S
Swen Schillig 已提交
2291 2292 2293
	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;
L
Linus Torvalds 已提交
2294

S
Swen Schillig 已提交
2295 2296 2297
	zfcp_fsf_req_free(req);
	req = NULL;
out:
2298
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
2299 2300
	return req;
}
L
Linus Torvalds 已提交
2301

S
Swen Schillig 已提交
2302 2303
static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
{
L
Linus Torvalds 已提交
2304 2305
}

S
Swen Schillig 已提交
2306 2307 2308 2309 2310
/**
 * 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 已提交
2311
 */
S
Swen Schillig 已提交
2312 2313
struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
					   struct zfcp_fsf_cfdc *fsf_cfdc)
L
Linus Torvalds 已提交
2314
{
2315
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332
	struct zfcp_fsf_req *req = NULL;
	struct fsf_qtcb_bottom_support *bottom;
	int direction, retval = -EIO, bytes;

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

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

2334
	spin_lock_irq(&qdio->req_q_lock);
2335
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
2336
		goto out;
L
Linus Torvalds 已提交
2337

2338
	req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, direction, NULL);
2339
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2340 2341 2342
		retval = -EPERM;
		goto out;
	}
L
Linus Torvalds 已提交
2343

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

S
Swen Schillig 已提交
2346 2347 2348
	bottom = &req->qtcb->bottom.support;
	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
	bottom->option = fsf_cfdc->option;
2349

2350 2351
	bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);

S
Swen Schillig 已提交
2352 2353 2354 2355
	if (bytes != ZFCP_CFDC_MAX_SIZE) {
		zfcp_fsf_req_free(req);
		goto out;
	}
2356
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
L
Linus Torvalds 已提交
2357

S
Swen Schillig 已提交
2358 2359 2360
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
out:
2361
	spin_unlock_irq(&qdio->req_q_lock);
2362

S
Swen Schillig 已提交
2363
	if (!retval) {
2364
		wait_for_completion(&req->completion);
S
Swen Schillig 已提交
2365
		return req;
L
Linus Torvalds 已提交
2366
	}
S
Swen Schillig 已提交
2367
	return ERR_PTR(retval);
L
Linus Torvalds 已提交
2368
}
2369 2370 2371 2372 2373 2374

/**
 * 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
 */
2375
void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2376
{
2377
	struct zfcp_adapter *adapter = qdio->adapter;
2378
	struct qdio_buffer *sbal = qdio->res_q[sbal_idx];
2379 2380
	struct qdio_buffer_element *sbale;
	struct zfcp_fsf_req *fsf_req;
2381
	unsigned long req_id;
2382 2383 2384 2385 2386 2387
	int idx;

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

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

2390
		if (!fsf_req) {
2391 2392 2393 2394
			/*
			 * Unknown request means that we have potentially memory
			 * corruption and must stop the machine immediately.
			 */
2395
			zfcp_qdio_siosl(adapter);
2396 2397
			panic("error: unknown req_id (%lx) on adapter %s.\n",
			      req_id, dev_name(&adapter->ccw_device->dev));
2398
		}
2399

2400
		fsf_req->qdio_req.sbal_response = sbal_idx;
2401 2402 2403 2404 2405 2406
		zfcp_fsf_req_complete(fsf_req);

		if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
			break;
	}
}