zfcp_fsf.c 73.6 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, 2009
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>
L
Linus Torvalds 已提交
13
#include "zfcp_ext.h"
14
#include "zfcp_dbf.h"
L
Linus Torvalds 已提交
15

16 17 18
static void zfcp_fsf_request_timeout_handler(unsigned long data)
{
	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
19 20
	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
				"fsrth_1", NULL);
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
}

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 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
/* 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 已提交
58 59
static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
{
S
Swen Schillig 已提交
60
	u16 subtable = table >> 16;
C
Christof Schmitt 已提交
61
	u16 rule = table & 0xffff;
62
	const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
C
Christof Schmitt 已提交
63

64
	if (subtable && subtable < ARRAY_SIZE(act_type))
C
Christof Schmitt 已提交
65
		dev_warn(&adapter->ccw_device->dev,
66 67
			 "Access denied according to ACT rule type %s, "
			 "rule %d\n", act_type[subtable], rule);
C
Christof Schmitt 已提交
68 69 70 71 72 73 74
}

static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
					struct zfcp_port *port)
{
	struct fsf_qtcb_header *header = &req->qtcb->header;
	dev_warn(&req->adapter->ccw_device->dev,
75
		 "Access denied to port 0x%016Lx\n",
76
		 (unsigned long long)port->wwpn);
C
Christof Schmitt 已提交
77 78
	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
79
	zfcp_erp_port_access_denied(port, "fspad_1", req);
C
Christof Schmitt 已提交
80 81 82 83 84 85 86 87
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}

static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
					struct zfcp_unit *unit)
{
	struct fsf_qtcb_header *header = &req->qtcb->header;
	dev_warn(&req->adapter->ccw_device->dev,
88
		 "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
89 90
		 (unsigned long long)unit->fcp_lun,
		 (unsigned long long)unit->port->wwpn);
C
Christof Schmitt 已提交
91 92
	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
93
	zfcp_erp_unit_access_denied(unit, "fsuad_1", req);
C
Christof Schmitt 已提交
94 95 96 97 98
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}

static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
{
99 100
	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
		"operational because of an unsupported FC class\n");
101
	zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1", req);
C
Christof Schmitt 已提交
102 103 104
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}

S
Swen Schillig 已提交
105 106 107
/**
 * zfcp_fsf_req_free - free memory used by fsf request
 * @fsf_req: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
108
 */
S
Swen Schillig 已提交
109
void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
110
{
S
Swen Schillig 已提交
111
	if (likely(req->pool)) {
112 113
		if (likely(req->qtcb))
			mempool_free(req->qtcb, req->adapter->pool.qtcb_pool);
S
Swen Schillig 已提交
114
		mempool_free(req, req->pool);
115 116 117
		return;
	}

118 119 120
	if (likely(req->qtcb))
		kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb);
	kfree(req);
L
Linus Torvalds 已提交
121 122
}

S
Swen Schillig 已提交
123
static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
124
{
S
Swen Schillig 已提交
125 126 127 128 129
	struct fsf_status_read_buffer *sr_buf = req->data;
	struct zfcp_adapter *adapter = req->adapter;
	struct zfcp_port *port;
	int d_id = sr_buf->d_id & ZFCP_DID_MASK;
	unsigned long flags;
L
Linus Torvalds 已提交
130

S
Swen Schillig 已提交
131 132 133 134
	read_lock_irqsave(&zfcp_data.config_lock, flags);
	list_for_each_entry(port, &adapter->port_list_head, list)
		if (port->d_id == d_id) {
			read_unlock_irqrestore(&zfcp_data.config_lock, flags);
135
			zfcp_erp_port_reopen(port, 0, "fssrpc1", req);
S
Swen Schillig 已提交
136 137 138
			return;
		}
	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
L
Linus Torvalds 已提交
139 140
}

141
static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
S
Swen Schillig 已提交
142
					 struct fsf_link_down_info *link_down)
143
{
S
Swen Schillig 已提交
144
	struct zfcp_adapter *adapter = req->adapter;
145
	unsigned long flags;
146

S
Swen Schillig 已提交
147
	if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
148 149 150
		return;

	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
151 152

	read_lock_irqsave(&zfcp_data.config_lock, flags);
153
	zfcp_scsi_schedule_rports_block(adapter);
154
	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
155

S
Swen Schillig 已提交
156
	if (!link_down)
157
		goto out;
158

159 160
	switch (link_down->error_code) {
	case FSF_PSQ_LINK_NO_LIGHT:
S
Swen Schillig 已提交
161
		dev_warn(&req->adapter->ccw_device->dev,
162 163
			 "There is no light signal from the local "
			 "fibre channel cable\n");
164 165
		break;
	case FSF_PSQ_LINK_WRAP_PLUG:
S
Swen Schillig 已提交
166
		dev_warn(&req->adapter->ccw_device->dev,
167 168
			 "There is a wrap plug instead of a fibre "
			 "channel cable\n");
169 170
		break;
	case FSF_PSQ_LINK_NO_FCP:
S
Swen Schillig 已提交
171
		dev_warn(&req->adapter->ccw_device->dev,
172 173
			 "The adjacent fibre channel node does not "
			 "support FCP\n");
174 175
		break;
	case FSF_PSQ_LINK_FIRMWARE_UPDATE:
S
Swen Schillig 已提交
176
		dev_warn(&req->adapter->ccw_device->dev,
177 178
			 "The FCP device is suspended because of a "
			 "firmware update\n");
C
Christof Schmitt 已提交
179
		break;
180
	case FSF_PSQ_LINK_INVALID_WWPN:
S
Swen Schillig 已提交
181
		dev_warn(&req->adapter->ccw_device->dev,
182 183
			 "The FCP device detected a WWPN that is "
			 "duplicate or not valid\n");
184 185
		break;
	case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
S
Swen Schillig 已提交
186
		dev_warn(&req->adapter->ccw_device->dev,
187
			 "The fibre channel fabric does not support NPIV\n");
188 189
		break;
	case FSF_PSQ_LINK_NO_FCP_RESOURCES:
S
Swen Schillig 已提交
190
		dev_warn(&req->adapter->ccw_device->dev,
191
			 "The FCP adapter cannot support more NPIV ports\n");
192 193
		break;
	case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
S
Swen Schillig 已提交
194
		dev_warn(&req->adapter->ccw_device->dev,
195 196
			 "The adjacent switch cannot support "
			 "more NPIV ports\n");
197 198
		break;
	case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
S
Swen Schillig 已提交
199
		dev_warn(&req->adapter->ccw_device->dev,
200 201
			 "The FCP adapter could not log in to the "
			 "fibre channel fabric\n");
202 203
		break;
	case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
S
Swen Schillig 已提交
204
		dev_warn(&req->adapter->ccw_device->dev,
205 206
			 "The WWPN assignment file on the FCP adapter "
			 "has been damaged\n");
207 208
		break;
	case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
S
Swen Schillig 已提交
209
		dev_warn(&req->adapter->ccw_device->dev,
210 211
			 "The mode table on the FCP adapter "
			 "has been damaged\n");
212 213
		break;
	case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
S
Swen Schillig 已提交
214
		dev_warn(&req->adapter->ccw_device->dev,
215 216
			 "All NPIV ports on the FCP adapter have "
			 "been assigned\n");
217 218
		break;
	default:
S
Swen Schillig 已提交
219
		dev_warn(&req->adapter->ccw_device->dev,
220 221
			 "The link between the FCP adapter and "
			 "the FC fabric is down\n");
222
	}
S
Swen Schillig 已提交
223 224
out:
	zfcp_erp_adapter_failed(adapter, id, req);
225 226
}

S
Swen Schillig 已提交
227
static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
228
{
S
Swen Schillig 已提交
229 230 231
	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 已提交
232

S
Swen Schillig 已提交
233 234
	switch (sr_buf->status_subtype) {
	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
235
		zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi);
L
Linus Torvalds 已提交
236
		break;
S
Swen Schillig 已提交
237
	case FSF_STATUS_READ_SUB_FDISC_FAILED:
238
		zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi);
L
Linus Torvalds 已提交
239
		break;
S
Swen Schillig 已提交
240
	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
241
		zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL);
S
Swen Schillig 已提交
242 243
	};
}
L
Linus Torvalds 已提交
244

S
Swen Schillig 已提交
245 246 247 248
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 已提交
249

S
Swen Schillig 已提交
250 251
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
		zfcp_hba_dbf_event_fsf_unsol("dism", adapter, sr_buf);
252
		mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
253 254 255
		zfcp_fsf_req_free(req);
		return;
	}
L
Linus Torvalds 已提交
256

S
Swen Schillig 已提交
257
	zfcp_hba_dbf_event_fsf_unsol("read", adapter, sr_buf);
L
Linus Torvalds 已提交
258

S
Swen Schillig 已提交
259 260 261
	switch (sr_buf->status_type) {
	case FSF_STATUS_READ_PORT_CLOSED:
		zfcp_fsf_status_read_port_closed(req);
L
Linus Torvalds 已提交
262
		break;
S
Swen Schillig 已提交
263 264
	case FSF_STATUS_READ_INCOMING_ELS:
		zfcp_fc_incoming_els(req);
L
Linus Torvalds 已提交
265
		break;
S
Swen Schillig 已提交
266
	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
L
Linus Torvalds 已提交
267
		break;
S
Swen Schillig 已提交
268
	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
269 270 271
		dev_warn(&adapter->ccw_device->dev,
			 "The error threshold for checksum statistics "
			 "has been exceeded\n");
272
		zfcp_hba_dbf_event_berr(adapter, req);
L
Linus Torvalds 已提交
273
		break;
S
Swen Schillig 已提交
274 275 276 277 278
	case FSF_STATUS_READ_LINK_DOWN:
		zfcp_fsf_status_read_link_down(req);
		break;
	case FSF_STATUS_READ_LINK_UP:
		dev_info(&adapter->ccw_device->dev,
279
			 "The local link has been restored\n");
S
Swen Schillig 已提交
280
		/* All ports should be marked as ready to run again */
281
		zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL,
S
Swen Schillig 已提交
282 283 284 285 286
					       ZFCP_STATUS_COMMON_RUNNING,
					       ZFCP_SET);
		zfcp_erp_adapter_reopen(adapter,
					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
					ZFCP_STATUS_COMMON_ERP_FAILED,
287
					"fssrh_2", req);
