zfcp_fsf.c 66.5 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,
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
out:
187
	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
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, 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, 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, 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 246
		zfcp_erp_set_adapter_status(adapter,
					    ZFCP_STATUS_COMMON_RUNNING);
S
Swen Schillig 已提交
247 248 249
		zfcp_erp_adapter_reopen(adapter,
					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
					ZFCP_STATUS_COMMON_ERP_FAILED,
250
					"fssrh_2", req);
251 252
		zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	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 已提交
438 439
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
{
440
	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
S
Swen Schillig 已提交
441 442
	struct zfcp_adapter *adapter = req->adapter;
	struct Scsi_Host *shost = adapter->scsi_host;
443
	struct fc_els_flogi *nsp, *plogi;
L
Linus Torvalds 已提交
444

445 446 447 448 449
	/* 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 已提交
450

S
Swen Schillig 已提交
451 452 453
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));

454 455
	fc_host_port_name(shost) = nsp->fl_wwpn;
	fc_host_node_name(shost) = nsp->fl_wwnn;
456
	fc_host_port_id(shost) = ntoh24(bottom->s_id);
S
Swen Schillig 已提交
457 458 459 460
	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;
461
	adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK;
462 463
	adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
					 (u16)FSF_STATUS_READS_RECOM);
S
Swen Schillig 已提交
464 465 466 467 468 469

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

489 490
	zfcp_scsi_set_prot(adapter);

L
Linus Torvalds 已提交
491 492 493
	return 0;
}

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

S
Swen Schillig 已提交
501 502
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		return;
L
Linus Torvalds 已提交
503

S
Swen Schillig 已提交
504 505 506 507 508 509
	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;
510

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

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

535
		zfcp_fsf_link_down_info_eval(req,
S
Swen Schillig 已提交
536
			&qtcb->header.fsf_status_qual.link_down_info);
L
Linus Torvalds 已提交
537
		break;
S
Swen Schillig 已提交
538
	default:
539
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req);
S
Swen Schillig 已提交
540 541
		return;
	}
L
Linus Torvalds 已提交
542

S
Swen Schillig 已提交
543 544 545 546 547 548 549
	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 已提交
550

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

S
Swen Schillig 已提交
566 567 568 569 570
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 已提交
571

S
Swen Schillig 已提交
572 573
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));
574

575
	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
S
Swen Schillig 已提交
576
		fc_host_permanent_port_name(shost) = bottom->wwpn;
577 578
		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
	} else
S
Swen Schillig 已提交
579 580 581
		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;
582 583 584 585
	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 已提交
586
}
L
Linus Torvalds 已提交
587

S
Swen Schillig 已提交
588 589 590 591 592 593 594 595 596 597 598 599 600
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);
601
		zfcp_fsf_link_down_info_eval(req,
S
Swen Schillig 已提交
602
			&qtcb->header.fsf_status_qual.link_down_info);
603
		break;
L
Linus Torvalds 已提交
604
	}
S
Swen Schillig 已提交
605
}
606

607
static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
S
Swen Schillig 已提交
608 609
{
	struct zfcp_fsf_req *req;
610 611 612 613 614 615 616

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

	if (unlikely(!req))
S
Swen Schillig 已提交
617
		return NULL;
618

S
Swen Schillig 已提交
619
	memset(req, 0, sizeof(*req));
620
	req->pool = pool;
S
Swen Schillig 已提交
621 622 623
	return req;
}

624
static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
S
Swen Schillig 已提交
625
{
626
	struct fsf_qtcb *qtcb;
S
Swen Schillig 已提交
627 628 629 630

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

S
Swen Schillig 已提交
633 634 635 636
	if (unlikely(!qtcb))
		return NULL;

	memset(qtcb, 0, sizeof(*qtcb));
637
	return qtcb;
S
Swen Schillig 已提交
638 639
}

640
static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
641 642
						u32 fsf_cmd, u32 sbtype,
						mempool_t *pool)
L
Linus Torvalds 已提交
643
{
644
	struct zfcp_adapter *adapter = qdio->adapter;
645
	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
L
Linus Torvalds 已提交
646

S
Swen Schillig 已提交
647
	if (unlikely(!req))
648
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
649

S
Swen Schillig 已提交
650 651
	if (adapter->req_no == 0)
		adapter->req_no++;
L
Linus Torvalds 已提交
652

S
Swen Schillig 已提交
653 654
	INIT_LIST_HEAD(&req->list);
	init_timer(&req->timer);
655
	init_completion(&req->completion);
L
Linus Torvalds 已提交
656

S
Swen Schillig 已提交
657 658
	req->adapter = adapter;
	req->fsf_command = fsf_cmd;
659
	req->req_id = adapter->req_no;
S
Swen Schillig 已提交
660

661 662 663 664 665 666 667 668 669 670 671
	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);
		}

672
		req->seq_no = adapter->fsf_req_seq_no;
673
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
S
Swen Schillig 已提交
674 675 676 677 678 679 680 681
		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;
	}

682 683 684
	zfcp_qdio_req_init(adapter->qdio, &req->qdio_req, req->req_id, sbtype,
			   req->qtcb, sizeof(struct fsf_qtcb));

S
Swen Schillig 已提交
685
	return req;
L
Linus Torvalds 已提交
686 687
}

S
Swen Schillig 已提交
688 689 690
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
691
	struct zfcp_qdio *qdio = adapter->qdio;
692
	int with_qtcb = (req->qtcb != NULL);
693
	int req_id = req->req_id;
S
Swen Schillig 已提交
694

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

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

	/* Don't increase for unsolicited status */
708
	if (with_qtcb)
S
Swen Schillig 已提交
709
		adapter->fsf_req_seq_no++;
710
	adapter->req_no++;
S
Swen Schillig 已提交
711 712 713 714 715 716 717 718 719

	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 已提交
720
 */
721
int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
L
Linus Torvalds 已提交
722
{
723
	struct zfcp_adapter *adapter = qdio->adapter;
S
Swen Schillig 已提交
724 725 726
	struct zfcp_fsf_req *req;
	struct fsf_status_read_buffer *sr_buf;
	int retval = -EIO;
L
Linus Torvalds 已提交
727

728
	spin_lock_irq(&qdio->req_q_lock);
729
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
730 731
		goto out;

732
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS, 0,
733
				  adapter->pool.status_read_req);
734
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
735 736
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
737 738
	}

