zfcp_fsf.c 73.7 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
C
Christof Schmitt 已提交
2
 * zfcp device driver
L
Linus Torvalds 已提交
3
 *
C
Christof Schmitt 已提交
4
 * Implementation of FSF commands.
L
Linus Torvalds 已提交
5
 *
6
 * Copyright IBM 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
{
125
	unsigned long flags;
S
Swen Schillig 已提交
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;
L
Linus Torvalds 已提交
130

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

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

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

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

150
	zfcp_scsi_schedule_rports_block(adapter);
151

S
Swen Schillig 已提交
152
	if (!link_down)
153
		goto out;
154

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

S
Swen Schillig 已提交
223
static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
224
{
S
Swen Schillig 已提交
225 226 227
	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 已提交
228

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

S
Swen Schillig 已提交
241 242 243 244
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 已提交
245

S
Swen Schillig 已提交
246
	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
S
Swen Schillig 已提交
247
		zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf);
248
		mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
249 250 251
		zfcp_fsf_req_free(req);
		return;
	}
L
Linus Torvalds 已提交
252

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

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

300
	mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
301
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
302

S
Swen Schillig 已提交
303
	atomic_inc(&adapter->stat_miss);
304
	queue_work(adapter->work_queue, &adapter->stat_work);
S
Swen Schillig 已提交
305
}
L
Linus Torvalds 已提交
306

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

S
Swen Schillig 已提交
329
static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
330
{
S
Swen Schillig 已提交
331 332
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
		return;
L
Linus Torvalds 已提交
333

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

S
Swen Schillig 已提交
348 349 350 351 352
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 已提交
353

S
Swen Schillig 已提交
354
	zfcp_dbf_hba_fsf_response(req);
L
Linus Torvalds 已提交
355

S
Swen Schillig 已提交
356 357 358 359 360
	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 已提交
361

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

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

S
Swen Schillig 已提交
434 435 436 437
	del_timer(&req->timer);
	zfcp_fsf_protstatus_eval(req);
	zfcp_fsf_fsfstatus_eval(req);
	req->handler(req);
L
Linus Torvalds 已提交
438

S
Swen Schillig 已提交
439
	if (req->erp_action)
440
		zfcp_erp_notify(req->erp_action, 0);
L
Linus Torvalds 已提交
441

S
Swen Schillig 已提交
442 443 444
	if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP))
		zfcp_fsf_req_free(req);
	else
445
		complete(&req->completion);
S
Swen Schillig 已提交
446
}
L
Linus Torvalds 已提交
447

448 449 450 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
/**
 * 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 已提交
477 478 479 480 481
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 已提交
482

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

S
Swen Schillig 已提交
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
	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;
512
		/* fall through */
S
Swen Schillig 已提交
513 514
	default:
		dev_err(&adapter->ccw_device->dev,
515 516
			"Unknown or unsupported arbitrated loop "
			"fibre channel topology detected\n");
517
		zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req);
S
Swen Schillig 已提交
518
		return -EIO;
L
Linus Torvalds 已提交
519
	}
S
Swen Schillig 已提交
520

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

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

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

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

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

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

S
Swen Schillig 已提交
565 566
		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
				&adapter->status);
L
Linus Torvalds 已提交
567

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

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

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

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

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

608
	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
S
Swen Schillig 已提交
609
		fc_host_permanent_port_name(shost) = bottom->wwpn;
610 611
		fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
	} else
S
Swen Schillig 已提交
612 613 614 615
		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 已提交
616

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

636
static int zfcp_fsf_sbal_check(struct zfcp_qdio *qdio)
S
Swen Schillig 已提交
637
{
638
	struct zfcp_qdio_queue *req_q = &qdio->req_q;
S
Swen Schillig 已提交
639

640
	spin_lock_bh(&qdio->req_q_lock);
641 642
	if (atomic_read(&req_q->count))
		return 1;
643
	spin_unlock_bh(&qdio->req_q_lock);
644 645 646
	return 0;
}

647
static int zfcp_fsf_req_sbal_get(struct zfcp_qdio *qdio)
648
{
649
	struct zfcp_adapter *adapter = qdio->adapter;
650
	long ret;
651

652 653 654
	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 已提交
655 656
	if (ret > 0)
		return 0;
657
	if (!ret) {
658
		atomic_inc(&qdio->req_q_full);
659 660 661
		/* assume hanging outbound queue, try queue recovery */
		zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
	}
662

663
	spin_lock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
664 665 666
	return -EIO;
}

667
static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
S
Swen Schillig 已提交
668 669
{
	struct zfcp_fsf_req *req;
670 671 672 673 674 675 676

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

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

S
Swen Schillig 已提交
679
	memset(req, 0, sizeof(*req));
680
	req->pool = pool;
S
Swen Schillig 已提交
681 682 683
	return req;
}

684
static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
S
Swen Schillig 已提交
685
{
686
	struct fsf_qtcb *qtcb;
S
Swen Schillig 已提交
687 688 689 690

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

S
Swen Schillig 已提交
693 694 695 696
	if (unlikely(!qtcb))
		return NULL;

	memset(qtcb, 0, sizeof(*qtcb));
697
	return qtcb;
S
Swen Schillig 已提交
698 699
}

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

S
Swen Schillig 已提交
708
	if (unlikely(!req))