S
Swen Schillig 已提交
288 289 290
		break;
	case FSF_STATUS_READ_NOTIFICATION_LOST:
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
291 292
			zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
							req);
S
Swen Schillig 已提交
293 294 295 296
		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
			schedule_work(&adapter->scan_work);
		break;
	case FSF_STATUS_READ_CFDC_UPDATED:
297
		zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
S
Swen Schillig 已提交
298 299 300
		break;
	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
		adapter->adapter_features = sr_buf->payload.word[0];
L
Linus Torvalds 已提交
301 302 303
		break;
	}

304
	mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
305
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
306

S
Swen Schillig 已提交
307
	atomic_inc(&adapter->stat_miss);
308
	queue_work(adapter->work_queue, &adapter->stat_work);
S
Swen Schillig 已提交
309
}
L
Linus Torvalds 已提交
310

S
Swen Schillig 已提交
311 312 313 314 315 316 317 318 319 320 321 322 323
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:
		req->status |= ZFCP_STATUS_FSFREQ_ABORTED;
		break;
	case FSF_SQ_NO_RECOM:
		dev_err(&req->adapter->ccw_device->dev,
324 325
			"The FCP adapter reported a problem "
			"that cannot be recovered\n");
326
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req);
S
Swen Schillig 已提交
327 328 329 330
		break;
	}
	/* all non-return stats set FSFREQ_ERROR*/
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
331 332
}

S
Swen Schillig 已提交
333
static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
334
{
S
Swen Schillig 已提交
335 336
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
		return;
L
Linus Torvalds 已提交
337

S
Swen Schillig 已提交
338 339 340
	switch (req->qtcb->header.fsf_status) {
	case FSF_UNKNOWN_COMMAND:
		dev_err(&req->adapter->ccw_device->dev,
341
			"The FCP adapter does not recognize the command 0x%x\n",
S
Swen Schillig 已提交
342
			req->qtcb->header.fsf_command);
343
		zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1", req);
S
Swen Schillig 已提交
344 345 346 347 348 349 350
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		zfcp_fsf_fsfstatus_qual_eval(req);
		break;
	}
}
L
Linus Torvalds 已提交
351

S
Swen Schillig 已提交
352 353 354 355 356
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 已提交
357

S
Swen Schillig 已提交
358
	zfcp_hba_dbf_event_fsf_response(req);
L
Linus Torvalds 已提交
359

S
Swen Schillig 已提交
360 361 362 363 364
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */
		return;
	}
L
Linus Torvalds 已提交
365

S
Swen Schillig 已提交
366 367 368 369 370 371
	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,
372 373 374
			"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]);
375
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1", req);
S
Swen Schillig 已提交
376 377 378
		break;
	case FSF_PROT_ERROR_STATE:
	case FSF_PROT_SEQ_NUMB_ERROR:
379
		zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req);
S
Swen Schillig 已提交
380 381 382 383
		req->status |= ZFCP_STATUS_FSFREQ_RETRY;
		break;
	case FSF_PROT_UNSUPP_QTCB_TYPE:
		dev_err(&adapter->ccw_device->dev,
384
			"The QTCB type is not supported by the FCP adapter\n");
385
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3", req);
S
Swen Schillig 已提交
386 387 388 389 390 391 392
		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,
393
			"0x%Lx is an ambiguous request identifier\n",
S
Swen Schillig 已提交
394
			(unsigned long long)qtcb->bottom.support.req_handle);
395
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
S
Swen Schillig 已提交
396 397
		break;
	case FSF_PROT_LINK_DOWN:
398 399
		zfcp_fsf_link_down_info_eval(req, "fspse_5",
					     &psq->link_down_info);
S
Swen Schillig 已提交
400
		/* FIXME: reopening adapter now? better wait for link up */
401
		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
S
Swen Schillig 已提交
402 403 404
		break;
	case FSF_PROT_REEST_QUEUE:
		/* All ports should be marked as ready to run again */
405
		zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL,
S
Swen Schillig 已提交
406 407 408 409
					       ZFCP_STATUS_COMMON_RUNNING,
					       ZFCP_SET);
		zfcp_erp_adapter_reopen(adapter,
					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
410 411
					ZFCP_STATUS_COMMON_ERP_FAILED,
					"fspse_8", req);
S
Swen Schillig 已提交
412 413 414
		break;
	default:
		dev_err(&adapter->ccw_device->dev,
415
			"0x%x is not a valid transfer protocol status\n",
S
Swen Schillig 已提交
416
			qtcb->prefix.prot_status);
417
		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req);
S
Swen Schillig 已提交
418 419
	}
	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
420 421
}

S
Swen Schillig 已提交
422 423 424 425 426 427 428 429 430
/**
 * 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.
 */
431
static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
432
{
S
Swen Schillig 已提交
433 434 435 436
	if (unlikely(req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
		zfcp_fsf_status_read_handler(req);
		return;
	}
L
Linus Torvalds 已提交
437

S
Swen Schillig 已提交
438 439 440 441
	del_timer(&req->timer);
	zfcp_fsf_protstatus_eval(req);
	zfcp_fsf_fsfstatus_eval(req);
	req->handler(req);
L
Linus Torvalds 已提交
442

S
Swen Schillig 已提交
443
	if (req->erp_action)
444
		zfcp_erp_notify(req->erp_action, 0);
L
Linus Torvalds 已提交
445

S
Swen Schillig 已提交
446 447 448
	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
		zfcp_fsf_req_free(req);
	else
449
		complete(&req->completion);
S
Swen Schillig 已提交
450
}
L
Linus Torvalds 已提交
451

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
/**
 * 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;
	unsigned long flags;
	LIST_HEAD(remove_queue);
	unsigned int i;

	BUG_ON(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP);
	spin_lock_irqsave(&adapter->req_list_lock, flags);
	for (i = 0; i < REQUEST_LIST_SIZE; i++)
		list_splice_init(&adapter->req_list[i], &remove_queue);
	spin_unlock_irqrestore(&adapter->req_list_lock, flags);

	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 已提交
481 482 483 484 485
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
{
	struct fsf_qtcb_bottom_config *bottom;
	struct zfcp_adapter *adapter = req->adapter;
	struct Scsi_Host *shost = adapter->scsi_host;
L
Linus Torvalds 已提交
486

S
Swen Schillig 已提交
487
	bottom = &req->qtcb->bottom.config;
L
Linus Torvalds 已提交
488

S
Swen Schillig 已提交
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));

	fc_host_node_name(shost) = bottom->nport_serv_param.wwnn;
	fc_host_port_name(shost) = bottom->nport_serv_param.wwpn;
	fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
	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;
	adapter->timer_ticks = bottom->timer_interval;

	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:
		adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
		adapter->peer_wwpn = bottom->plogi_payload.wwpn;
		adapter->peer_wwnn = bottom->plogi_payload.wwnn;
		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;
516
		/* fall through */
S
Swen Schillig 已提交
517 518
	default:
		dev_err(&adapter->ccw_device->dev,
519 520
			"Unknown or unsupported arbitrated loop "
			"fibre channel topology detected\n");
521
		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req);
S
Swen Schillig 已提交
522
		return -EIO;
L
Linus Torvalds 已提交
523
	}
S
Swen Schillig 已提交
524

L
Linus Torvalds 已提交
525 526 527
	return 0;
}

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

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

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

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

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

S
Swen Schillig 已提交
569 570
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
				&adapter->status);
L
Linus Torvalds 已提交
571

572
		zfcp_fsf_link_down_info_eval(req, "fsecdh2",
S
Swen Schillig 已提交
573
			&qtcb->header.fsf_status_qual.link_down_info);
L
Linus Torvalds 已提交
574
		break;
S
Swen Schillig 已提交
575
	default:
576
		zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req);
S
Swen Schillig 已提交
577 578
		return;
	}
L
Linus Torvalds 已提交
579

S
Swen Schillig 已提交
580 581 582 583 584 585 586
	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 已提交
587

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

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

S
Swen Schillig 已提交
609 610
	if (req->data)
		memcpy(req->data, bottom, sizeof(*bottom));
611

612
	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
S
Swen Schillig 已提交
613
		fc_host_permanent_port_name(shost) = bottom->wwpn;
614 615
		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
	} else
S
Swen Schillig 已提交
616 617 618 619
		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;
}
L
Linus Torvalds 已提交
620

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

640
static int zfcp_fsf_sbal_check(struct zfcp_qdio *qdio)
S
Swen Schillig 已提交
641
{
642
	struct zfcp_qdio_queue *req_q = &qdio->req_q;
S
Swen Schillig 已提交
643

644
	spin_lock_bh(&qdio->req_q_lock);
645 646
	if (atomic_read(&req_q->count))
		return 1;
647
	spin_unlock_bh(&qdio->req_q_lock);
648 649 650
	return 0;
}

651
static int zfcp_fsf_req_sbal_get(struct zfcp_qdio *qdio)
652
{
653
	struct zfcp_adapter *adapter = qdio->adapter;
654
	long ret;
655

656 657 658
	spin_unlock_bh(&qdio->req_q_lock);
	ret = wait_event_interruptible_timeout(qdio->req_q_wq,
			       zfcp_fsf_sbal_check(qdio), 5 * HZ);
S
Swen Schillig 已提交
659 660
	if (ret > 0)
		return 0;
661
	if (!ret) {
662
		atomic_inc(&qdio->req_q_full);
663 664 665
		/* assume hanging outbound queue, try queue recovery */
		zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
	}
666

667
	spin_lock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
668 669 670
	return -EIO;
}

671
static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
S
Swen Schillig 已提交
672 673
{
	struct zfcp_fsf_req *req;
674 675 676 677 678 679 680

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

	if (unlikely(!req))
S
Swen Schillig 已提交
681
		return NULL;
682

S
Swen Schillig 已提交
683
	memset(req, 0, sizeof(*req));
684
	req->pool = pool;
S
Swen Schillig 已提交
685 686 687
	return req;
}

688
static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
S
Swen Schillig 已提交
689
{
690
	struct fsf_qtcb *qtcb;
S
Swen Schillig 已提交
691 692 693 694

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

S
Swen Schillig 已提交
697 698 699 700
	if (unlikely(!qtcb))
		return NULL;

	memset(qtcb, 0, sizeof(*qtcb));
701
	return qtcb;
S
Swen Schillig 已提交
702 703
}