739
	sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
S
Swen Schillig 已提交
740 741 742 743 744 745
	if (!sr_buf) {
		retval = -ENOMEM;
		goto failed_buf;
	}
	memset(sr_buf, 0, sizeof(*sr_buf));
	req->data = sr_buf;
746 747 748

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

S
Swen Schillig 已提交
750 751 752
	retval = zfcp_fsf_req_send(req);
	if (retval)
		goto failed_req_send;
L
Linus Torvalds 已提交
753

S
Swen Schillig 已提交
754 755 756
	goto out;

failed_req_send:
757
	mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
758 759
failed_buf:
	zfcp_fsf_req_free(req);
S
Swen Schillig 已提交
760
	zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
S
Swen Schillig 已提交
761
out:
762
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
763 764 765 766 767
	return retval;
}

static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
768 769
	struct scsi_device *sdev = req->data;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
S
Swen Schillig 已提交
770 771 772 773 774 775
	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 已提交
776
	case FSF_PORT_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
777
		if (fsq->word[0] == fsq->word[1]) {
778
			zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
779
						"fsafch1", req);
S
Swen Schillig 已提交
780
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
781 782 783
		}
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
784
		if (fsq->word[0] == fsq->word[1]) {
785 786
			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2",
					     req);
S
Swen Schillig 已提交
787
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
788 789 790
		}
		break;
	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
S
Swen Schillig 已提交
791
		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
L
Linus Torvalds 已提交
792 793
		break;
	case FSF_PORT_BOXED:
794 795 796 797 798
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3",
				     req);
799
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
800 801
		break;
	case FSF_LUN_BOXED:
802 803 804
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
				    "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 = 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 1347
		zfcp_erp_set_port_status(port,
					 ZFCP_STATUS_COMMON_ERP_FAILED);