709
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
710

S
Swen Schillig 已提交
711 712
	if (adapter->req_no == 0)
		adapter->req_no++;
L
Linus Torvalds 已提交
713

S
Swen Schillig 已提交
714 715
	INIT_LIST_HEAD(&req->list);
	init_timer(&req->timer);
716
	init_completion(&req->completion);
L
Linus Torvalds 已提交
717

S
Swen Schillig 已提交
718 719
	req->adapter = adapter;
	req->fsf_command = fsf_cmd;
720
	req->req_id = adapter->req_no;
721 722 723 724
	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 已提交
725

726
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
727 728 729
	sbale[0].addr = (void *) req->req_id;
	sbale[0].flags |= SBAL_FLAGS0_COMMAND;

730 731 732 733 734 735 736 737 738 739 740
	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);
		}

741
		req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no;
S
Swen Schillig 已提交
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
		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);
	}
758

S
Swen Schillig 已提交
759
	return req;
L
Linus Torvalds 已提交
760 761
}

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

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

776
	req->queue_req.qdio_outb_usage = atomic_read(&qdio->req_q.count);
S
Swen Schillig 已提交
777
	req->issued = get_clock();
778
	if (zfcp_qdio_send(qdio, &req->queue_req)) {
S
Swen Schillig 已提交
779
		del_timer(&req->timer);
780 781 782 783 784
		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);
785
		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req);
S
Swen Schillig 已提交
786 787 788 789
		return -EIO;
	}

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

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

811 812
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
813 814
		goto out;

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

822
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
823
	sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY;
824
	req->queue_req.sbale_curr = 2;
S
Swen Schillig 已提交
825

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

S
Swen Schillig 已提交
837 838 839
	retval = zfcp_fsf_req_send(req);
	if (retval)
		goto failed_req_send;
L
Linus Torvalds 已提交
840

S
Swen Schillig 已提交
841 842 843
	goto out;

failed_req_send:
844
	mempool_free(sr_buf, adapter->pool.status_read_data);
S
Swen Schillig 已提交
845 846
failed_buf:
	zfcp_fsf_req_free(req);
S
Swen Schillig 已提交
847
	zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
S
Swen Schillig 已提交
848
out:
849
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
850 851 852 853 854 855 856 857 858 859 860 861
	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 已提交
862
	case FSF_PORT_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
863
		if (fsq->word[0] == fsq->word[1]) {
864 865
			zfcp_erp_adapter_reopen(unit->port->adapter, 0,
						"fsafch1", req);
S
Swen Schillig 已提交
866
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
867 868 869
		}
		break;
	case FSF_LUN_HANDLE_NOT_VALID:
S
Swen Schillig 已提交
870
		if (fsq->word[0] == fsq->word[1]) {
871
			zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
S
Swen Schillig 已提交
872
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
873 874 875
		}
		break;
	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
S
Swen Schillig 已提交
876
		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
L
Linus Torvalds 已提交
877 878
		break;
	case FSF_PORT_BOXED:
879
		zfcp_erp_port_boxed(unit->port, "fsafch3", req);
S
Swen Schillig 已提交
880 881
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
882 883
		break;
	case FSF_LUN_BOXED:
884
		zfcp_erp_unit_boxed(unit, "fsafch4", req);
S
Swen Schillig 已提交
885 886
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
L
Linus Torvalds 已提交
887 888
                break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
S
Swen Schillig 已提交
889
		switch (fsq->word[0]) {
L
Linus Torvalds 已提交
890
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
891
			zfcp_fc_test_link(unit->port);
892
			/* fall through */
L
Linus Torvalds 已提交
893
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
894
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
895 896 897 898
			break;
		}
		break;
	case FSF_GOOD:
S
Swen Schillig 已提交
899
		req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
L
Linus Torvalds 已提交
900 901 902 903 904
		break;
	}
}

/**
S
Swen Schillig 已提交
905 906 907 908
 * 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 已提交
909 910
 */

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

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

S
Swen Schillig 已提交
928 929 930
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		goto out_error_free;
L
Linus Torvalds 已提交
931

932
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
933 934
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
935

S
Swen Schillig 已提交
936 937 938 939 940 941 942 943 944 945 946 947 948 949
	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:
950
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
951
	return req;
L
Linus Torvalds 已提交
952 953
}

S
Swen Schillig 已提交
954
static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
955
{
S
Swen Schillig 已提交
956 957 958
	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 已提交
959

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

S
Swen Schillig 已提交
962
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
L
Linus Torvalds 已提交
963 964 965 966
		goto skip_fsfstatus;

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

skip_fsfstatus:
S
Swen Schillig 已提交
1000
	if (send_ct->handler)
L
Linus Torvalds 已提交
1001
		send_ct->handler(send_ct->handler_data);
S
Swen Schillig 已提交
1002
}
L
Linus Torvalds 已提交
1003

1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
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;
}

1021 1022 1023 1024
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 已提交
1025
{
1026
	struct zfcp_adapter *adapter = req->adapter;
1027
	struct qdio_buffer_element *sbale = zfcp_qdio_sbale_req(adapter->qdio,
1028 1029
							       &req->queue_req);
	u32 feat = adapter->adapter_features;
S
Swen Schillig 已提交
1030 1031
	int bytes;

1032
	if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
1033
		if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
1034 1035
			return -EOPNOTSUPP;

1036 1037 1038 1039 1040 1041 1042
		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);