704
static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
705
						u32 fsf_cmd, mempool_t *pool)
L
Linus Torvalds 已提交
706
{
707
	struct qdio_buffer_element *sbale;
708 709
	struct zfcp_qdio_queue *req_q = &qdio->req_q;
	struct zfcp_adapter *adapter = qdio->adapter;
710
	struct zfcp_fsf_req *req = zfcp_fsf_alloc(pool);
L
Linus Torvalds 已提交
711

S
Swen Schillig 已提交
712
	if (unlikely(!req))
713
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
714

S
Swen Schillig 已提交
715 716
	if (adapter->req_no == 0)
		adapter->req_no++;
L
Linus Torvalds 已提交
717

S
Swen Schillig 已提交
718 719
	INIT_LIST_HEAD(&req->list);
	init_timer(&req->timer);
720
	init_completion(&req->completion);
L
Linus Torvalds 已提交
721

S
Swen Schillig 已提交
722 723
	req->adapter = adapter;
	req->fsf_command = fsf_cmd;
724
	req->req_id = adapter->req_no;
725 726 727 728
	req->queue_req.sbal_number = 1;
	req->queue_req.sbal_first = req_q->first;
	req->queue_req.sbal_last = req_q->first;
	req->queue_req.sbale_curr = 1;
S
Swen Schillig 已提交
729

730
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
731 732 733
	sbale[0].addr = (void *) req->req_id;
	sbale[0].flags |= SBAL_FLAGS0_COMMAND;

734 735 736 737 738 739 740 741 742 743 744
	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);
		}

745
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
S
Swen Schillig 已提交
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
		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;
		req->seq_no = adapter->fsf_req_seq_no;
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
		sbale[1].addr = (void *) req->qtcb;
		sbale[1].length = sizeof(struct fsf_qtcb);
	}

	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) {
		zfcp_fsf_req_free(req);
		return ERR_PTR(-EIO);
	}
762

S
Swen Schillig 已提交
763
	return req;
L
Linus Torvalds 已提交
764 765
}

S
Swen Schillig 已提交
766 767 768
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
	struct zfcp_adapter *adapter = req->adapter;
769
	struct zfcp_qdio *qdio = adapter->qdio;
770 771 772
	unsigned long	     flags;
	int		     idx;
	int		     with_qtcb = (req->qtcb != NULL);
S
Swen Schillig 已提交
773 774

	/* put allocated FSF request into hash table */
775
	spin_lock_irqsave(&adapter->req_list_lock, flags);
S
Swen Schillig 已提交
776 777
	idx = zfcp_reqlist_hash(req->req_id);
	list_add_tail(&req->list, &adapter->req_list[idx]);
778
	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
S
Swen Schillig 已提交
779

780
	req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
S
Swen Schillig 已提交
781
	req->issued = get_clock();
782
	if (zfcp_qdio_send(qdio, &req->queue_req)) {
S
Swen Schillig 已提交
783
		del_timer(&req->timer);
784 785 786 787 788
		spin_lock_irqsave(&adapter->req_list_lock, flags);
		/* lookup request again, list might have changed */
		if (zfcp_reqlist_find_safe(adapter, req))
			zfcp_reqlist_remove(adapter, req);
		spin_unlock_irqrestore(&adapter->req_list_lock, flags);
789
		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req);
S
Swen Schillig 已提交
790 791 792 793
		return -EIO;
	}

	/* Don't increase for unsolicited status */
794
	if (with_qtcb)
S
Swen Schillig 已提交
795
		adapter->fsf_req_seq_no++;
796
	adapter->req_no++;
S
Swen Schillig 已提交
797 798 799 800 801 802 803 804 805

	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 已提交
806
 */
807
int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
L
Linus Torvalds 已提交
808
{
809
	struct zfcp_adapter *adapter = qdio->adapter;
S
Swen Schillig 已提交
810 811
	struct zfcp_fsf_req *req;
	struct fsf_status_read_buffer *sr_buf;
812
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
813
	int retval = -EIO;
L
Linus Torvalds 已提交
814

815 816
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
817 818
		goto out;

819
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_UNSOLICITED_STATUS,
820
				  adapter->pool.status_read_req);
821
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
822 823
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
824 825
	}

826
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
827
	sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
828
	req->queue_req.sbale_curr = 2;
S
Swen Schillig 已提交
829

830
	sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
S
Swen Schillig 已提交
831 832 833 834 835 836
	if (!sr_buf) {
		retval = -ENOMEM;
		goto failed_buf;
	}
	memset(sr_buf, 0, sizeof(*sr_buf));
	req->data = sr_buf;
837
	sbale = zfcp_qdio_sbale_curr(qdio, &req->queue_req);
S
Swen Schillig 已提交
838 839
	sbale->addr = (void *) sr_buf;
	sbale->length = sizeof(*sr_buf);
840

S
Swen Schillig 已提交
841 842 843
	retval = zfcp_fsf_req_send(req);
	if (retval)
		goto failed_req_send;
L
Linus Torvalds 已提交
844

S
Swen Schillig 已提交
845 846 847
	goto out;

failed_req_send:
848
	mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
849 850 851 852
failed_buf:
	zfcp_fsf_req_free(req);
	zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL);
out:
853
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
854 855 856 857 858 859 860 861 862 863 864 865
	return retval;
}

static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_unit *unit = req->data;
	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 已提交
866
	case FSF_PORT_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
867
		if (fsq->word[0] == fsq->word[1]) {
868 869
			zfcp_erp_adapter_reopen(unit->port->adapter, 0,
						"fsafch1", req);
S
Swen Schillig 已提交
870
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
871 872 873
		}
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
874
		if (fsq->word[0] == fsq->word[1]) {
875
			zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
S
Swen Schillig 已提交
876
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
877 878 879
		}
		break;
	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
S
Swen Schillig 已提交
880
		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
L
Linus Torvalds 已提交
881 882
		break;
	case FSF_PORT_BOXED:
883
		zfcp_erp_port_boxed(unit->port, "fsafch3", req);
S
Swen Schillig 已提交
884 885
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
886 887
		break;
	case FSF_LUN_BOXED:
888
		zfcp_erp_unit_boxed(unit, "fsafch4", req);
S
Swen Schillig 已提交
889 890
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
891 892
                break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
893
		switch (fsq->word[0]) {
L
Linus Torvalds 已提交
894
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
895
			zfcp_test_link(unit->port);
896
			/* fall through */
L
Linus Torvalds 已提交
897
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
898
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
899 900 901 902
			break;
		}
		break;
	case FSF_GOOD:
S
Swen Schillig 已提交
903
		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
L
Linus Torvalds 已提交
904 905 906 907 908
		break;
	}
}

/**
S
Swen Schillig 已提交
909 910 911 912
 * zfcp_fsf_abort_fcp_command - abort running SCSI command
 * @old_req_id: unsigned long
 * @unit: pointer to struct zfcp_unit
 * Returns: pointer to struct zfcp_fsf_req
L
Linus Torvalds 已提交
913 914
 */

S
Swen Schillig 已提交
915
struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
916
						struct zfcp_unit *unit)
L
Linus Torvalds 已提交
917
{
918
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
919
	struct zfcp_fsf_req *req = NULL;
920
	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
921

922 923
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
924
		goto out;
925 926
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
				  qdio->adapter->pool.scsi_abort);
927 928
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
929
		goto out;
930
	}
931

S
Swen Schillig 已提交
932 933 934
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		goto out_error_free;
L
Linus Torvalds 已提交
935

936
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
937 938
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
939

S
Swen Schillig 已提交
940 941 942 943 944 945 946 947 948 949 950 951 952 953
	req->data = unit;
	req->handler = zfcp_fsf_abort_fcp_command_handler;
	req->qtcb->header.lun_handle = unit->handle;
	req->qtcb->header.port_handle = unit->port->handle;
	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:
954
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
955
	return req;
L
Linus Torvalds 已提交
956 957
}

S
Swen Schillig 已提交
958
static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
959
{
S
Swen Schillig 已提交
960 961 962
	struct zfcp_adapter *adapter = req->adapter;
	struct zfcp_send_ct *send_ct = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
963

S
Swen Schillig 已提交
964
	send_ct->status = -EINVAL;
L
Linus Torvalds 已提交
965

S
Swen Schillig 已提交
966
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
967 968 969 970
		goto skip_fsfstatus;

	switch (header->fsf_status) {
        case FSF_GOOD:
S
Swen Schillig 已提交
971 972
		zfcp_san_dbf_event_ct_response(req);
		send_ct->status = 0;
L
Linus Torvalds 已提交
973 974
		break;
        case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
975
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
976 977 978 979 980
		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 已提交
981
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
982 983 984 985 986 987
			break;
                }
                break;
	case FSF_ACCESS_DENIED:
		break;
        case FSF_PORT_BOXED:
S
Swen Schillig 已提交
988 989
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
990
		break;
S
Swen Schillig 已提交
991
	case FSF_PORT_HANDLE_NOT_VALID:
992
		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req);
993
		/* fall through */
S
Swen Schillig 已提交
994
	case FSF_GENERIC_COMMAND_REJECTED:
L
Linus Torvalds 已提交
995 996 997 998
	case FSF_PAYLOAD_SIZE_MISMATCH:
	case FSF_REQUEST_SIZE_TOO_LARGE:
	case FSF_RESPONSE_SIZE_TOO_LARGE:
	case FSF_SBAL_MISMATCH:
S
Swen Schillig 已提交
999
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1000 1001 1002 1003
		break;
	}

skip_fsfstatus:
S
Swen Schillig 已提交
1004
	if (send_ct->handler)
L
Linus Torvalds 已提交
1005
		send_ct->handler(send_ct->handler_data);
S
Swen Schillig 已提交
1006
}
L
Linus Torvalds 已提交
1007

1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
					    struct scatterlist *sg_req,
					    struct scatterlist *sg_resp)
{
	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
	sbale[2].addr   = sg_virt(sg_req);
	sbale[2].length = sg_req->length;
	sbale[3].addr   = sg_virt(sg_resp);
	sbale[3].length = sg_resp->length;
	sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
}

static int zfcp_fsf_one_sbal(struct scatterlist *sg)
{
	return sg_is_last(sg) && sg->length <= PAGE_SIZE;
}