S
Swen Schillig 已提交
1348
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1349 1350 1351 1352 1353 1354
		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 已提交
1355
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1356 1357 1358 1359 1360 1361 1362
			break;
		}
		break;
	case FSF_GOOD:
		port->handle = header->port_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1363 1364 1365
		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
		                  &port->status);
L
Linus Torvalds 已提交
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
		/* 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.
		 */
1381
		plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els;
1382
		if (req->qtcb->bottom.support.els1_length >=
1383
		    FSF_PLOGI_MIN_LEN)
S
Swen Schillig 已提交
1384
				zfcp_fc_plogi_evaluate(port, plogi);
L
Linus Torvalds 已提交
1385 1386
		break;
	case FSF_UNKNOWN_OP_SUBTYPE:
S
Swen Schillig 已提交
1387
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1388 1389
		break;
	}
1390 1391

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	switch (header->fsf_status) {

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

	case FSF_GOOD:
1789 1790
		zfcp_sdev->lun_handle = header->lun_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
1791
		zfcp_cfdc_open_lun_eval(sdev, bottom);
L
Linus Torvalds 已提交
1792 1793 1794 1795
		break;
	}
}

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

1808
	spin_lock_irq(&qdio->req_q_lock);
1809
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1810 1811
		goto out;

1812
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1813
				  SBAL_FLAGS0_TYPE_READ,
1814
				  adapter->pool.erp_req);
1815

1816
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1817 1818 1819 1820
		retval = PTR_ERR(req);
		goto out;
	}

1821
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1822
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1823

S
Swen Schillig 已提交
1824
	req->qtcb->header.port_handle = erp_action->port->handle;
1825 1826 1827
	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 已提交
1828
	req->erp_action = erp_action;
1829
	erp_action->fsf_req_id = req->req_id;
S
Swen Schillig 已提交
1830 1831 1832 1833

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

1834
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1835
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1836
	if (retval) {
S
Swen Schillig 已提交
1837
		zfcp_fsf_req_free(req);
1838
		erp_action->fsf_req_id = 0;
L
Linus Torvalds 已提交
1839
	}
S
Swen Schillig 已提交
1840
out:
1841
	spin_unlock_irq(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1842 1843 1844
	return retval;
}

1845
static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1846
{
1847 1848
	struct scsi_device *sdev = req->data;
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
L
Linus Torvalds 已提交
1849

S
Swen Schillig 已提交
1850
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1851
		return;
L
Linus Torvalds 已提交
1852

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

/**
1888 1889
 * zfcp_fsf_close_LUN - close LUN
 * @erp_action: pointer to erp_action triggering the "close LUN"
S
Swen Schillig 已提交
1890
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1891
 */
1892
int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1893
{
1894
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1895
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
S
Swen Schillig 已提交
1896 1897
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1898

1899
	spin_lock_irq(&qdio->req_q_lock);
1900
	if (zfcp_qdio_sbal_get(qdio))
L
Linus Torvalds 已提交
1901
		goto out;
1902

1903
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
1904
				  SBAL_FLAGS0_TYPE_READ,
1905
				  qdio->adapter->pool.erp_req);
1906

1907
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1908 1909 1910
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1911

1912
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1913
	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
L
Linus Torvalds 已提交
1914

S
Swen Schillig 已提交
1915
	req->qtcb->header.port_handle = erp_action->port->handle;
1916 1917 1918
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->handler = zfcp_fsf_close_lun_handler;
	req->data = erp_action->sdev;
S
Swen Schillig 已提交
1919
	req->erp_action = erp_action;
1920
	erp_action->fsf_req_id = req->req_id;
1921

1922
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1923 1924 1925
	retval = zfcp_fsf_req_send(req);
	if (retval) {
		zfcp_fsf_req_free(req);
1926
		erp_action->fsf_req_id = 0;
S
Swen Schillig 已提交
1927 1928
	}
out:
1929
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
1930
	return retval;
L
Linus Torvalds 已提交
1931 1932
}