1043 1044 1045
		return 0;
	}

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

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

1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
	return 0;
}

static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
				 struct scatterlist *sg_req,
				 struct scatterlist *sg_resp,
				 int max_sbals)
{
	int ret;

	ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals);
	if (ret)
		return ret;

1075 1076 1077
	/* common settings for ct/gs and els requests */
	req->qtcb->bottom.support.service_class = FSF_CLASS_3;
	req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
1078
	zfcp_fsf_start_timer(req, (2 * R_A_TOV + 10) * HZ);
S
Swen Schillig 已提交
1079 1080

	return 0;
L
Linus Torvalds 已提交
1081 1082 1083
}

/**
S
Swen Schillig 已提交
1084 1085 1086
 * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS)
 * @ct: pointer to struct zfcp_send_ct with data for request
 * @pool: if non-null this mempool is used to allocate struct zfcp_fsf_req
L
Linus Torvalds 已提交
1087
 */
1088
int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool)
L
Linus Torvalds 已提交
1089
{
1090
	struct zfcp_wka_port *wka_port = ct->wka_port;
1091
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
S
Swen Schillig 已提交
1092 1093
	struct zfcp_fsf_req *req;
	int ret = -EIO;
L
Linus Torvalds 已提交
1094

1095 1096
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1097
		goto out;
L
Linus Torvalds 已提交
1098

1099
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_SEND_GENERIC, pool);
1100

1101
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1102 1103
		ret = PTR_ERR(req);
		goto out;
1104 1105
	}

1106
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1107 1108
	ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp,
				    FSF_MAX_SBALS_PER_REQ);
C
Christof Schmitt 已提交
1109
	if (ret)
L
Linus Torvalds 已提交
1110 1111
		goto failed_send;

S
Swen Schillig 已提交
1112
	req->handler = zfcp_fsf_send_ct_handler;
1113
	req->qtcb->header.port_handle = wka_port->handle;
S
Swen Schillig 已提交
1114 1115
	req->data = ct;

S
Swen Schillig 已提交
1116
	zfcp_dbf_san_ct_request(req);
L
Linus Torvalds 已提交
1117

S
Swen Schillig 已提交
1118 1119 1120
	ret = zfcp_fsf_req_send(req);
	if (ret)
		goto failed_send;
L
Linus Torvalds 已提交
1121

S
Swen Schillig 已提交
1122
	goto out;
L
Linus Torvalds 已提交
1123

S
Swen Schillig 已提交
1124 1125 1126
failed_send:
	zfcp_fsf_req_free(req);
out:
1127
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
1128
	return ret;
L
Linus Torvalds 已提交
1129 1130
}