1025 1026 1027 1028
static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
				       struct scatterlist *sg_req,
				       struct scatterlist *sg_resp,
				       int max_sbals)
S
Swen Schillig 已提交
1029
{
1030
	struct zfcp_adapter *adapter = req->adapter;
1031
	struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio,
1032 1033
							       &req->queue_req);
	u32 feat = adapter->adapter_features;
S
Swen Schillig 已提交
1034 1035
	int bytes;

1036
	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
1037
		if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
1038 1039
			return -EOPNOTSUPP;

1040 1041 1042 1043 1044 1045 1046
		zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
		return 0;
	}

	/* use single, unchained SBAL if it can hold the request */
	if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) {
		zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
1047 1048 1049
		return 0;
	}

1050
	bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
1051
					SBAL_FLAGS0_TYPE_WRITE_READ,
S
Swen Schillig 已提交
1052 1053
					sg_req, max_sbals);
	if (bytes <= 0)
1054
		return -EIO;
S
Swen Schillig 已提交
1055
	req->qtcb->bottom.support.req_buf_length = bytes;
1056
	req->queue_req.sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
S
Swen Schillig 已提交
1057

1058
	bytes = zfcp_qdio_sbals_from_sg(adapter->qdio, &req->queue_req,
1059
					SBAL_FLAGS0_TYPE_WRITE_READ,
S
Swen Schillig 已提交
1060 1061
					sg_resp, max_sbals);
	if (bytes <= 0)
1062
		return -EIO;
S
Swen Schillig 已提交
1063 1064 1065
	req->qtcb->bottom.support.resp_buf_length = bytes;

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

/**
S
Swen Schillig 已提交
1069 1070 1071 1072
 * 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
 * @erp_action: if non-null the Generic Service request sent within ERP
L
Linus Torvalds 已提交
1073
 */
S
Swen Schillig 已提交
1074 1075
int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
		     struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1076
{
1077
	struct zfcp_wka_port *wka_port = ct->wka_port;
1078
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
S
Swen Schillig 已提交
1079 1080
	struct zfcp_fsf_req *req;
	int ret = -EIO;
L
Linus Torvalds 已提交
1081

1082 1083
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1084
		goto out;
L
Linus Torvalds 已提交
1085

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

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

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

S
Swen Schillig 已提交
1099
	req->handler = zfcp_fsf_send_ct_handler;
1100
	req->qtcb->header.port_handle = wka_port->handle;
S
Swen Schillig 已提交
1101 1102 1103 1104 1105 1106 1107 1108 1109
	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
	req->qtcb->bottom.support.timeout = ct->timeout;
	req->data = ct;

	zfcp_san_dbf_event_ct_request(req);

	if (erp_action) {
		erp_action->fsf_req = req;
		req->erp_action = erp_action;
1110
		zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1111 1112
	} else
		zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
L
Linus Torvalds 已提交
1113

S
Swen Schillig 已提交
1114 1115 1116
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;
L
Linus Torvalds 已提交
1117

S
Swen Schillig 已提交
1118
	goto out;
L
Linus Torvalds 已提交
1119

S
Swen Schillig 已提交
1120 1121 1122 1123 1124
failed_send:
	zfcp_fsf_req_free(req);
	if (erp_action)
		erp_action->fsf_req = NULL;
out:
1125
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
1126
	return ret;
L
Linus Torvalds 已提交
1127 1128
}

S
Swen Schillig 已提交
1129
static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1130
{
S
Swen Schillig 已提交
1131 1132 1133
	struct zfcp_send_els *send_els = req->data;
	struct zfcp_port *port = send_els->port;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1134

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

S
Swen Schillig 已提交
1137
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
1138 1139 1140 1141
		goto skip_fsfstatus;

	switch (header->fsf_status) {
	case FSF_GOOD:
S
Swen Schillig 已提交
1142 1143
		zfcp_san_dbf_event_els_response(req);
		send_els->status = 0;
L
Linus Torvalds 已提交
1144 1145
		break;
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
S
Swen Schillig 已提交
1146
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
1147 1148 1149 1150
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]){
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1151 1152
			if (port && (send_els->ls_code != ZFCP_LS_ADISC))
				zfcp_test_link(port);
S
Swen Schillig 已提交
1153
			/*fall through */
L
Linus Torvalds 已提交
1154 1155
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
		case FSF_SQ_RETRY_IF_POSSIBLE:
S
Swen Schillig 已提交
1156
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1157 1158 1159 1160 1161 1162 1163 1164 1165
			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:
1166 1167
		if (port)
			zfcp_fsf_access_denied_port(req, port);
L
Linus Torvalds 已提交
1168
		break;
S
Swen Schillig 已提交
1169 1170 1171
	case FSF_SBAL_MISMATCH:
		/* should never occure, avoided in zfcp_fsf_send_els */
		/* fall through */
L
Linus Torvalds 已提交
1172
	default:
S
Swen Schillig 已提交
1173
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1174 1175 1176
		break;
	}
skip_fsfstatus:
H
Heiko Carstens 已提交
1177
	if (send_els->handler)
L
Linus Torvalds 已提交
1178
		send_els->handler(send_els->handler_data);
S
Swen Schillig 已提交
1179
}
L
Linus Torvalds 已提交
1180

S
Swen Schillig 已提交
1181 1182 1183 1184 1185 1186 1187
/**
 * zfcp_fsf_send_els - initiate an ELS command (FC-FS)
 * @els: pointer to struct zfcp_send_els with data for the command
 */
int zfcp_fsf_send_els(struct zfcp_send_els *els)
{
	struct zfcp_fsf_req *req;
1188
	struct zfcp_qdio *qdio = els->adapter->qdio;
S
Swen Schillig 已提交
1189 1190 1191
	struct fsf_qtcb_bottom_support *bottom;
	int ret = -EIO;

1192 1193
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1194
		goto out;
1195

1196
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_ELS, NULL);
1197

1198
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1199 1200 1201 1202
		ret = PTR_ERR(req);
		goto out;
	}

1203
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1204
	ret = zfcp_fsf_setup_ct_els_sbals(req, els->req, els->resp, 2);
1205

S
Swen Schillig 已提交
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
	if (ret)
		goto failed_send;

	bottom = &req->qtcb->bottom.support;
	req->handler = zfcp_fsf_send_els_handler;
	bottom->d_id = els->d_id;
	bottom->service_class = FSF_CLASS_3;
	bottom->timeout = 2 * R_A_TOV;
	req->data = els;

	zfcp_san_dbf_event_els_request(req);

	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;

	goto out;

failed_send:
	zfcp_fsf_req_free(req);
out:
1228
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
1229
	return ret;
L
Linus Torvalds 已提交
1230 1231
}

S
Swen Schillig 已提交
1232
int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1233
{
1234
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1235
	struct zfcp_fsf_req *req;
1236
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1237 1238
	int retval = -EIO;

1239 1240
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1241
		goto out;
1242

1243 1244
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
				  qdio->adapter->pool.erp_req);
1245

1246
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1247 1248
		retval = PTR_ERR(req);
		goto out;
L
Linus Torvalds 已提交
1249 1250
	}

1251
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1252
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1253 1254
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
1255

S
Swen Schillig 已提交
1256
	req->qtcb->bottom.config.feature_selection =
1257 1258
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
1259
			FSF_FEATURE_NOTIFICATION_LOST |
1260
			FSF_FEATURE_UPDATE_ALERT;
S
Swen Schillig 已提交
1261 1262 1263
	req->erp_action = erp_action;
	req->handler = zfcp_fsf_exchange_config_data_handler;
	erp_action->fsf_req = req;
L
Linus Torvalds 已提交
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);
L
Linus Torvalds 已提交
1269 1270
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1271
out:
1272
	spin_unlock_bh(&qdio->req_q_lock);
1273 1274
	return retval;
}
L
Linus Torvalds 已提交
1275

1276
int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
S
Swen Schillig 已提交
1277
				       struct fsf_qtcb_bottom_config *data)
1278
{
1279
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1280 1281 1282
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;

1283 1284
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
1285
		goto out_unlock;
S
Swen Schillig 已提交
1286

1287
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, NULL);
1288

1289
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1290
		retval = PTR_ERR(req);
1291
		goto out_unlock;
1292 1293
	}

1294
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1295 1296
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
S
Swen Schillig 已提交
1297
	req->handler = zfcp_fsf_exchange_config_data_handler;
1298

S
Swen Schillig 已提交
1299
	req->qtcb->bottom.config.feature_selection =
1300 1301 1302 1303 1304 1305
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
			FSF_FEATURE_NOTIFICATION_LOST |
			FSF_FEATURE_UPDATE_ALERT;

	if (data)
S
Swen Schillig 已提交
1306
		req->data = data;
1307

S
Swen Schillig 已提交
1308 1309
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
1310
	spin_unlock_bh(&qdio->req_q_lock);
C
Christof Schmitt 已提交
1311
	if (!retval)
1312
		wait_for_completion(&req->completion);
1313

S
Swen Schillig 已提交
1314
	zfcp_fsf_req_free(req);
1315
	return retval;
1316

1317
out_unlock:
1318
	spin_unlock_bh(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1319 1320 1321 1322 1323
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data - request information about local port
1324
 * @erp_action: ERP action for the adapter for which port data is requested
S
Swen Schillig 已提交
1325
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1326
 */
S
Swen Schillig 已提交
1327
int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1328
{
1329
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1330
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1331 1332
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
1333

1334
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1335
		return -EOPNOTSUPP;
L
Linus Torvalds 已提交
1336

1337 1338
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1339
		goto out;
1340

1341 1342
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
				  qdio->adapter->pool.erp_req);
1343

1344
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1345 1346
		retval = PTR_ERR(req);
		goto out;
1347 1348
	}

1349
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1350
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1351 1352
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
1353

S
Swen Schillig 已提交
1354 1355 1356
	req->handler = zfcp_fsf_exchange_port_data_handler;
	req->erp_action = erp_action;
	erp_action->fsf_req = req;
1357

1358
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1359
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1360
	if (retval) {
S
Swen Schillig 已提交
1361
		zfcp_fsf_req_free(req);
1362 1363
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1364
out:
1365
	spin_unlock_bh(&qdio->req_q_lock);
1366 1367 1368 1369 1370
	return retval;
}