1933 1934 1935
static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
{
	lat_rec->sum += lat;
S
Swen Schillig 已提交
1936 1937
	lat_rec->min = min(lat_rec->min, lat);
	lat_rec->max = max(lat_rec->max, lat);
1938 1939
}

1940
static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
1941
{
1942 1943
	struct fsf_qual_latency_info *lat_in;
	struct latency_cont *lat = NULL;
1944
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
1945 1946
	struct zfcp_blk_drv_data blktrc;
	int ticks = req->adapter->timer_ticks;
1947

1948
	lat_in = &req->qtcb->prefix.prot_status_qual.latency_info;
1949

1950 1951 1952 1953
	blktrc.flags = 0;
	blktrc.magic = ZFCP_BLK_DRV_DATA_MAGIC;
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
		blktrc.flags |= ZFCP_BLK_REQ_ERROR;
1954
	blktrc.inb_usage = 0;
1955
	blktrc.outb_usage = req->qdio_req.qdio_outb_usage;
1956

1957 1958
	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
	    !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
1959 1960 1961 1962 1963
		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) {
1964 1965
		case FSF_DATADIR_DIF_READ_STRIP:
		case FSF_DATADIR_DIF_READ_CONVERT:
1966
		case FSF_DATADIR_READ:
1967
			lat = &zfcp_sdev->latencies.read;
1968
			break;
1969 1970
		case FSF_DATADIR_DIF_WRITE_INSERT:
		case FSF_DATADIR_DIF_WRITE_CONVERT:
1971
		case FSF_DATADIR_WRITE:
1972
			lat = &zfcp_sdev->latencies.write;
1973 1974
			break;
		case FSF_DATADIR_CMND:
1975
			lat = &zfcp_sdev->latencies.cmd;
1976 1977
			break;
		}
L
Linus Torvalds 已提交
1978

1979
		if (lat) {
1980
			spin_lock(&zfcp_sdev->latencies.lock);
1981 1982 1983
			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
			lat->counter++;
1984
			spin_unlock(&zfcp_sdev->latencies.lock);
1985
		}
S
Stefan Raspl 已提交
1986 1987
	}

1988 1989
	blk_add_driver_data(scsi->request->q, scsi->request, &blktrc,
			    sizeof(blktrc));
S
Stefan Raspl 已提交
1990 1991
}