S
Swen Schillig 已提交
1131
static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1132
{
S
Swen Schillig 已提交
1133 1134 1135
	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 已提交
1136

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

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

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

S
Swen Schillig 已提交
1183 1184 1185 1186 1187 1188 1189
/**
 * 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;
1190
	struct zfcp_qdio *qdio = els->adapter->qdio;
S
Swen Schillig 已提交
1191 1192
	int ret = -EIO;

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

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

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

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

S
Swen Schillig 已提交
1207 1208 1209
	if (ret)
		goto failed_send;

1210
	req->qtcb->bottom.support.d_id = els->d_id;
S
Swen Schillig 已提交
1211 1212 1213
	req->handler = zfcp_fsf_send_els_handler;
	req->data = els;

S
Swen Schillig 已提交
1214
	zfcp_dbf_san_els_request(req);
S
Swen Schillig 已提交
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224

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

	goto out;

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

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

1236 1237
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1238
		goto out;
1239

1240 1241
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA,
				  qdio->adapter->pool.erp_req);
1242

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

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

S
Swen Schillig 已提交
1253
	req->qtcb->bottom.config.feature_selection =
1254 1255
			FSF_FEATURE_CFDC |
			FSF_FEATURE_LUN_SHARING |
1256
			FSF_FEATURE_NOTIFICATION_LOST |
1257
			FSF_FEATURE_UPDATE_ALERT;
S
Swen Schillig 已提交
1258 1259 1260
	req->erp_action = erp_action;
	req->handler = zfcp_fsf_exchange_config_data_handler;
	erp_action->fsf_req = req;
L
Linus Torvalds 已提交
1261

1262
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1263
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1264
	if (retval) {
S
Swen Schillig 已提交
1265
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1266 1267
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1268
out:
1269
	spin_unlock_bh(&qdio->req_q_lock);
1270 1271
	return retval;
}
L
Linus Torvalds 已提交
1272

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

1280 1281
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
1282
		goto out_unlock;
S
Swen Schillig 已提交
1283

1284
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_CONFIG_DATA, NULL);
1285

1286
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1287
		retval = PTR_ERR(req);
1288
		goto out_unlock;
1289 1290
	}

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

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

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

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

S
Swen Schillig 已提交
1311
	zfcp_fsf_req_free(req);
1312
	return retval;
1313

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

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

1331
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1332
		return -EOPNOTSUPP;
L
Linus Torvalds 已提交
1333

1334 1335
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1336
		goto out;
1337

1338 1339
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA,
				  qdio->adapter->pool.erp_req);
1340

1341
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1342 1343
		retval = PTR_ERR(req);
		goto out;
1344 1345
	}

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

S
Swen Schillig 已提交
1351 1352 1353
	req->handler = zfcp_fsf_exchange_port_data_handler;
	req->erp_action = erp_action;
	erp_action->fsf_req = req;
1354

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

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

1379
	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
1380 1381
		return -EOPNOTSUPP;

1382 1383
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
1384
		goto out_unlock;
S
Swen Schillig 已提交
1385

1386
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_EXCHANGE_PORT_DATA, NULL);
1387

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

1393
	if (data)
S
Swen Schillig 已提交
1394
		req->data = data;
1395

1396
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1397 1398 1399
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

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

C
Christof Schmitt 已提交
1405
	if (!retval)
1406 1407
		wait_for_completion(&req->completion);

S
Swen Schillig 已提交
1408
	zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1409 1410

	return retval;
1411 1412

out_unlock:
1413
	spin_unlock_bh(&qdio->req_q_lock);
1414
	return retval;
L
Linus Torvalds 已提交
1415 1416
}

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

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

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

out:
	zfcp_port_put(port);
L
Linus Torvalds 已提交
1496 1497
}

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

1511 1512
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1513 1514
		goto out;

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

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

1523
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1524
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
L
Linus Torvalds 已提交
1525 1526 1527
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1528
	req->handler = zfcp_fsf_open_port_handler;
1529 1530
	req->qtcb->bottom.support.d_id = port->d_id;
	req->data = port;
S
Swen Schillig 已提交
1531 1532
	req->erp_action = erp_action;
	erp_action->fsf_req = req;
1533
	zfcp_port_get(port);
S
Swen Schillig 已提交
1534

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

S
Swen Schillig 已提交
1547
static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1548
{
S
Swen Schillig 已提交
1549
	struct zfcp_port *port = req->data;
L
Linus Torvalds 已提交
1550

S
Swen Schillig 已提交
1551
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1552
		return;
L
Linus Torvalds 已提交
1553

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

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

1581 1582
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
1583 1584
		goto out;

1585 1586
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
				  qdio->adapter->pool.erp_req);
1587

1588
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1589
		retval = PTR_ERR(req);
L
Linus Torvalds 已提交
1590
		goto out;
S
Swen Schillig 已提交
1591
	}
L
Linus Torvalds 已提交
1592

1593
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1594
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
L
Linus Torvalds 已提交
1595 1596 1597
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
1598 1599 1600 1601 1602 1603
	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;

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

1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
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);
1629
		/* fall through */
1630 1631
	case FSF_ADAPTER_STATUS_AVAILABLE:
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1632
		/* fall through */
1633 1634 1635 1636 1637
	case FSF_ACCESS_DENIED:
		wka_port->status = ZFCP_WKA_PORT_OFFLINE;
		break;
	case FSF_GOOD:
		wka_port->handle = header->port_handle;
1638 1639
		/* fall through */
	case FSF_PORT_ALREADY_OPEN:
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653
		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;
1654
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1655 1656 1657
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1658 1659
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
1660 1661
		goto out;

1662 1663
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_PORT_WITH_DID,
				  qdio->adapter->pool.erp_req);
1664

1665 1666 1667 1668 1669
	if (unlikely(IS_ERR(req))) {
		retval = PTR_ERR(req);
		goto out;
	}

1670
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1671
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683
	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:
1684
	spin_unlock_bh(&qdio->req_q_lock);
1685 1686 1687 1688 1689 1690 1691 1692 1693
	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;
1694
		zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req);
1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708
	}

	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;
1709
	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
1710 1711 1712
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1713 1714
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
1715 1716
		goto out;

1717 1718
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_PORT,
				  qdio->adapter->pool.erp_req);
1719

1720 1721 1722 1723 1724
	if (unlikely(IS_ERR(req))) {
		retval = PTR_ERR(req);
		goto out;
	}

1725
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1726
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738
	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:
1739
	spin_unlock_bh(&qdio->req_q_lock);
1740 1741 1742
	return retval;
}

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

S
Swen Schillig 已提交
1749
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1750
		return;
L
Linus Torvalds 已提交
1751 1752 1753

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

L
Linus Torvalds 已提交
1773 1774 1775 1776
		break;
	case FSF_ADAPTER_STATUS_AVAILABLE:
		switch (header->fsf_status_qual.word[0]) {
		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
S
Swen Schillig 已提交
1777
			/* fall through */
L
Linus Torvalds 已提交
1778
		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
S
Swen Schillig 已提交
1779
			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
1780 1781 1782 1783 1784 1785 1786 1787
			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);
1788 1789
		read_lock(&port->unit_list_lock);
		list_for_each_entry(unit, &port->unit_list, list)
S
Swen Schillig 已提交
1790 1791
			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
					  &unit->status);
1792
		read_unlock(&port->unit_list_lock);
L
Linus Torvalds 已提交
1793 1794 1795 1796
		break;
	}
}

S
Swen Schillig 已提交
1797 1798 1799 1800
/**
 * zfcp_fsf_close_physical_port - close physical port
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success
L
Linus Torvalds 已提交
1801
 */