/**
 * zfcp_fsf_exchange_port_data_sync - request information about local port
1371
 * @qdio: pointer to struct zfcp_qdio
S
Swen Schillig 已提交
1372 1373
 * @data: pointer to struct fsf_qtcb_bottom_port
 * Returns: 0 on success, error otherwise
1374
 */
1375
int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
S
Swen Schillig 已提交
1376
				     struct fsf_qtcb_bottom_port *data)
1377
{
1378
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1379 1380
	struct zfcp_fsf_req *req = NULL;
	int retval = -EIO;
1381

1382
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1383 1384
		return -EOPNOTSUPP;

1385 1386
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
1387
		goto out_unlock;
S
Swen Schillig 已提交
1388

1389
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, NULL);
1390

1391
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1392
		retval = PTR_ERR(req);
1393
		goto out_unlock;
L
Linus Torvalds 已提交
1394 1395
	}

1396
	if (data)
S
Swen Schillig 已提交
1397
		req->data = data;
1398

1399
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1400 1401 1402
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1403 1404 1405
	req->handler = zfcp_fsf_exchange_port_data_handler;
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
1406
	spin_unlock_bh(&qdio->req_q_lock);
1407

C
Christof Schmitt 已提交
1408
	if (!retval)
1409 1410
		wait_for_completion(&req->completion);

S
Swen Schillig 已提交
1411
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1412 1413

	return retval;
1414 1415

out_unlock:
1416
	spin_unlock_bh(&qdio->req_q_lock);
1417
	return retval;
L
Linus Torvalds 已提交
1418 1419
}

S
Swen Schillig 已提交
1420
static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1421
{
S
Swen Schillig 已提交
1422 1423
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1424 1425
	struct fsf_plogi *plogi;

S
Swen Schillig 已提交
1426
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1427
		goto out;
L
Linus Torvalds 已提交
1428 1429 1430 1431 1432

	switch (header->fsf_status) {
	case FSF_PORT_ALREADY_OPEN:
		break;
	case FSF_ACCESS_DENIED:
S
Swen Schillig 已提交
1433
		zfcp_fsf_access_denied_port(req, port);
L
Linus Torvalds 已提交
1434 1435
		break;
	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
S
Swen Schillig 已提交
1436
		dev_warn(&req->adapter->ccw_device->dev,
1437
			 "Not enough FCP adapter resources to open "
1438 1439
			 "remote port 0x%016Lx\n",
			 (unsigned long long)port->wwpn);
1440
		zfcp_erp_port_failed(port, "fsoph_1", req);
S
Swen Schillig 已提交
1441
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1442 1443 1444 1445 1446 1447
		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 已提交
1448
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1449 1450 1451 1452 1453 1454 1455
			break;
		}
		break;
	case FSF_GOOD:
		port->handle = header->port_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1456 1457 1458
		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
		                  &port->status);
L
Linus Torvalds 已提交
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
		/* 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.
		 */
S
Swen Schillig 已提交
1474
		plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
1475 1476
		if (req->qtcb->bottom.support.els1_length >=
		    FSF_PLOGI_MIN_LEN) {
S
Swen Schillig 已提交
1477
			if (plogi->serv_param.wwpn != port->wwpn)
1478
				port->d_id = 0;
S
Swen Schillig 已提交
1479 1480 1481
			else {
				port->wwnn = plogi->serv_param.wwnn;
				zfcp_fc_plogi_evaluate(port, plogi);
L
Linus Torvalds 已提交
1482 1483 1484 1485
			}
		}
		break;
	case FSF_UNKNOWN_OP_SUBTYPE:
S
Swen Schillig 已提交
1486
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1487 1488
		break;
	}
1489 1490 1491

out:
	zfcp_port_put(port);
L
Linus Torvalds 已提交
1492 1493
}

S
Swen Schillig 已提交
1494 1495 1496 1497
/**
 * 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 已提交
1498
 */
S
Swen Schillig 已提交
1499
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1500
{
1501
	struct qdio_buffer_element *sbale;
1502
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
1503
	struct zfcp_port *port = erp_action->port;
1504
	struct zfcp_fsf_req *req;
S
Swen Schillig 已提交
1505 1506
	int retval = -EIO;

1507 1508
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1509 1510
		goto out;

1511 1512
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
				  qdio->adapter->pool.erp_req);
1513

1514
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1515
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1516
		goto out;
S
Swen Schillig 已提交
1517
	}
L
Linus Torvalds 已提交
1518

1519
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1520
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
L
Linus Torvalds 已提交
1521 1522 1523
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1524
	req->handler = zfcp_fsf_open_port_handler;
1525 1526
	req->qtcb->bottom.support.d_id = port->d_id;
	req->data = port;
S
Swen Schillig 已提交
1527 1528
	req->erp_action = erp_action;
	erp_action->fsf_req = req;
1529
	zfcp_port_get(port);
S
Swen Schillig 已提交
1530

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

S
Swen Schillig 已提交
1543
static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1544
{
S
Swen Schillig 已提交
1545
	struct zfcp_port *port = req->data;
L
Linus Torvalds 已提交
1546

S
Swen Schillig 已提交
1547
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1548
		return;
L
Linus Torvalds 已提交
1549

S
Swen Schillig 已提交
1550
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
1551
	case FSF_PORT_HANDLE_NOT_VALID:
1552
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req);
S
Swen Schillig 已提交
1553
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1554 1555 1556 1557
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		break;
	case FSF_GOOD:
1558
		zfcp_erp_modify_port_status(port, "fscph_2", req,
L
Linus Torvalds 已提交
1559 1560 1561 1562 1563 1564
					    ZFCP_STATUS_COMMON_OPEN,
					    ZFCP_CLEAR);
		break;
	}
}

S
Swen Schillig 已提交
1565 1566 1567 1568
/**
 * 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 已提交
1569
 */
S
Swen Schillig 已提交
1570
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1571
{
1572
	struct qdio_buffer_element *sbale;
1573
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1574 1575 1576
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1577 1578
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1579 1580
		goto out;

1581 1582
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
				  qdio->adapter->pool.erp_req);
1583

1584
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1585
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1586
		goto out;
S
Swen Schillig 已提交
1587
	}
L
Linus Torvalds 已提交
1588

1589
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1590
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
L
Linus Torvalds 已提交
1591 1592 1593
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1594 1595 1596 1597 1598 1599
	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;
	erp_action->fsf_req = req;

1600
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1601
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1602
	if (retval) {
S
Swen Schillig 已提交
1603
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1604 1605
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1606
out:
1607
	spin_unlock_bh(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1608 1609 1610
	return retval;
}

1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624
static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_wka_port *wka_port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
		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);
1625
		/* fall through */
1626 1627
	case FSF_ADAPTER_STATUS_AVAILABLE:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1628
		/* fall through */
1629 1630 1631 1632 1633
	case FSF_ACCESS_DENIED:
		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
		break;
	case FSF_GOOD:
		wka_port->handle = header->port_handle;
1634 1635
		/* fall through */
	case FSF_PORT_ALREADY_OPEN:
1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
		wka_port->status = ZFCP_WKA_PORT_ONLINE;
	}
out:
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_open_wka_port - create and send open wka-port request
 * @wka_port: pointer to struct zfcp_wka_port
 * Returns: 0 on success, error otherwise
 */
int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
{
	struct qdio_buffer_element *sbale;
1650
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1651 1652 1653
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1654 1655
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
1656 1657
		goto out;

1658 1659
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
				  qdio->adapter->pool.erp_req);
1660

1661 1662 1663 1664 1665
	if (unlikely(IS_ERR(req))) {
		retval = PTR_ERR(req);
		goto out;
	}

1666
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1667
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

	req->handler = zfcp_fsf_open_wka_port_handler;
	req->qtcb->bottom.support.d_id = wka_port->d_id;
	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:
1680
	spin_unlock_bh(&qdio->req_q_lock);
1681 1682 1683 1684 1685 1686 1687 1688 1689
	return retval;
}

static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_wka_port *wka_port = req->data;

	if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1690
		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req);
1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
	}

	wka_port->status = ZFCP_WKA_PORT_OFFLINE;
	wake_up(&wka_port->completion_wq);
}

/**
 * zfcp_fsf_close_wka_port - create and send close wka port request
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
 */
int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
{
	struct qdio_buffer_element *sbale;
1705
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1706 1707 1708
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1709 1710
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
1711 1712
		goto out;

1713 1714
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
				  qdio->adapter->pool.erp_req);
1715

1716 1717 1718 1719 1720
	if (unlikely(IS_ERR(req))) {
		retval = PTR_ERR(req);
		goto out;
	}

1721
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1722
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

	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:
1735
	spin_unlock_bh(&qdio->req_q_lock);
1736 1737 1738
	return retval;
}

S
Swen Schillig 已提交
1739
static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1740
{
S
Swen Schillig 已提交
1741 1742
	struct zfcp_port *port = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
L
Linus Torvalds 已提交
1743 1744
	struct zfcp_unit *unit;

S
Swen Schillig 已提交
1745
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1746
		return;
L
Linus Torvalds 已提交
1747 1748 1749

	switch (header->fsf_status) {
	case FSF_PORT_HANDLE_NOT_VALID:
1750
		zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req);
S
Swen Schillig 已提交
1751
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1752 1753
		break;
	case FSF_ACCESS_DENIED:
S
Swen Schillig 已提交
1754
		zfcp_fsf_access_denied_port(req, port);
L
Linus Torvalds 已提交
1755 1756
		break;
	case FSF_PORT_BOXED:
1757 1758 1759 1760 1761 1762
		/* 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);
		list_for_each_entry(unit, &port->unit_list_head, list)
			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
					  &unit->status);
1763 1764 1765 1766
		zfcp_erp_port_boxed(port, "fscpph2", req);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;

L
Linus Torvalds 已提交
1767 1768 1769 1770
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
S
Swen Schillig 已提交
1771
			/* fall through */
L
Linus Torvalds 已提交
1772
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1773
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1774 1775 1776 1777 1778 1779 1780 1781 1782
			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);
		list_for_each_entry(unit, &port->unit_list_head, list)
S
Swen Schillig 已提交
1783 1784
			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
					  &unit->status);
L
Linus Torvalds 已提交
1785 1786 1787 1788
		break;
	}
}