1992
static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
S
Swen Schillig 已提交
1993
{
1994 1995 1996
	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 已提交
1997 1998 1999
	struct fsf_qtcb_header *header = &req->qtcb->header;

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

S
Swen Schillig 已提交
2002 2003 2004
	switch (header->fsf_status) {
	case FSF_HANDLE_MISMATCH:
	case FSF_PORT_HANDLE_NOT_VALID:
2005 2006
		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1",
					req);
S
Swen Schillig 已提交
2007 2008 2009 2010
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_FCPLUN_NOT_VALID:
	case FSF_LUN_HANDLE_NOT_VALID:
2011
		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2", req);
S
Swen Schillig 已提交
2012
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2013
		break;
S
Swen Schillig 已提交
2014 2015
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
2016
		break;
S
Swen Schillig 已提交
2017
	case FSF_ACCESS_DENIED:
2018 2019
		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2020 2021 2022
		break;
	case FSF_DIRECTION_INDICATOR_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2023
			"Incorrect direction %d, LUN 0x%016Lx on port "
2024
			"0x%016Lx closed\n",
S
Swen Schillig 已提交
2025
			req->qtcb->bottom.io.data_direction,
2026 2027 2028 2029
			(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 已提交
2030 2031 2032 2033
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_CMND_LENGTH_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2034
			"Incorrect CDB length %d, LUN 0x%016Lx on "
2035
			"port 0x%016Lx closed\n",
S
Swen Schillig 已提交
2036
			req->qtcb->bottom.io.fcp_cmnd_length,
2037 2038 2039 2040
			(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 已提交
2041 2042 2043
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_PORT_BOXED:
2044 2045 2046 2047 2048
		zfcp_erp_set_port_status(zfcp_sdev->port,
					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_port_reopen(zfcp_sdev->port,
				     ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5",
				     req);
2049
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2050 2051
		break;
	case FSF_LUN_BOXED:
2052 2053 2054
		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
				    "fssfch6", req);
2055
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
S
Swen Schillig 已提交
2056 2057 2058 2059
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		if (header->fsf_status_qual.word[0] ==
		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
2060
			zfcp_fc_test_link(zfcp_sdev->port);
S
Swen Schillig 已提交
2061
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2062 2063
		break;
	}
2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077
}

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 已提交
2078
	}
2079

2080 2081
	zfcp_fsf_fcp_handler_common(req);

2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117
	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 已提交
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 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157
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 已提交
2158
/**
2159
 * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
S
Swen Schillig 已提交
2160
 * @scsi_cmnd: scsi command to be sent
L
Linus Torvalds 已提交
2161
 */
2162
int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
L
Linus Torvalds 已提交
2163
{
S
Swen Schillig 已提交
2164
	struct zfcp_fsf_req *req;
2165
	struct fcp_cmnd *fcp_cmnd;
2166
	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
2167
	int real_bytes, retval = -EIO, dix_bytes = 0;
2168 2169 2170
	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;
2171
	struct zfcp_qdio *qdio = adapter->qdio;
2172
	struct fsf_qtcb_bottom_io *io;
L
Linus Torvalds 已提交
2173

2174
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2175 2176
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return -EBUSY;
L
Linus Torvalds 已提交
2177

2178
	spin_lock(&qdio->req_q_lock);
2179
	if (atomic_read(&qdio->req_q_free) <= 0) {
2180
		atomic_inc(&qdio->req_q_full);
S
Swen Schillig 已提交
2181
		goto out;
2182
	}
2183

2184 2185 2186
	if (scsi_cmnd->sc_data_direction == DMA_TO_DEVICE)
		sbtype = SBAL_FLAGS0_TYPE_WRITE;

2187
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2188
				  sbtype, adapter->pool.scsi_req);
2189

2190
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2191 2192 2193 2194
		retval = PTR_ERR(req);
		goto out;
	}

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

	io = &req->qtcb->bottom.io;
2198
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
S
Swen Schillig 已提交
2199
	req->data = scsi_cmnd;
2200
	req->handler = zfcp_fsf_fcp_cmnd_handler;
2201 2202
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
2203 2204
	io->service_class = FSF_CLASS_3;
	io->fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2205

2206 2207 2208
	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 已提交
2209 2210
	}

2211 2212
	zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);

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

2216 2217 2218 2219 2220 2221 2222 2223
	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;
	}

2224
	real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
2225
					     scsi_sglist(scsi_cmnd));
2226 2227

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

2230 2231
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);

S
Swen Schillig 已提交
2232 2233 2234
	retval = zfcp_fsf_req_send(req);
	if (unlikely(retval))
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2235

S
Swen Schillig 已提交
2236
	goto out;
L
Linus Torvalds 已提交
2237

S
Swen Schillig 已提交
2238 2239 2240 2241
failed_scsi_cmnd:
	zfcp_fsf_req_free(req);
	scsi_cmnd->host_scribble = NULL;
out:
2242
	spin_unlock(&qdio->req_q_lock);
S
Swen Schillig 已提交
2243
	return retval;
L
Linus Torvalds 已提交
2244 2245
}

2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260
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 已提交
2261
/**
2262 2263
 * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
 * @scmnd: SCSI command to send the task management command for
S
Swen Schillig 已提交
2264 2265
 * @tm_flags: unsigned byte for task management flags
 * Returns: on success pointer to struct fsf_req, NULL otherwise
L
Linus Torvalds 已提交
2266
 */
2267 2268
struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
					    u8 tm_flags)
L
Linus Torvalds 已提交
2269
{
S
Swen Schillig 已提交
2270
	struct zfcp_fsf_req *req = NULL;
2271
	struct fcp_cmnd *fcp_cmnd;
2272 2273
	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
L
Linus Torvalds 已提交
2274

2275
	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
S
Swen Schillig 已提交
2276 2277
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return NULL;
L
Linus Torvalds 已提交
2278

2279
	spin_lock_irq(&qdio->req_q_lock);
2280
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
2281
		goto out;
2282

2283
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2284
				  SBAL_FLAGS0_TYPE_WRITE,
2285
				  qdio->adapter->pool.scsi_req);