S
Swen Schillig 已提交
1802
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1803
{
1804
	struct qdio_buffer_element *sbale;
1805
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
1806 1807 1808
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1809 1810
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
L
Linus Torvalds 已提交
1811 1812
		goto out;

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

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

1821
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1822
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
1823 1824
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
1825

S
Swen Schillig 已提交
1826 1827 1828 1829 1830 1831
	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;

1832
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
1833
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
1834
	if (retval) {
S
Swen Schillig 已提交
1835
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
1836 1837
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
1838
out:
1839
	spin_unlock_bh(&qdio->req_q_lock);
L
Linus Torvalds 已提交
1840 1841 1842
	return retval;
}

S
Swen Schillig 已提交
1843
static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
1844
{
S
Swen Schillig 已提交
1845 1846 1847 1848 1849 1850
	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;
1851
	int exclusive, readwrite;
L
Linus Torvalds 已提交
1852

S
Swen Schillig 已提交
1853
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
1854
		return;
L
Linus Torvalds 已提交
1855 1856

	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1857
			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
L
Linus Torvalds 已提交
1858 1859 1860 1861 1862 1863 1864
			  ZFCP_STATUS_UNIT_SHARED |
			  ZFCP_STATUS_UNIT_READONLY,
			  &unit->status);

	switch (header->fsf_status) {

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

	case FSF_GOOD:
		unit->handle = header->lun_handle;
		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
1921 1922 1923

		if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
		    (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
1924
		    !zfcp_ccw_priv_sch(adapter)) {
1925 1926 1927 1928 1929
			exclusive = (bottom->lun_access_info &
					FSF_UNIT_ACCESS_EXCLUSIVE);
			readwrite = (bottom->lun_access_info &
					FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);

L
Linus Torvalds 已提交
1930 1931 1932 1933 1934 1935 1936
			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 已提交
1937
				dev_info(&adapter->ccw_device->dev,
1938 1939
					 "SCSI device at LUN 0x%016Lx on port "
					 "0x%016Lx opened read-only\n",
1940 1941
					 (unsigned long long)unit->fcp_lun,
					 (unsigned long long)unit->port->wwpn);
L
Linus Torvalds 已提交
1942 1943 1944
        		}

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

S
Swen Schillig 已提交
1970 1971 1972 1973
/**
 * zfcp_fsf_open_unit - open unit
 * @erp_action: pointer to struct zfcp_erp_action
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
1974
 */
S
Swen Schillig 已提交
1975
int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
1976
{
1977
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
1978
	struct zfcp_adapter *adapter = erp_action->adapter;
1979
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
1980 1981 1982
	struct zfcp_fsf_req *req;
	int retval = -EIO;

1983 1984
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
L
Linus Torvalds 已提交
1985 1986
		goto out;

1987
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_OPEN_LUN,
1988
				  adapter->pool.erp_req);
1989

1990
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
1991 1992 1993 1994
		retval = PTR_ERR(req);
		goto out;
	}

1995
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
1996
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
L
Linus Torvalds 已提交
1997 1998 1999
        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
	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;

2010
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
2011
	retval = zfcp_fsf_req_send(req);
L
Linus Torvalds 已提交
2012
	if (retval) {
S
Swen Schillig 已提交
2013
		zfcp_fsf_req_free(req);
L
Linus Torvalds 已提交
2014 2015
		erp_action->fsf_req = NULL;
	}
S
Swen Schillig 已提交
2016
out:
2017
	spin_unlock_bh(&qdio->req_q_lock);
L
Linus Torvalds 已提交
2018 2019 2020
	return retval;
}

S
Swen Schillig 已提交
2021
static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
2022
{
S
Swen Schillig 已提交
2023
	struct zfcp_unit *unit = req->data;
L
Linus Torvalds 已提交
2024

S
Swen Schillig 已提交
2025
	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
2026
		return;
L
Linus Torvalds 已提交
2027

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

/**
S
Swen Schillig 已提交
2059 2060 2061
 * zfcp_fsf_close_unit - close zfcp unit
 * @erp_action: pointer to struct zfcp_unit
 * Returns: 0 on success, error otherwise
L
Linus Torvalds 已提交
2062
 */
S
Swen Schillig 已提交
2063
int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
L
Linus Torvalds 已提交
2064
{
2065
	struct qdio_buffer_element *sbale;
2066
	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
S
Swen Schillig 已提交
2067 2068
	struct zfcp_fsf_req *req;
	int retval = -EIO;
L
Linus Torvalds 已提交
2069

2070 2071
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
L
Linus Torvalds 已提交
2072
		goto out;
2073

2074 2075
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_CLOSE_LUN,
				  qdio->adapter->pool.erp_req);
2076

2077
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2078 2079 2080
		retval = PTR_ERR(req);
		goto out;
	}
L
Linus Torvalds 已提交
2081

2082
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
2083
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
2084
	sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
L
Linus Torvalds 已提交
2085 2086
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;

S
Swen Schillig 已提交
2087 2088 2089 2090 2091 2092
	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;
2093

2094
	zfcp_fsf_start_erp_timer(req);
S
Swen Schillig 已提交
2095 2096 2097 2098 2099 2100
	retval = zfcp_fsf_req_send(req);
	if (retval) {
		zfcp_fsf_req_free(req);
		erp_action->fsf_req = NULL;
	}
out:
2101
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
2102
	return retval;
L
Linus Torvalds 已提交
2103 2104
}