S
Swen Schillig 已提交
1789 1790 1791 1792
/**
 * zfcp_fsf_close_physical_port - close physical port
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success
L
Linus Torvalds 已提交
1793
 */
S
Swen Schillig 已提交
1794
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1795
{
1796
	struct qdio_buffer_element *sbale;
1797
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1798 1799 1800
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1801 1802
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
L
Linus Torvalds 已提交
1803 1804
		goto out;

1805 1806
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PHYSICAL_PORT,
				  qdio->adapter->pool.erp_req);
1807

1808
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1809 1810 1811
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
1812

1813
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1814
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
1815 1816
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
1817

S
Swen Schillig 已提交
1818 1819 1820 1821 1822 1823
	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;
	erp_action->fsf_req = req;

1824
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1825
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1826
	if (retval) {
S
Swen Schillig 已提交
1827
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1828 1829
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1830
out:
1831
	spin_unlock_bh(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1832 1833 1834
	return retval;
}

S
Swen Schillig 已提交
1835
static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1836
{
S
Swen Schillig 已提交
1837 1838 1839 1840 1841 1842
	struct zfcp_adapter *adapter = req->adapter;
	struct zfcp_unit *unit = req->data;
	struct fsf_qtcb_header *header = &req->qtcb->header;
	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
	struct fsf_queue_designator *queue_designator =
				&header->fsf_status_qual.fsf_queue_designator;
1843
	int exclusive, readwrite;
L
Linus Torvalds 已提交
1844

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

	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1849
			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
L
Linus Torvalds 已提交
1850 1851 1852 1853 1854 1855 1856
			  ZFCP_STATUS_UNIT_SHARED |
			  ZFCP_STATUS_UNIT_READONLY,
			  &unit->status);

	switch (header->fsf_status) {

	case FSF_PORT_HANDLE_NOT_VALID:
1857
		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req);
S
Swen Schillig 已提交
1858
		/* fall through */
L
Linus Torvalds 已提交
1859 1860 1861
	case FSF_LUN_ALREADY_OPEN:
		break;
	case FSF_ACCESS_DENIED:
S
Swen Schillig 已提交
1862
		zfcp_fsf_access_denied_unit(req, unit);
L
Linus Torvalds 已提交
1863
		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
C
Christof Schmitt 已提交
1864
		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
L
Linus Torvalds 已提交
1865 1866
		break;
	case FSF_PORT_BOXED:
1867
		zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
S
Swen Schillig 已提交
1868 1869
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
1870 1871
		break;
	case FSF_LUN_SHARING_VIOLATION:
S
Swen Schillig 已提交
1872
		if (header->fsf_status_qual.word[0])
C
Christof Schmitt 已提交
1873
			dev_warn(&adapter->ccw_device->dev,
1874 1875
				 "LUN 0x%Lx on port 0x%Lx is already in "
				 "use by CSS%d, MIF Image ID %x\n",
1876 1877
				 (unsigned long long)unit->fcp_lun,
				 (unsigned long long)unit->port->wwpn,
1878 1879
				 queue_designator->cssid,
				 queue_designator->hla);
S
Swen Schillig 已提交
1880
		else
C
Christof Schmitt 已提交
1881 1882
			zfcp_act_eval_err(adapter,
					  header->fsf_status_qual.word[2]);
1883
		zfcp_erp_unit_access_denied(unit, "fsouh_3", req);
L
Linus Torvalds 已提交
1884 1885
		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
S
Swen Schillig 已提交
1886
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1887 1888
		break;
	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
S
Swen Schillig 已提交
1889
		dev_warn(&adapter->ccw_device->dev,
1890 1891
			 "No handle is available for LUN "
			 "0x%016Lx on port 0x%016Lx\n",
1892 1893
			 (unsigned long long)unit->fcp_lun,
			 (unsigned long long)unit->port->wwpn);
1894
		zfcp_erp_unit_failed(unit, "fsouh_4", req);
S
Swen Schillig 已提交
1895 1896 1897
		/* fall through */
	case FSF_INVALID_COMMAND_OPTION:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1898 1899 1900 1901
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1902
			zfcp_test_link(unit->port);
S
Swen Schillig 已提交
1903
			/* fall through */
L
Linus Torvalds 已提交
1904
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1905
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1906 1907 1908 1909 1910 1911 1912
			break;
		}
		break;

	case FSF_GOOD:
		unit->handle = header->lun_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
1913 1914 1915

		if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
		    (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
1916
		    !zfcp_ccw_priv_sch(adapter)) {
1917 1918 1919 1920 1921
			exclusive = (bottom->lun_access_info &
					FSF_UNIT_ACCESS_EXCLUSIVE);
			readwrite = (bottom->lun_access_info &
					FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);

L
Linus Torvalds 已提交
1922 1923 1924 1925 1926 1927 1928
			if (!exclusive)
		                atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
						&unit->status);

			if (!readwrite) {
                		atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
						&unit->status);
S
Swen Schillig 已提交
1929
				dev_info(&adapter->ccw_device->dev,
1930 1931
					 "SCSI device at LUN 0x%016Lx on port "
					 "0x%016Lx opened read-only\n",
1932 1933
					 (unsigned long long)unit->fcp_lun,
					 (unsigned long long)unit->port->wwpn);
L
Linus Torvalds 已提交
1934 1935 1936
        		}

        		if (exclusive && !readwrite) {
S
Swen Schillig 已提交
1937
				dev_err(&adapter->ccw_device->dev,
1938 1939 1940
					"Exclusive read-only access not "
					"supported (unit 0x%016Lx, "
					"port 0x%016Lx)\n",
1941 1942
					(unsigned long long)unit->fcp_lun,
					(unsigned long long)unit->port->wwpn);
1943
				zfcp_erp_unit_failed(unit, "fsouh_5", req);
S
Swen Schillig 已提交
1944
				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1945
				zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req);
L
Linus Torvalds 已提交
1946
        		} else if (!exclusive && readwrite) {
S
Swen Schillig 已提交
1947
				dev_err(&adapter->ccw_device->dev,
1948 1949
					"Shared read-write access not "
					"supported (unit 0x%016Lx, port "
1950
					"0x%016Lx)\n",
1951 1952
					(unsigned long long)unit->fcp_lun,
					(unsigned long long)unit->port->wwpn);
1953
				zfcp_erp_unit_failed(unit, "fsouh_7", req);
S
Swen Schillig 已提交
1954
				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1955
				zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req);
L
Linus Torvalds 已提交
1956 1957 1958 1959 1960 1961
        		}
		}
		break;
	}
}

S
Swen Schillig 已提交
1962 1963 1964 1965
/**
 * zfcp_fsf_open_unit - open unit
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1966
 */
S
Swen Schillig 已提交
1967
int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1968
{
1969
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1970
	struct zfcp_adapter *adapter = erp_action->adapter;
1971
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1972 1973 1974
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1975 1976
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
L
Linus Torvalds 已提交
1977 1978
		goto out;

1979
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1980
				  adapter->pool.erp_req);
1981

1982
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1983 1984 1985 1986
		retval = PTR_ERR(req);
		goto out;
	}

1987
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1988
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
L
Linus Torvalds 已提交
1989 1990 1991
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001
	req->qtcb->header.port_handle = erp_action->port->handle;
	req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
	req->handler = zfcp_fsf_open_unit_handler;
	req->data = erp_action->unit;
	req->erp_action = erp_action;
	erp_action->fsf_req = req;

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

2002
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
2003
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
2004
	if (retval) {
S
Swen Schillig 已提交
2005
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
2006 2007
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
2008
out:
2009
	spin_unlock_bh(&qdio->req_q_lock);
L
Linus Torvalds 已提交
2010 2011 2012
	return retval;
}

S
Swen Schillig 已提交
2013
static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
2014
{
S
Swen Schillig 已提交
2015
	struct zfcp_unit *unit = req->data;
L
Linus Torvalds 已提交
2016

S
Swen Schillig 已提交
2017
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
2018
		return;
L
Linus Torvalds 已提交
2019

S
Swen Schillig 已提交
2020
	switch (req->qtcb->header.fsf_status) {
L
Linus Torvalds 已提交
2021
	case FSF_PORT_HANDLE_NOT_VALID:
2022
		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req);
S
Swen Schillig 已提交
2023
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2024 2025
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
2026
		zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req);
S
Swen Schillig 已提交
2027
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2028 2029
		break;
	case FSF_PORT_BOXED:
2030
		zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
S
Swen Schillig 已提交
2031 2032
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
2033 2034
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
2035
		switch (req->qtcb->header.fsf_status_qual.word[0]) {
L
Linus Torvalds 已提交
2036
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
2037
			zfcp_test_link(unit->port);
S
Swen Schillig 已提交
2038
			/* fall through */
L
Linus Torvalds 已提交
2039
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
2040
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
			break;
		}
		break;
	case FSF_GOOD:
		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
		break;
	}
}

/**
S
Swen Schillig 已提交
2051 2052 2053
 * zfcp_fsf_close_unit - close zfcp unit
 * @erp_action: pointer to struct zfcp_unit
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
2054
 */
S
Swen Schillig 已提交
2055
int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
2056
{
2057
	struct qdio_buffer_element *sbale;
2058
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
2059 2060
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
2061

2062 2063
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
L
Linus Torvalds 已提交
2064
		goto out;
2065

2066 2067
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
				  qdio->adapter->pool.erp_req);
2068

2069
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2070 2071 2072
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
2073

2074
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
2075
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
2076
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
L
Linus Torvalds 已提交
2077 2078
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
2079 2080 2081 2082 2083 2084
	req->qtcb->header.port_handle = erp_action->port->handle;
	req->qtcb->header.lun_handle = erp_action->unit->handle;
	req->handler = zfcp_fsf_close_unit_handler;
	req->data = erp_action->unit;
	req->erp_action = erp_action;
	erp_action->fsf_req = req;
2085

2086
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
2087 2088 2089 2090 2091 2092
	retval = zfcp_fsf_req_send(req);
	if (retval) {
		zfcp_fsf_req_free(req);
		erp_action->fsf_req = NULL;
	}
out:
2093
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
2094
	return retval;
L
Linus Torvalds 已提交
2095 2096
}

2097 2098 2099
static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
{
	lat_rec->sum += lat;
S
Swen Schillig 已提交
2100 2101
	lat_rec->min = min(lat_rec->min, lat);
	lat_rec->max = max(lat_rec->max, lat);
2102 2103
}