2286

2287 2288
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
2289
		goto out;
2290
	}
L
Linus Torvalds 已提交
2291

S
Swen Schillig 已提交
2292
	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
2293
	req->data = scmnd;
2294
	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
2295 2296
	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
S
Swen Schillig 已提交
2297 2298
	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
2299
	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
S
Swen Schillig 已提交
2300

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

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

S
Swen Schillig 已提交
2306 2307 2308
	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;
L
Linus Torvalds 已提交
2309

S
Swen Schillig 已提交
2310 2311 2312
	zfcp_fsf_req_free(req);
	req = NULL;
out:
2313
	spin_unlock_irq(&qdio->req_q_lock);
S
Swen Schillig 已提交
2314 2315
	return req;
}
L
Linus Torvalds 已提交
2316

S
Swen Schillig 已提交
2317 2318
static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
{
L
Linus Torvalds 已提交
2319 2320
}

S
Swen Schillig 已提交
2321 2322 2323 2324 2325
/**
 * 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 已提交
2326
 */
S
Swen Schillig 已提交
2327 2328
struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
					   struct zfcp_fsf_cfdc *fsf_cfdc)
L
Linus Torvalds 已提交
2329
{
2330
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347
	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 已提交
2348

2349
	spin_lock_irq(&qdio->req_q_lock);
2350
	if (zfcp_qdio_sbal_get(qdio))
S
Swen Schillig 已提交
2351
		goto out;
L
Linus Torvalds 已提交
2352

2353
	req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, direction, NULL);
2354
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2355 2356 2357
		retval = -EPERM;
		goto out;
	}
L
Linus Torvalds 已提交
2358

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

S
Swen Schillig 已提交
2361 2362 2363
	bottom = &req->qtcb->bottom.support;
	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
	bottom->option = fsf_cfdc->option;
2364

2365 2366
	bytes = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, fsf_cfdc->sg);

S
Swen Schillig 已提交
2367 2368 2369 2370
	if (bytes != ZFCP_CFDC_MAX_SIZE) {
		zfcp_fsf_req_free(req);
		goto out;
	}
2371
	zfcp_qdio_set_sbale_last(adapter->qdio, &req->qdio_req);
L
Linus Torvalds 已提交
2372

S
Swen Schillig 已提交
2373 2374 2375
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
out:
2376
	spin_unlock_irq(&qdio->req_q_lock);
2377

S
Swen Schillig 已提交
2378
	if (!retval) {
2379
		wait_for_completion(&req->completion);
S
Swen Schillig 已提交
2380
		return req;
L
Linus Torvalds 已提交
2381
	}
S
Swen Schillig 已提交
2382
	return ERR_PTR(retval);
L
Linus Torvalds 已提交
2383
}
2384 2385 2386 2387 2388 2389

/**
 * 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
 */
2390
void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2391
{
2392
	struct zfcp_adapter *adapter = qdio->adapter;
2393
	struct qdio_buffer *sbal = qdio->res_q[sbal_idx];
2394 2395
	struct qdio_buffer_element *sbale;
	struct zfcp_fsf_req *fsf_req;
2396
	unsigned long req_id;
2397 2398 2399 2400 2401 2402
	int idx;

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

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

2405
		if (!fsf_req) {
2406 2407 2408 2409
			/*
			 * Unknown request means that we have potentially memory
			 * corruption and must stop the machine immediately.
			 */
2410
			zfcp_qdio_siosl(adapter);
2411 2412
			panic("error: unknown req_id (%lx) on adapter %s.\n",
			      req_id, dev_name(&adapter->ccw_device->dev));
2413
		}
2414

2415
		fsf_req->qdio_req.sbal_response = sbal_idx;
2416 2417 2418 2419 2420 2421
		zfcp_fsf_req_complete(fsf_req);

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