2105 2106 2107
static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
{
	lat_rec->sum += lat;
S
Swen Schillig 已提交
2108 2109
	lat_rec->min = min(lat_rec->min, lat);
	lat_rec->max = max(lat_rec->max, lat);
2110 2111
}

S
Swen Schillig 已提交
2112
static void zfcp_fsf_req_latency(struct zfcp_fsf_req *req)
2113 2114 2115
{
	struct fsf_qual_latency_info *lat_inf;
	struct latency_cont *lat;
S
Swen Schillig 已提交
2116
	struct zfcp_unit *unit = req->unit;
2117

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

S
Swen Schillig 已提交
2120
	switch (req->qtcb->bottom.io.data_direction) {
2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133
	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;
	}

2134
	spin_lock(&unit->latencies.lock);
2135 2136 2137
	zfcp_fsf_update_lat(&lat->channel, lat_inf->channel_lat);
	zfcp_fsf_update_lat(&lat->fabric, lat_inf->fabric_lat);
	lat->counter++;
2138
	spin_unlock(&unit->latencies.lock);
L
Linus Torvalds 已提交
2139 2140
}

S
Stefan Raspl 已提交
2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159
#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;
2160 2161
	trace.inb_usage = fsf_req->queue_req.qdio_inb_usage;
	trace.outb_usage = fsf_req->queue_req.qdio_outb_usage;
S
Stefan Raspl 已提交
2162 2163 2164 2165 2166 2167 2168 2169 2170

	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 已提交
2171
static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
2172
{
2173
	struct scsi_cmnd *scpnt;
L
Linus Torvalds 已提交
2174
	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
S
Swen Schillig 已提交
2175
	    &(req->qtcb->bottom.io.fcp_rsp);
L
Linus Torvalds 已提交
2176
	u32 sns_len;
2177
	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
L
Linus Torvalds 已提交
2178 2179
	unsigned long flags;

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

2182 2183 2184 2185 2186 2187
	scpnt = req->data;
	if (unlikely(!scpnt)) {
		read_unlock_irqrestore(&req->adapter->abort_lock, flags);
		return;
	}

S
Swen Schillig 已提交
2188
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) {
2189
		set_host_byte(scpnt, DID_SOFT_ERROR);
L
Linus Torvalds 已提交
2190 2191 2192
		goto skip_fsfstatus;
	}

S
Swen Schillig 已提交
2193
	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
2194
		set_host_byte(scpnt, DID_ERROR);
L
Linus Torvalds 已提交
2195 2196 2197
		goto skip_fsfstatus;
	}

2198
	set_msg_byte(scpnt, COMMAND_COMPLETE);
L
Linus Torvalds 已提交
2199 2200 2201

	scpnt->result |= fcp_rsp_iu->scsi_status;

S
Swen Schillig 已提交
2202 2203
	if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
		zfcp_fsf_req_latency(req);
2204

S
Stefan Raspl 已提交
2205 2206
	zfcp_fsf_trace_latency(req);

L
Linus Torvalds 已提交
2207
	if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
S
Swen Schillig 已提交
2208
		if (fcp_rsp_info[3] == RSP_CODE_GOOD)
2209
			set_host_byte(scpnt, DID_OK);
S
Swen Schillig 已提交
2210
		else {
2211
			set_host_byte(scpnt, DID_ERROR);
已提交
2212
			goto skip_fsfstatus;
L
Linus Torvalds 已提交
2213 2214 2215 2216
		}
	}

	if (unlikely(fcp_rsp_iu->validity.bits.fcp_sns_len_valid)) {
S
Swen Schillig 已提交
2217 2218
		sns_len = FSF_FCP_RSP_SIZE - sizeof(struct fcp_rsp_iu) +
			  fcp_rsp_iu->fcp_rsp_len;
L
Linus Torvalds 已提交
2219 2220 2221
		sns_len = min(sns_len, (u32) SCSI_SENSE_BUFFERSIZE);
		sns_len = min(sns_len, fcp_rsp_iu->fcp_sns_len);

2222
		memcpy(scpnt->sense_buffer,
L
Linus Torvalds 已提交
2223 2224 2225 2226
		       zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len);
	}

	if (unlikely(fcp_rsp_iu->validity.bits.fcp_resid_under)) {
2227 2228 2229
		scsi_set_resid(scpnt, fcp_rsp_iu->fcp_resid);
		if (scsi_bufflen(scpnt) - scsi_get_resid(scpnt) <
		    scpnt->underflow)
2230
			set_host_byte(scpnt, DID_ERROR);
L
Linus Torvalds 已提交
2231
	}
S
Swen Schillig 已提交
2232
skip_fsfstatus:
2233
	if (scpnt->result != 0)
S
Swen Schillig 已提交
2234
		zfcp_dbf_scsi_result("erro", 3, req->adapter->dbf, scpnt, req);
2235
	else if (scpnt->retries > 0)
S
Swen Schillig 已提交
2236
		zfcp_dbf_scsi_result("retr", 4, req->adapter->dbf, scpnt, req);
2237
	else
S
Swen Schillig 已提交
2238
		zfcp_dbf_scsi_result("norm", 6, req->adapter->dbf, scpnt, req);
L
Linus Torvalds 已提交
2239 2240 2241 2242 2243 2244 2245 2246 2247

	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 已提交