S
Swen Schillig 已提交
2104
static void zfcp_fsf_req_latency(struct zfcp_fsf_req *req)
2105 2106 2107
{
	struct fsf_qual_latency_info *lat_inf;
	struct latency_cont *lat;
S
Swen Schillig 已提交
2108
	struct zfcp_unit *unit = req->unit;
2109

S
Swen Schillig 已提交
2110
	lat_inf = &req->qtcb->prefix.prot_status_qual.latency_info;
2111

S
Swen Schillig 已提交
2112
	switch (req->qtcb->bottom.io.data_direction) {
2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125
	case FSF_DATADIR_READ:
		lat = &unit->latencies.read;
		break;
	case FSF_DATADIR_WRITE:
		lat = &unit->latencies.write;
		break;
	case FSF_DATADIR_CMND:
		lat = &unit->latencies.cmd;
		break;
	default:
		return;
	}

2126
	spin_lock(&unit->latencies.lock);
2127 2128 2129
	zfcp_fsf_update_lat(&lat->channel, lat_inf->channel_lat);
	zfcp_fsf_update_lat(&lat->fabric, lat_inf->fabric_lat);
	lat->counter++;
2130
	spin_unlock(&unit->latencies.lock);
L
Linus Torvalds 已提交
2131 2132
}

S
Stefan Raspl 已提交
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151
#ifdef CONFIG_BLK_DEV_IO_TRACE
static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
{
	struct fsf_qual_latency_info *lat_inf;
	struct scsi_cmnd *scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
	struct request *req = scsi_cmnd->request;
	struct zfcp_blk_drv_data trace;
	int ticks = fsf_req->adapter->timer_ticks;

	trace.flags = 0;
	trace.magic = ZFCP_BLK_DRV_DATA_MAGIC;
	if (fsf_req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
		trace.flags |= ZFCP_BLK_LAT_VALID;
		lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
		trace.channel_lat = lat_inf->channel_lat * ticks;
		trace.fabric_lat = lat_inf->fabric_lat * ticks;
	}
	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
		trace.flags |= ZFCP_BLK_REQ_ERROR;
2152 2153
	trace.inb_usage = fsf_req->queue_req.qdio_inb_usage;
	trace.outb_usage = fsf_req->queue_req.qdio_outb_usage;
S
Stefan Raspl 已提交
2154 2155 2156 2157 2158 2159 2160 2161 2162

	blk_add_driver_data(req->q, req, &trace, sizeof(trace));
}
#else
static inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
{
}
#endif

S
Swen Schillig 已提交
2163
static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
2164
{
2165
	struct scsi_cmnd *scpnt;
L
Linus Torvalds 已提交
2166
	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
S
Swen Schillig 已提交
2167
	    &(req->qtcb->bottom.io.fcp_rsp);
L
Linus Torvalds 已提交
2168
	u32 sns_len;
2169
	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
L
Linus Torvalds 已提交
2170 2171
	unsigned long flags;

S
Swen Schillig 已提交
2172 2173
	read_lock_irqsave(&req->adapter->abort_lock, flags);

2174 2175 2176 2177 2178 2179
	scpnt = req->data;
	if (unlikely(!scpnt)) {
		read_unlock_irqrestore(&req->adapter->abort_lock, flags);
		return;
	}

S
Swen Schillig 已提交
2180
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) {
2181
		set_host_byte(scpnt, DID_SOFT_ERROR);
L
Linus Torvalds 已提交
2182 2183 2184
		goto skip_fsfstatus;
	}

S
Swen Schillig 已提交
2185
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2186
		set_host_byte(scpnt, DID_ERROR);
L
Linus Torvalds 已提交
2187 2188 2189
		goto skip_fsfstatus;
	}

2190
	set_msg_byte(scpnt, COMMAND_COMPLETE);
L
Linus Torvalds 已提交
2191 2192 2193

	scpnt->result |= fcp_rsp_iu->scsi_status;

S
Swen Schillig 已提交
2194 2195
	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
		zfcp_fsf_req_latency(req);
2196

S
Stefan Raspl 已提交
2197 2198
	zfcp_fsf_trace_latency(req);

L
Linus Torvalds 已提交
2199
	if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
S
Swen Schillig 已提交
2200
		if (fcp_rsp_info[3] == RSP_CODE_GOOD)
2201
			set_host_byte(scpnt, DID_OK);
S
Swen Schillig 已提交
2202
		else {
2203
			set_host_byte(scpnt, DID_ERROR);
已提交
2204
			goto skip_fsfstatus;
L
Linus Torvalds 已提交
2205 2206 2207 2208
		}
	}

	if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) {
S
Swen Schillig 已提交
2209 2210
		sns_len = FSF_FCP_RSP_SIZE - sizeof(struct fcp_rsp_iu) +
			  fcp_rsp_iu->fcp_rsp_len;
L
Linus Torvalds 已提交
2211 2212 2213
		sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE);
		sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len);

2214
		memcpy(scpnt->sense_buffer,
L
Linus Torvalds 已提交
2215 2216 2217 2218
		       zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len);
	}

	if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) {
2219 2220 2221
		scsi_set_resid(scpnt, fcp_rsp_iu->fcp_resid);
		if (scsi_bufflen(scpnt) - scsi_get_resid(scpnt) <
		    scpnt->underflow)
2222
			set_host_byte(scpnt, DID_ERROR);
L
Linus Torvalds 已提交
2223
	}
S
Swen Schillig 已提交
2224
skip_fsfstatus:
2225
	if (scpnt->result != 0)
S
Swen Schillig 已提交
2226
		zfcp_scsi_dbf_event_result("erro", 3, req->adapter, scpnt, req);
2227
	else if (scpnt->retries > 0)
S
Swen Schillig 已提交
2228
		zfcp_scsi_dbf_event_result("retr", 4, req->adapter, scpnt, req);
2229
	else
S
Swen Schillig 已提交
2230
		zfcp_scsi_dbf_event_result("norm", 6, req->adapter, scpnt, req);
L
Linus Torvalds 已提交
2231 2232 2233 2234 2235 2236 2237 2238 2239

	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!
	 */
S
Swen Schillig 已提交
2240
	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
L
Linus Torvalds 已提交
2241 2242
}

S
Swen Schillig 已提交
2243
static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
2244 2245
{
	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
S
Swen Schillig 已提交
2246
	    &(req->qtcb->bottom.io.fcp_rsp);
2247
	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
L
Linus Torvalds 已提交
2248

S
Swen Schillig 已提交
2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265
	if ((fcp_rsp_info[3] != RSP_CODE_GOOD) ||
	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
}


static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
{
	struct zfcp_unit *unit;
	struct fsf_qtcb_header *header = &req->qtcb->header;

	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
		unit = req->data;
	else
		unit = req->unit;

	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
L
Linus Torvalds 已提交
2266 2267
		goto skip_fsfstatus;

S
Swen Schillig 已提交
2268 2269 2270
	switch (header->fsf_status) {
	case FSF_HANDLE_MISMATCH:
	case FSF_PORT_HANDLE_NOT_VALID:
2271
		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
S
Swen Schillig 已提交
2272 2273 2274 2275
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_FCPLUN_NOT_VALID:
	case FSF_LUN_HANDLE_NOT_VALID:
2276
		zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
S
Swen Schillig 已提交
2277
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2278
		break;
S
Swen Schillig 已提交
2279 2280
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
2281
		break;
S
Swen Schillig 已提交
2282 2283 2284 2285 2286
	case FSF_ACCESS_DENIED:
		zfcp_fsf_access_denied_unit(req, unit);
		break;
	case FSF_DIRECTION_INDICATOR_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2287 2288
			"Incorrect direction %d, unit 0x%016Lx on port "
			"0x%016Lx closed\n",
S
Swen Schillig 已提交
2289
			req->qtcb->bottom.io.data_direction,
2290 2291
			(unsigned long long)unit->fcp_lun,
			(unsigned long long)unit->port->wwpn);
2292 2293
		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
					  req);
S
Swen Schillig 已提交
2294 2295 2296 2297
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_CMND_LENGTH_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2298 2299
			"Incorrect CDB length %d, unit 0x%016Lx on "
			"port 0x%016Lx closed\n",
S
Swen Schillig 已提交
2300
			req->qtcb->bottom.io.fcp_cmnd_length,
2301 2302
			(unsigned long long)unit->fcp_lun,
			(unsigned long long)unit->port->wwpn);
2303 2304
		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
					  req);
S
Swen Schillig 已提交
2305 2306 2307
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_PORT_BOXED:
2308
		zfcp_erp_port_boxed(unit->port, "fssfch5", req);
S
Swen Schillig 已提交
2309 2310 2311 2312
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
		break;
	case FSF_LUN_BOXED:
2313
		zfcp_erp_unit_boxed(unit, "fssfch6", req);
S
Swen Schillig 已提交
2314 2315 2316 2317 2318 2319 2320 2321
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		if (header->fsf_status_qual.word[0] ==
		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
			zfcp_test_link(unit->port);
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2322 2323
		break;
	}
S
Swen Schillig 已提交
2324 2325 2326 2327 2328 2329 2330 2331
skip_fsfstatus:
	if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
		zfcp_fsf_send_fcp_ctm_handler(req);
	else {
		zfcp_fsf_send_fcp_command_task_handler(req);
		req->unit = NULL;
		zfcp_unit_put(unit);
	}
L
Linus Torvalds 已提交
2332 2333
}

2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347
static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
{
	u32 *fcp_dl_ptr;

	/*
	 * fcp_dl_addr = start address of fcp_cmnd structure +
	 * size of fixed part + size of dynamically sized add_dcp_cdb field
	 * SEE FCP-2 documentation
	 */
	fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] +
			(fcp_cmd->add_fcp_cdb_length << 2));
	*fcp_dl_ptr = fcp_dl;
}

S
Swen Schillig 已提交
2348 2349 2350 2351
/**
 * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
 * @unit: unit where command is sent to
 * @scsi_cmnd: scsi command to be sent
L
Linus Torvalds 已提交
2352
 */
2353 2354
int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
				   struct scsi_cmnd *scsi_cmnd)