2248
	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
L
Linus Torvalds 已提交
2249 2250
}

S
Swen Schillig 已提交
2251
static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
L
Linus Torvalds 已提交
2252 2253
{
	struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *)
S
Swen Schillig 已提交
2254
	    &(req->qtcb->bottom.io.fcp_rsp);
2255
	char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1];
L
Linus Torvalds 已提交
2256

S
Swen Schillig 已提交
2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273
	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 已提交
2274 2275
		goto skip_fsfstatus;

S
Swen Schillig 已提交
2276 2277 2278
	switch (header->fsf_status) {
	case FSF_HANDLE_MISMATCH:
	case FSF_PORT_HANDLE_NOT_VALID:
2279
		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
S
Swen Schillig 已提交
2280 2281 2282 2283
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_FCPLUN_NOT_VALID:
	case FSF_LUN_HANDLE_NOT_VALID:
2284
		zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
S
Swen Schillig 已提交
2285
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2286
		break;
S
Swen Schillig 已提交
2287 2288
	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
		zfcp_fsf_class_not_supp(req);
L
Linus Torvalds 已提交
2289
		break;
S
Swen Schillig 已提交
2290 2291 2292 2293 2294
	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,
2295 2296
			"Incorrect direction %d, unit 0x%016Lx on port "
			"0x%016Lx closed\n",
S
Swen Schillig 已提交
2297
			req->qtcb->bottom.io.data_direction,
2298 2299
			(unsigned long long)unit->fcp_lun,
			(unsigned long long)unit->port->wwpn);
2300 2301
		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
					  req);
S
Swen Schillig 已提交
2302 2303 2304 2305
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_CMND_LENGTH_NOT_VALID:
		dev_err(&req->adapter->ccw_device->dev,
2306 2307
			"Incorrect CDB length %d, unit 0x%016Lx on "
			"port 0x%016Lx closed\n",
S
Swen Schillig 已提交
2308
			req->qtcb->bottom.io.fcp_cmnd_length,
2309 2310
			(unsigned long long)unit->fcp_lun,
			(unsigned long long)unit->port->wwpn);
2311 2312
		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
					  req);
S
Swen Schillig 已提交
2313 2314 2315
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
		break;
	case FSF_PORT_BOXED:
2316
		zfcp_erp_port_boxed(unit->port, "fssfch5", req);
S
Swen Schillig 已提交
2317 2318 2319 2320
		req->status |= ZFCP_STATUS_FSFREQ_ERROR |
			       ZFCP_STATUS_FSFREQ_RETRY;
		break;
	case FSF_LUN_BOXED:
2321
		zfcp_erp_unit_boxed(unit, "fssfch6", req);
S
Swen Schillig 已提交
2322 2323 2324 2325 2326 2327
		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)
2328
			zfcp_fc_test_link(unit->port);
S
Swen Schillig 已提交
2329
		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
L
Linus Torvalds 已提交
2330 2331
		break;
	}
S
Swen Schillig 已提交
2332 2333 2334 2335 2336 2337 2338 2339
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 已提交
2340 2341
}

2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355
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 已提交
2356 2357 2358 2359
/**
 * 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 已提交
2360
 */
2361 2362
int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
				   struct scsi_cmnd *scsi_cmnd)
L
Linus Torvalds 已提交
2363
{
S
Swen Schillig 已提交
2364 2365
	struct zfcp_fsf_req *req;
	struct fcp_cmnd_iu *fcp_cmnd_iu;
2366
	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
S
Swen Schillig 已提交
2367
	int real_bytes, retval = -EIO;
2368
	struct zfcp_adapter *adapter = unit->port->adapter;
2369
	struct zfcp_qdio *qdio = adapter->qdio;
L
Linus Torvalds 已提交
2370

S
Swen Schillig 已提交
2371 2372 2373
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return -EBUSY;
L
Linus Torvalds 已提交
2374

2375 2376 2377
	spin_lock(&qdio->req_q_lock);
	if (atomic_read(&qdio->req_q.count) <= 0) {
		atomic_inc(&qdio->req_q_full);
S
Swen Schillig 已提交
2378
		goto out;
2379
	}
2380

2381
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
2382
				  adapter->pool.scsi_req);
2383

2384
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2385 2386 2387 2388
		retval = PTR_ERR(req);
		goto out;
	}

2389
	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
S
Swen Schillig 已提交
2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
	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 已提交
2411
		break;
S
Swen Schillig 已提交
2412 2413 2414 2415 2416 2417 2418 2419
	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 已提交
2420
		break;
S
Swen Schillig 已提交
2421 2422
	case DMA_BIDIRECTIONAL:
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2423 2424
	}

S
Swen Schillig 已提交
2425 2426 2427 2428 2429 2430
	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 已提交
2431

S
Swen Schillig 已提交
2432 2433 2434
	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 已提交
2435

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

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

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

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

S
Swen Schillig 已提交
2459 2460 2461
	retval = zfcp_fsf_req_send(req);
	if (unlikely(retval))
		goto failed_scsi_cmnd;
L
Linus Torvalds 已提交
2462

S
Swen Schillig 已提交
2463
	goto out;
L
Linus Torvalds 已提交
2464

S
Swen Schillig 已提交
2465 2466 2467 2468 2469
failed_scsi_cmnd:
	zfcp_unit_put(unit);
	zfcp_fsf_req_free(req);
	scsi_cmnd->host_scribble = NULL;
out:
2470
	spin_unlock(&qdio->req_q_lock);
S
Swen Schillig 已提交
2471
	return retval;
L
Linus Torvalds 已提交
2472 2473 2474
}

/**
S
Swen Schillig 已提交
2475 2476 2477 2478
 * 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 已提交
2479
 */
2480
struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
L
Linus Torvalds 已提交
2481
{
2482
	struct qdio_buffer_element *sbale;
S
Swen Schillig 已提交
2483 2484
	struct zfcp_fsf_req *req = NULL;
	struct fcp_cmnd_iu *fcp_cmnd_iu;
2485
	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
L
Linus Torvalds 已提交
2486

S
Swen Schillig 已提交
2487 2488 2489
	if (unlikely(!(atomic_read(&unit->status) &
		       ZFCP_STATUS_COMMON_UNBLOCKED)))
		return NULL;
L
Linus Torvalds 已提交
2490

2491 2492
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
2493
		goto out;
2494

2495 2496
	req = zfcp_fsf_req_create(qdio, FSF_QTCB_FCP_CMND,
				  qdio->adapter->pool.scsi_req);
2497

2498 2499
	if (IS_ERR(req)) {
		req = NULL;
S
Swen Schillig 已提交
2500
		goto out;
2501
	}
L
Linus Torvalds 已提交
2502

S
Swen Schillig 已提交
2503 2504 2505 2506 2507 2508 2509 2510
	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) +
2511
						sizeof(u32);
S
Swen Schillig 已提交
2512

2513
	sbale = zfcp_qdio_sbale_req(qdio, &req->queue_req);
S
Swen Schillig 已提交
2514 2515
	sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
	sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
L
Linus Torvalds 已提交
2516

S
Swen Schillig 已提交
2517 2518 2519
	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 已提交
2520

S
Swen Schillig 已提交
2521 2522 2523
	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
	if (!zfcp_fsf_req_send(req))
		goto out;
L
Linus Torvalds 已提交
2524

S
Swen Schillig 已提交
2525 2526 2527
	zfcp_fsf_req_free(req);
	req = NULL;
out:
2528
	spin_unlock_bh(&qdio->req_q_lock);
S
Swen Schillig 已提交
2529 2530
	return req;
}
L
Linus Torvalds 已提交
2531

S
Swen Schillig 已提交
2532 2533
static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
{
L
Linus Torvalds 已提交
2534 2535
}

S
Swen Schillig 已提交
2536 2537 2538 2539 2540
/**
 * 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 已提交
2541
 */
S
Swen Schillig 已提交
2542 2543
struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
					   struct zfcp_fsf_cfdc *fsf_cfdc)
L
Linus Torvalds 已提交
2544
{
2545
	struct qdio_buffer_element *sbale;
2546
	struct zfcp_qdio *qdio = adapter->qdio;
S
Swen Schillig 已提交
2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563
	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 已提交
2564

2565 2566
	spin_lock_bh(&qdio->req_q_lock);
	if (zfcp_fsf_req_sbal_get(qdio))
S
Swen Schillig 已提交
2567
		goto out;
L
Linus Torvalds 已提交
2568

2569
	req = zfcp_fsf_req_create(qdio, fsf_cfdc->command, NULL);
2570
	if (IS_ERR(req)) {
S
Swen Schillig 已提交
2571 2572 2573
		retval = -EPERM;
		goto out;
	}
L
Linus Torvalds 已提交
2574

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

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

S
Swen Schillig 已提交
2580 2581 2582
	bottom = &req->qtcb->bottom.support;
	bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE;
	bottom->option = fsf_cfdc->option;
2583

2584 2585 2586
	bytes = zfcp_qdio_sbals_from_sg(qdio, &req->queue_req,
					direction, fsf_cfdc->sg,
					FSF_MAX_SBALS_PER_REQ);
S
Swen Schillig 已提交
2587 2588 2589 2590
	if (bytes != ZFCP_CFDC_MAX_SIZE) {
		zfcp_fsf_req_free(req);
		goto out;
	}
L
Linus Torvalds 已提交
2591

S
Swen Schillig 已提交
2592 2593 2594
	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
	retval = zfcp_fsf_req_send(req);
out:
2595
	spin_unlock_bh(&qdio->req_q_lock);
2596

S
Swen Schillig 已提交
2597
	if (!retval) {
2598
		wait_for_completion(&req->completion);
S
Swen Schillig 已提交
2599
		return req;
L
Linus Torvalds 已提交
2600
	}
S
Swen Schillig 已提交
2601
	return ERR_PTR(retval);
L
Linus Torvalds 已提交
2602
}
2603 2604 2605 2606 2607 2608

/**
 * 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
 */
2609
void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
2610
{
2611 2612
	struct zfcp_adapter *adapter = qdio->adapter;
	struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx];
2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635
	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);

2636 2637
		fsf_req->queue_req.sbal_response = sbal_idx;
		fsf_req->queue_req.qdio_inb_usage =
2638
			atomic_read(&qdio->resp_q.count);
2639 2640 2641 2642 2643 2644
		zfcp_fsf_req_complete(fsf_req);

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