L
Linus Torvalds 已提交
2355
{
S
Swen Schillig 已提交
2356 2357
	struct zfcp_fsf_req *req;
	struct fcp_cmnd_iu *fcp_cmnd_iu;
2358
	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
S
Swen Schillig 已提交
2359
	int real_bytes, retval = -EIO;
2360
	struct zfcp_adapter *adapter = unit->port->adapter;
2361
	struct zfcp_qdio *qdio = adapter->qdio;
L
Linus Torvalds 已提交
2362

S
Swen Schillig 已提交
2363 2364 2365
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return -EBUSY;
L
Linus Torvalds 已提交
2366

2367 2368 2369
	spin_lock(&qdio->req_q_lock);
	if (atomic_read(&qdio->req_q.count) <= 0) {
		atomic_inc(&qdio->req_q_full);
S
Swen Schillig 已提交
2370
		goto out;
2371
	}
2372

2373
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2374
				  adapter->pool.scsi_req);
2375

2376
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2377 2378 2379 2380
		retval = PTR_ERR(req);
		goto out;
	}

2381
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
S
Swen Schillig 已提交
2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402
	zfcp_unit_get(unit);
	req->unit = unit;
	req->data = scsi_cmnd;
	req->handler = zfcp_fsf_send_fcp_command_handler;
	req->qtcb->header.lun_handle = unit->handle;
	req->qtcb->header.port_handle = unit->port->handle;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;

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

	fcp_cmnd_iu = (struct fcp_cmnd_iu *) &(req->qtcb->bottom.io.fcp_cmnd);
	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
	/*
	 * set depending on data direction:
	 *      data direction bits in SBALE (SB Type)
	 *      data direction bits in QTCB
	 *      data direction bits in FCP_CMND IU
	 */
	switch (scsi_cmnd->sc_data_direction) {
	case DMA_NONE:
		req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
L
Linus Torvalds 已提交
2403
		break;
S
Swen Schillig 已提交
2404 2405 2406 2407 2408 2409 2410 2411
	case DMA_FROM_DEVICE:
		req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
		fcp_cmnd_iu->rddata = 1;
		break;
	case DMA_TO_DEVICE:
		req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
		sbtype = SBAL_FLAGS0_TYPE_WRITE;
		fcp_cmnd_iu->wddata = 1;
L
Linus Torvalds 已提交
2412
		break;
S
Swen Schillig 已提交
2413 2414
	case DMA_BIDIRECTIONAL:
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2415 2416
	}

S
Swen Schillig 已提交
2417 2418 2419 2420 2421 2422
	if (likely((scsi_cmnd->device->simple_tags) ||
		   ((atomic_read(&unit->status) & ZFCP_STATUS_UNIT_READONLY) &&
		    (atomic_read(&unit->status) & ZFCP_STATUS_UNIT_SHARED))))
		fcp_cmnd_iu->task_attribute = SIMPLE_Q;
	else
		fcp_cmnd_iu->task_attribute = UNTAGGED;
L
Linus Torvalds 已提交
2423

S
Swen Schillig 已提交
2424 2425 2426
	if (unlikely(scsi_cmnd->cmd_len > FCP_CDB_LENGTH))
		fcp_cmnd_iu->add_fcp_cdb_length =
			(scsi_cmnd->cmd_len - FCP_CDB_LENGTH) >> 2;
L
Linus Torvalds 已提交
2427

S
Swen Schillig 已提交
2428
	memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
2429

S
Swen Schillig 已提交
2430
	req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
2431
		fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
L
Linus Torvalds 已提交
2432

2433
	real_bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req, sbtype,
S
Swen Schillig 已提交
2434 2435 2436
					     scsi_sglist(scsi_cmnd),
					     FSF_MAX_SBALS_PER_REQ);
	if (unlikely(real_bytes < 0)) {
2437
		if (req->queue_req.sbal_number >= FSF_MAX_SBALS_PER_REQ) {
S
Swen Schillig 已提交
2438
			dev_err(&adapter->ccw_device->dev,
2439 2440
				"Oversize data package, unit 0x%016Lx "
				"on port 0x%016Lx closed\n",
2441 2442
				(unsigned long long)unit->fcp_lun,
				(unsigned long long)unit->port->wwpn);
2443
			zfcp_erp_unit_shutdown(unit, 0, "fssfct1", req);
S
Swen Schillig 已提交
2444 2445 2446
			retval = -EINVAL;
		}
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2447 2448
	}

S
Swen Schillig 已提交
2449
	zfcp_set_fcp_dl(fcp_cmnd_iu, real_bytes);
L
Linus Torvalds 已提交
2450

S
Swen Schillig 已提交
2451 2452 2453
	retval = zfcp_fsf_req_send(req);
	if (unlikely(retval))
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2454

S
Swen Schillig 已提交
2455
	goto out;
L
Linus Torvalds 已提交
2456

S
Swen Schillig 已提交
2457 2458 2459 2460 2461
failed_scsi_cmnd:
	zfcp_unit_put(unit);
	zfcp_fsf_req_free(req);
	scsi_cmnd->host_scribble = NULL;
out:
2462
	spin_unlock(&qdio->req_q_lock);
S
Swen Schillig 已提交
2463
	return retval;
L
Linus Torvalds 已提交
2464 2465 2466
}

/**
S
Swen Schillig 已提交
2467 2468 2469 2470
 * zfcp_fsf_send_fcp_ctm - send SCSI task management command
 * @unit: pointer to struct zfcp_unit
 * @tm_flags: unsigned byte for task management flags
 * Returns: on success pointer to struct fsf_req, NULL otherwise
L
Linus Torvalds 已提交
2471
 */
2472
struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
L
Linus Torvalds 已提交
2473
{
2474
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
2475 2476
	struct zfcp_fsf_req *req = NULL;
	struct fcp_cmnd_iu *fcp_cmnd_iu;
2477
	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
L
Linus Torvalds 已提交
2478

S
Swen Schillig 已提交
2479 2480 2481
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return NULL;
L
Linus Torvalds 已提交
2482

2483 2484
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
2485
		goto out;
2486

2487 2488
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
				  qdio->adapter->pool.scsi_req);
2489

2490 2491
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
2492
		goto out;
2493
	}
L
Linus Torvalds 已提交
2494

S
Swen Schillig 已提交
2495 2496 2497 2498 2499 2500 2501 2502
	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
	req->data = unit;
	req->handler = zfcp_fsf_send_fcp_command_handler;
	req->qtcb->header.lun_handle = unit->handle;
	req->qtcb->header.port_handle = unit->port->handle;
	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
	req->qtcb->bottom.io.fcp_cmnd_length = 	sizeof(struct fcp_cmnd_iu) +
2503
						sizeof(u32);
S
Swen Schillig 已提交
2504

2505
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
2506 2507
	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
2508

S
Swen Schillig 已提交
2509 2510 2511
	fcp_cmnd_iu = (struct fcp_cmnd_iu *) &req->qtcb->bottom.io.fcp_cmnd;
	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
	fcp_cmnd_iu->task_management_flags = tm_flags;
L
Linus Torvalds 已提交
2512

S
Swen Schillig 已提交
2513 2514 2515
	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;
L
Linus Torvalds 已提交
2516

S
Swen Schillig 已提交
2517 2518 2519
	zfcp_fsf_req_free(req);
	req = NULL;
out:
2520
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
2521 2522
	return req;
}
L
Linus Torvalds 已提交
2523

S
Swen Schillig 已提交
2524 2525
static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
{
L
Linus Torvalds 已提交
2526 2527
}

S
Swen Schillig 已提交
2528 2529 2530 2531 2532
/**
 * 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 已提交
2533
 */
S
Swen Schillig 已提交
2534 2535
struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
					   struct zfcp_fsf_cfdc *fsf_cfdc)
L
Linus Torvalds 已提交
2536
{
2537
	struct qdio_buffer_element *sbale;
2538
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555
	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 已提交
2556

2557 2558
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
2559
		goto out;
L
Linus Torvalds 已提交
2560

2561
	req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, NULL);
2562
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2563 2564 2565
		retval = -EPERM;
		goto out;
	}
L
Linus Torvalds 已提交
2566

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

2569
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
2570
	sbale[0].flags |= direction;
2571

S
Swen Schillig 已提交
2572 2573 2574
	bottom = &req->qtcb->bottom.support;
	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
	bottom->option = fsf_cfdc->option;
2575

2576 2577 2578
	bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req,
					direction, fsf_cfdc->sg,
					FSF_MAX_SBALS_PER_REQ);
S
Swen Schillig 已提交
2579 2580 2581 2582
	if (bytes != ZFCP_CFDC_MAX_SIZE) {
		zfcp_fsf_req_free(req);
		goto out;
	}
L
Linus Torvalds 已提交
2583

S
Swen Schillig 已提交
2584 2585 2586
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
out:
2587
	spin_unlock_bh(&qdio->req_q_lock);
2588

S
Swen Schillig 已提交
2589
	if (!retval) {
2590
		wait_for_completion(&req->completion);
S
Swen Schillig 已提交
2591
		return req;
L
Linus Torvalds 已提交
2592
	}
S
Swen Schillig 已提交
2593
	return ERR_PTR(retval);
L
Linus Torvalds 已提交
2594
}
2595 2596 2597 2598 2599 2600

/**
 * 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
 */
2601
void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2602
{
2603 2604
	struct zfcp_adapter *adapter = qdio->adapter;
	struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx];
2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627
	struct qdio_buffer_element *sbale;
	struct zfcp_fsf_req *fsf_req;
	unsigned long flags, req_id;
	int idx;

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

		sbale = &sbal->element[idx];
		req_id = (unsigned long) sbale->addr;
		spin_lock_irqsave(&adapter->req_list_lock, flags);
		fsf_req = zfcp_reqlist_find(adapter, req_id);

		if (!fsf_req)
			/*
			 * Unknown request means that we have potentially memory
			 * corruption and must stop the machine immediately.
			 */
			panic("error: unknown req_id (%lx) on adapter %s.\n",
			      req_id, dev_name(&adapter->ccw_device->dev));

		list_del(&fsf_req->list);
		spin_unlock_irqrestore(&adapter->req_list_lock, flags);

2628 2629
		fsf_req->queue_req.sbal_response = sbal_idx;
		fsf_req->queue_req.qdio_inb_usage =
2630
			atomic_read(&qdio->resp_q.count);
2631 2632 2633 2634 2635 2636
		zfcp_fsf_req_complete(fsf_req);

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