PageRenderTime 335ms CodeModel.GetById 31ms app.highlight 248ms RepoModel.GetById 1ms app.codeStats 2ms

/drivers/scsi/ibmvscsi/ibmvfc.c

https://bitbucket.org/wisechild/galaxy-nexus
C | 4976 lines | 3450 code | 564 blank | 962 comment | 501 complexity | ad5922a1a8e04238825d56a83cc050d6 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * ibmvfc.c -- driver for IBM Power Virtual Fibre Channel Adapter
   3 *
   4 * Written By: Brian King <brking@linux.vnet.ibm.com>, IBM Corporation
   5 *
   6 * Copyright (C) IBM Corporation, 2008
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 *
  22 */
  23
  24#include <linux/module.h>
  25#include <linux/moduleparam.h>
  26#include <linux/dma-mapping.h>
  27#include <linux/dmapool.h>
  28#include <linux/delay.h>
  29#include <linux/interrupt.h>
  30#include <linux/kthread.h>
  31#include <linux/slab.h>
  32#include <linux/of.h>
  33#include <linux/pm.h>
  34#include <linux/stringify.h>
  35#include <asm/firmware.h>
  36#include <asm/irq.h>
  37#include <asm/vio.h>
  38#include <scsi/scsi.h>
  39#include <scsi/scsi_cmnd.h>
  40#include <scsi/scsi_host.h>
  41#include <scsi/scsi_device.h>
  42#include <scsi/scsi_tcq.h>
  43#include <scsi/scsi_transport_fc.h>
  44#include <scsi/scsi_bsg_fc.h>
  45#include "ibmvfc.h"
  46
  47static unsigned int init_timeout = IBMVFC_INIT_TIMEOUT;
  48static unsigned int default_timeout = IBMVFC_DEFAULT_TIMEOUT;
  49static unsigned int max_lun = IBMVFC_MAX_LUN;
  50static unsigned int max_targets = IBMVFC_MAX_TARGETS;
  51static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
  52static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
  53static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
  54static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL;
  55static LIST_HEAD(ibmvfc_head);
  56static DEFINE_SPINLOCK(ibmvfc_driver_lock);
  57static struct scsi_transport_template *ibmvfc_transport_template;
  58
  59MODULE_DESCRIPTION("IBM Virtual Fibre Channel Driver");
  60MODULE_AUTHOR("Brian King <brking@linux.vnet.ibm.com>");
  61MODULE_LICENSE("GPL");
  62MODULE_VERSION(IBMVFC_DRIVER_VERSION);
  63
  64module_param_named(init_timeout, init_timeout, uint, S_IRUGO | S_IWUSR);
  65MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds. "
  66		 "[Default=" __stringify(IBMVFC_INIT_TIMEOUT) "]");
  67module_param_named(default_timeout, default_timeout, uint, S_IRUGO | S_IWUSR);
  68MODULE_PARM_DESC(default_timeout,
  69		 "Default timeout in seconds for initialization and EH commands. "
  70		 "[Default=" __stringify(IBMVFC_DEFAULT_TIMEOUT) "]");
  71module_param_named(max_requests, max_requests, uint, S_IRUGO);
  72MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter. "
  73		 "[Default=" __stringify(IBMVFC_MAX_REQUESTS_DEFAULT) "]");
  74module_param_named(max_lun, max_lun, uint, S_IRUGO);
  75MODULE_PARM_DESC(max_lun, "Maximum allowed LUN. "
  76		 "[Default=" __stringify(IBMVFC_MAX_LUN) "]");
  77module_param_named(max_targets, max_targets, uint, S_IRUGO);
  78MODULE_PARM_DESC(max_targets, "Maximum allowed targets. "
  79		 "[Default=" __stringify(IBMVFC_MAX_TARGETS) "]");
  80module_param_named(disc_threads, disc_threads, uint, S_IRUGO);
  81MODULE_PARM_DESC(disc_threads, "Number of device discovery threads to use. "
  82		 "[Default=" __stringify(IBMVFC_MAX_DISC_THREADS) "]");
  83module_param_named(debug, ibmvfc_debug, uint, S_IRUGO | S_IWUSR);
  84MODULE_PARM_DESC(debug, "Enable driver debug information. "
  85		 "[Default=" __stringify(IBMVFC_DEBUG) "]");
  86module_param_named(log_level, log_level, uint, 0);
  87MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. "
  88		 "[Default=" __stringify(IBMVFC_DEFAULT_LOG_LEVEL) "]");
  89
  90static const struct {
  91	u16 status;
  92	u16 error;
  93	u8 result;
  94	u8 retry;
  95	int log;
  96	char *name;
  97} cmd_status [] = {
  98	{ IBMVFC_FABRIC_MAPPED, IBMVFC_UNABLE_TO_ESTABLISH, DID_ERROR, 1, 1, "unable to establish" },
  99	{ IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_FAULT, DID_OK, 1, 0, "transport fault" },
 100	{ IBMVFC_FABRIC_MAPPED, IBMVFC_CMD_TIMEOUT, DID_TIME_OUT, 1, 1, "command timeout" },
 101	{ IBMVFC_FABRIC_MAPPED, IBMVFC_ENETDOWN, DID_TRANSPORT_DISRUPTED, 1, 1, "network down" },
 102	{ IBMVFC_FABRIC_MAPPED, IBMVFC_HW_FAILURE, DID_ERROR, 1, 1, "hardware failure" },
 103	{ IBMVFC_FABRIC_MAPPED, IBMVFC_LINK_DOWN_ERR, DID_REQUEUE, 0, 0, "link down" },
 104	{ IBMVFC_FABRIC_MAPPED, IBMVFC_LINK_DEAD_ERR, DID_ERROR, 0, 0, "link dead" },
 105	{ IBMVFC_FABRIC_MAPPED, IBMVFC_UNABLE_TO_REGISTER, DID_ERROR, 1, 1, "unable to register" },
 106	{ IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_BUSY, DID_BUS_BUSY, 1, 0, "transport busy" },
 107	{ IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_DEAD, DID_ERROR, 0, 1, "transport dead" },
 108	{ IBMVFC_FABRIC_MAPPED, IBMVFC_CONFIG_ERROR, DID_ERROR, 1, 1, "configuration error" },
 109	{ IBMVFC_FABRIC_MAPPED, IBMVFC_NAME_SERVER_FAIL, DID_ERROR, 1, 1, "name server failure" },
 110	{ IBMVFC_FABRIC_MAPPED, IBMVFC_LINK_HALTED, DID_REQUEUE, 1, 0, "link halted" },
 111	{ IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_GENERAL, DID_OK, 1, 0, "general transport error" },
 112
 113	{ IBMVFC_VIOS_FAILURE, IBMVFC_CRQ_FAILURE, DID_REQUEUE, 1, 1, "CRQ failure" },
 114	{ IBMVFC_VIOS_FAILURE, IBMVFC_SW_FAILURE, DID_ERROR, 0, 1, "software failure" },
 115	{ IBMVFC_VIOS_FAILURE, IBMVFC_INVALID_PARAMETER, DID_ERROR, 0, 1, "invalid parameter" },
 116	{ IBMVFC_VIOS_FAILURE, IBMVFC_MISSING_PARAMETER, DID_ERROR, 0, 1, "missing parameter" },
 117	{ IBMVFC_VIOS_FAILURE, IBMVFC_HOST_IO_BUS, DID_ERROR, 1, 1, "host I/O bus failure" },
 118	{ IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED, DID_ERROR, 0, 1, "transaction cancelled" },
 119	{ IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED_IMPLICIT, DID_ERROR, 0, 1, "transaction cancelled implicit" },
 120	{ IBMVFC_VIOS_FAILURE, IBMVFC_INSUFFICIENT_RESOURCE, DID_REQUEUE, 1, 1, "insufficient resources" },
 121	{ IBMVFC_VIOS_FAILURE, IBMVFC_PLOGI_REQUIRED, DID_ERROR, 0, 1, "port login required" },
 122	{ IBMVFC_VIOS_FAILURE, IBMVFC_COMMAND_FAILED, DID_ERROR, 1, 1, "command failed" },
 123
 124	{ IBMVFC_FC_FAILURE, IBMVFC_INVALID_ELS_CMD_CODE, DID_ERROR, 0, 1, "invalid ELS command code" },
 125	{ IBMVFC_FC_FAILURE, IBMVFC_INVALID_VERSION, DID_ERROR, 0, 1, "invalid version level" },
 126	{ IBMVFC_FC_FAILURE, IBMVFC_LOGICAL_ERROR, DID_ERROR, 1, 1, "logical error" },
 127	{ IBMVFC_FC_FAILURE, IBMVFC_INVALID_CT_IU_SIZE, DID_ERROR, 0, 1, "invalid CT_IU size" },
 128	{ IBMVFC_FC_FAILURE, IBMVFC_LOGICAL_BUSY, DID_REQUEUE, 1, 0, "logical busy" },
 129	{ IBMVFC_FC_FAILURE, IBMVFC_PROTOCOL_ERROR, DID_ERROR, 1, 1, "protocol error" },
 130	{ IBMVFC_FC_FAILURE, IBMVFC_UNABLE_TO_PERFORM_REQ, DID_ERROR, 1, 1, "unable to perform request" },
 131	{ IBMVFC_FC_FAILURE, IBMVFC_CMD_NOT_SUPPORTED, DID_ERROR, 0, 0, "command not supported" },
 132	{ IBMVFC_FC_FAILURE, IBMVFC_SERVER_NOT_AVAIL, DID_ERROR, 0, 1, "server not available" },
 133	{ IBMVFC_FC_FAILURE, IBMVFC_CMD_IN_PROGRESS, DID_ERROR, 0, 1, "command already in progress" },
 134	{ IBMVFC_FC_FAILURE, IBMVFC_VENDOR_SPECIFIC, DID_ERROR, 1, 1, "vendor specific" },
 135
 136	{ IBMVFC_FC_SCSI_ERROR, 0, DID_OK, 1, 0, "SCSI error" },
 137};
 138
 139static void ibmvfc_npiv_login(struct ibmvfc_host *);
 140static void ibmvfc_tgt_send_prli(struct ibmvfc_target *);
 141static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *);
 142static void ibmvfc_tgt_query_target(struct ibmvfc_target *);
 143static void ibmvfc_npiv_logout(struct ibmvfc_host *);
 144
 145static const char *unknown_error = "unknown error";
 146
 147#ifdef CONFIG_SCSI_IBMVFC_TRACE
 148/**
 149 * ibmvfc_trc_start - Log a start trace entry
 150 * @evt:		ibmvfc event struct
 151 *
 152 **/
 153static void ibmvfc_trc_start(struct ibmvfc_event *evt)
 154{
 155	struct ibmvfc_host *vhost = evt->vhost;
 156	struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd;
 157	struct ibmvfc_mad_common *mad = &evt->iu.mad_common;
 158	struct ibmvfc_trace_entry *entry;
 159
 160	entry = &vhost->trace[vhost->trace_index++];
 161	entry->evt = evt;
 162	entry->time = jiffies;
 163	entry->fmt = evt->crq.format;
 164	entry->type = IBMVFC_TRC_START;
 165
 166	switch (entry->fmt) {
 167	case IBMVFC_CMD_FORMAT:
 168		entry->op_code = vfc_cmd->iu.cdb[0];
 169		entry->scsi_id = vfc_cmd->tgt_scsi_id;
 170		entry->lun = scsilun_to_int(&vfc_cmd->iu.lun);
 171		entry->tmf_flags = vfc_cmd->iu.tmf_flags;
 172		entry->u.start.xfer_len = vfc_cmd->iu.xfer_len;
 173		break;
 174	case IBMVFC_MAD_FORMAT:
 175		entry->op_code = mad->opcode;
 176		break;
 177	default:
 178		break;
 179	};
 180}
 181
 182/**
 183 * ibmvfc_trc_end - Log an end trace entry
 184 * @evt:		ibmvfc event struct
 185 *
 186 **/
 187static void ibmvfc_trc_end(struct ibmvfc_event *evt)
 188{
 189	struct ibmvfc_host *vhost = evt->vhost;
 190	struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
 191	struct ibmvfc_mad_common *mad = &evt->xfer_iu->mad_common;
 192	struct ibmvfc_trace_entry *entry = &vhost->trace[vhost->trace_index++];
 193
 194	entry->evt = evt;
 195	entry->time = jiffies;
 196	entry->fmt = evt->crq.format;
 197	entry->type = IBMVFC_TRC_END;
 198
 199	switch (entry->fmt) {
 200	case IBMVFC_CMD_FORMAT:
 201		entry->op_code = vfc_cmd->iu.cdb[0];
 202		entry->scsi_id = vfc_cmd->tgt_scsi_id;
 203		entry->lun = scsilun_to_int(&vfc_cmd->iu.lun);
 204		entry->tmf_flags = vfc_cmd->iu.tmf_flags;
 205		entry->u.end.status = vfc_cmd->status;
 206		entry->u.end.error = vfc_cmd->error;
 207		entry->u.end.fcp_rsp_flags = vfc_cmd->rsp.flags;
 208		entry->u.end.rsp_code = vfc_cmd->rsp.data.info.rsp_code;
 209		entry->u.end.scsi_status = vfc_cmd->rsp.scsi_status;
 210		break;
 211	case IBMVFC_MAD_FORMAT:
 212		entry->op_code = mad->opcode;
 213		entry->u.end.status = mad->status;
 214		break;
 215	default:
 216		break;
 217
 218	};
 219}
 220
 221#else
 222#define ibmvfc_trc_start(evt) do { } while (0)
 223#define ibmvfc_trc_end(evt) do { } while (0)
 224#endif
 225
 226/**
 227 * ibmvfc_get_err_index - Find the index into cmd_status for the fcp response
 228 * @status:		status / error class
 229 * @error:		error
 230 *
 231 * Return value:
 232 *	index into cmd_status / -EINVAL on failure
 233 **/
 234static int ibmvfc_get_err_index(u16 status, u16 error)
 235{
 236	int i;
 237
 238	for (i = 0; i < ARRAY_SIZE(cmd_status); i++)
 239		if ((cmd_status[i].status & status) == cmd_status[i].status &&
 240		    cmd_status[i].error == error)
 241			return i;
 242
 243	return -EINVAL;
 244}
 245
 246/**
 247 * ibmvfc_get_cmd_error - Find the error description for the fcp response
 248 * @status:		status / error class
 249 * @error:		error
 250 *
 251 * Return value:
 252 *	error description string
 253 **/
 254static const char *ibmvfc_get_cmd_error(u16 status, u16 error)
 255{
 256	int rc = ibmvfc_get_err_index(status, error);
 257	if (rc >= 0)
 258		return cmd_status[rc].name;
 259	return unknown_error;
 260}
 261
 262/**
 263 * ibmvfc_get_err_result - Find the scsi status to return for the fcp response
 264 * @vfc_cmd:	ibmvfc command struct
 265 *
 266 * Return value:
 267 *	SCSI result value to return for completed command
 268 **/
 269static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd)
 270{
 271	int err;
 272	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
 273	int fc_rsp_len = rsp->fcp_rsp_len;
 274
 275	if ((rsp->flags & FCP_RSP_LEN_VALID) &&
 276	    ((fc_rsp_len && fc_rsp_len != 4 && fc_rsp_len != 8) ||
 277	     rsp->data.info.rsp_code))
 278		return DID_ERROR << 16;
 279
 280	err = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
 281	if (err >= 0)
 282		return rsp->scsi_status | (cmd_status[err].result << 16);
 283	return rsp->scsi_status | (DID_ERROR << 16);
 284}
 285
 286/**
 287 * ibmvfc_retry_cmd - Determine if error status is retryable
 288 * @status:		status / error class
 289 * @error:		error
 290 *
 291 * Return value:
 292 *	1 if error should be retried / 0 if it should not
 293 **/
 294static int ibmvfc_retry_cmd(u16 status, u16 error)
 295{
 296	int rc = ibmvfc_get_err_index(status, error);
 297
 298	if (rc >= 0)
 299		return cmd_status[rc].retry;
 300	return 1;
 301}
 302
 303static const char *unknown_fc_explain = "unknown fc explain";
 304
 305static const struct {
 306	u16 fc_explain;
 307	char *name;
 308} ls_explain [] = {
 309	{ 0x00, "no additional explanation" },
 310	{ 0x01, "service parameter error - options" },
 311	{ 0x03, "service parameter error - initiator control" },
 312	{ 0x05, "service parameter error - recipient control" },
 313	{ 0x07, "service parameter error - received data field size" },
 314	{ 0x09, "service parameter error - concurrent seq" },
 315	{ 0x0B, "service parameter error - credit" },
 316	{ 0x0D, "invalid N_Port/F_Port_Name" },
 317	{ 0x0E, "invalid node/Fabric Name" },
 318	{ 0x0F, "invalid common service parameters" },
 319	{ 0x11, "invalid association header" },
 320	{ 0x13, "association header required" },
 321	{ 0x15, "invalid originator S_ID" },
 322	{ 0x17, "invalid OX_ID-RX-ID combination" },
 323	{ 0x19, "command (request) already in progress" },
 324	{ 0x1E, "N_Port Login requested" },
 325	{ 0x1F, "Invalid N_Port_ID" },
 326};
 327
 328static const struct {
 329	u16 fc_explain;
 330	char *name;
 331} gs_explain [] = {
 332	{ 0x00, "no additional explanation" },
 333	{ 0x01, "port identifier not registered" },
 334	{ 0x02, "port name not registered" },
 335	{ 0x03, "node name not registered" },
 336	{ 0x04, "class of service not registered" },
 337	{ 0x06, "initial process associator not registered" },
 338	{ 0x07, "FC-4 TYPEs not registered" },
 339	{ 0x08, "symbolic port name not registered" },
 340	{ 0x09, "symbolic node name not registered" },
 341	{ 0x0A, "port type not registered" },
 342	{ 0xF0, "authorization exception" },
 343	{ 0xF1, "authentication exception" },
 344	{ 0xF2, "data base full" },
 345	{ 0xF3, "data base empty" },
 346	{ 0xF4, "processing request" },
 347	{ 0xF5, "unable to verify connection" },
 348	{ 0xF6, "devices not in a common zone" },
 349};
 350
 351/**
 352 * ibmvfc_get_ls_explain - Return the FC Explain description text
 353 * @status:	FC Explain status
 354 *
 355 * Returns:
 356 *	error string
 357 **/
 358static const char *ibmvfc_get_ls_explain(u16 status)
 359{
 360	int i;
 361
 362	for (i = 0; i < ARRAY_SIZE(ls_explain); i++)
 363		if (ls_explain[i].fc_explain == status)
 364			return ls_explain[i].name;
 365
 366	return unknown_fc_explain;
 367}
 368
 369/**
 370 * ibmvfc_get_gs_explain - Return the FC Explain description text
 371 * @status:	FC Explain status
 372 *
 373 * Returns:
 374 *	error string
 375 **/
 376static const char *ibmvfc_get_gs_explain(u16 status)
 377{
 378	int i;
 379
 380	for (i = 0; i < ARRAY_SIZE(gs_explain); i++)
 381		if (gs_explain[i].fc_explain == status)
 382			return gs_explain[i].name;
 383
 384	return unknown_fc_explain;
 385}
 386
 387static const struct {
 388	enum ibmvfc_fc_type fc_type;
 389	char *name;
 390} fc_type [] = {
 391	{ IBMVFC_FABRIC_REJECT, "fabric reject" },
 392	{ IBMVFC_PORT_REJECT, "port reject" },
 393	{ IBMVFC_LS_REJECT, "ELS reject" },
 394	{ IBMVFC_FABRIC_BUSY, "fabric busy" },
 395	{ IBMVFC_PORT_BUSY, "port busy" },
 396	{ IBMVFC_BASIC_REJECT, "basic reject" },
 397};
 398
 399static const char *unknown_fc_type = "unknown fc type";
 400
 401/**
 402 * ibmvfc_get_fc_type - Return the FC Type description text
 403 * @status:	FC Type error status
 404 *
 405 * Returns:
 406 *	error string
 407 **/
 408static const char *ibmvfc_get_fc_type(u16 status)
 409{
 410	int i;
 411
 412	for (i = 0; i < ARRAY_SIZE(fc_type); i++)
 413		if (fc_type[i].fc_type == status)
 414			return fc_type[i].name;
 415
 416	return unknown_fc_type;
 417}
 418
 419/**
 420 * ibmvfc_set_tgt_action - Set the next init action for the target
 421 * @tgt:		ibmvfc target struct
 422 * @action:		action to perform
 423 *
 424 **/
 425static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt,
 426				  enum ibmvfc_target_action action)
 427{
 428	switch (tgt->action) {
 429	case IBMVFC_TGT_ACTION_DEL_RPORT:
 430		if (action == IBMVFC_TGT_ACTION_DELETED_RPORT)
 431			tgt->action = action;
 432	case IBMVFC_TGT_ACTION_DELETED_RPORT:
 433		break;
 434	default:
 435		if (action == IBMVFC_TGT_ACTION_DEL_RPORT)
 436			tgt->add_rport = 0;
 437		tgt->action = action;
 438		break;
 439	}
 440}
 441
 442/**
 443 * ibmvfc_set_host_state - Set the state for the host
 444 * @vhost:		ibmvfc host struct
 445 * @state:		state to set host to
 446 *
 447 * Returns:
 448 *	0 if state changed / non-zero if not changed
 449 **/
 450static int ibmvfc_set_host_state(struct ibmvfc_host *vhost,
 451				  enum ibmvfc_host_state state)
 452{
 453	int rc = 0;
 454
 455	switch (vhost->state) {
 456	case IBMVFC_HOST_OFFLINE:
 457		rc = -EINVAL;
 458		break;
 459	default:
 460		vhost->state = state;
 461		break;
 462	};
 463
 464	return rc;
 465}
 466
 467/**
 468 * ibmvfc_set_host_action - Set the next init action for the host
 469 * @vhost:		ibmvfc host struct
 470 * @action:		action to perform
 471 *
 472 **/
 473static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
 474				   enum ibmvfc_host_action action)
 475{
 476	switch (action) {
 477	case IBMVFC_HOST_ACTION_ALLOC_TGTS:
 478		if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT)
 479			vhost->action = action;
 480		break;
 481	case IBMVFC_HOST_ACTION_LOGO_WAIT:
 482		if (vhost->action == IBMVFC_HOST_ACTION_LOGO)
 483			vhost->action = action;
 484		break;
 485	case IBMVFC_HOST_ACTION_INIT_WAIT:
 486		if (vhost->action == IBMVFC_HOST_ACTION_INIT)
 487			vhost->action = action;
 488		break;
 489	case IBMVFC_HOST_ACTION_QUERY:
 490		switch (vhost->action) {
 491		case IBMVFC_HOST_ACTION_INIT_WAIT:
 492		case IBMVFC_HOST_ACTION_NONE:
 493		case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
 494			vhost->action = action;
 495			break;
 496		default:
 497			break;
 498		};
 499		break;
 500	case IBMVFC_HOST_ACTION_TGT_INIT:
 501		if (vhost->action == IBMVFC_HOST_ACTION_ALLOC_TGTS)
 502			vhost->action = action;
 503		break;
 504	case IBMVFC_HOST_ACTION_INIT:
 505	case IBMVFC_HOST_ACTION_TGT_DEL:
 506		switch (vhost->action) {
 507		case IBMVFC_HOST_ACTION_RESET:
 508		case IBMVFC_HOST_ACTION_REENABLE:
 509			break;
 510		default:
 511			vhost->action = action;
 512			break;
 513		};
 514		break;
 515	case IBMVFC_HOST_ACTION_LOGO:
 516	case IBMVFC_HOST_ACTION_QUERY_TGTS:
 517	case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
 518	case IBMVFC_HOST_ACTION_NONE:
 519	case IBMVFC_HOST_ACTION_RESET:
 520	case IBMVFC_HOST_ACTION_REENABLE:
 521	default:
 522		vhost->action = action;
 523		break;
 524	};
 525}
 526
 527/**
 528 * ibmvfc_reinit_host - Re-start host initialization (no NPIV Login)
 529 * @vhost:		ibmvfc host struct
 530 *
 531 * Return value:
 532 *	nothing
 533 **/
 534static void ibmvfc_reinit_host(struct ibmvfc_host *vhost)
 535{
 536	if (vhost->action == IBMVFC_HOST_ACTION_NONE) {
 537		if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
 538			scsi_block_requests(vhost->host);
 539			ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
 540		}
 541	} else
 542		vhost->reinit = 1;
 543
 544	wake_up(&vhost->work_wait_q);
 545}
 546
 547/**
 548 * ibmvfc_link_down - Handle a link down event from the adapter
 549 * @vhost:	ibmvfc host struct
 550 * @state:	ibmvfc host state to enter
 551 *
 552 **/
 553static void ibmvfc_link_down(struct ibmvfc_host *vhost,
 554			     enum ibmvfc_host_state state)
 555{
 556	struct ibmvfc_target *tgt;
 557
 558	ENTER;
 559	scsi_block_requests(vhost->host);
 560	list_for_each_entry(tgt, &vhost->targets, queue)
 561		ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 562	ibmvfc_set_host_state(vhost, state);
 563	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL);
 564	vhost->events_to_log |= IBMVFC_AE_LINKDOWN;
 565	wake_up(&vhost->work_wait_q);
 566	LEAVE;
 567}
 568
 569/**
 570 * ibmvfc_init_host - Start host initialization
 571 * @vhost:		ibmvfc host struct
 572 *
 573 * Return value:
 574 *	nothing
 575 **/
 576static void ibmvfc_init_host(struct ibmvfc_host *vhost)
 577{
 578	struct ibmvfc_target *tgt;
 579
 580	if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) {
 581		if (++vhost->init_retries > IBMVFC_MAX_HOST_INIT_RETRIES) {
 582			dev_err(vhost->dev,
 583				"Host initialization retries exceeded. Taking adapter offline\n");
 584			ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
 585			return;
 586		}
 587	}
 588
 589	if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
 590		memset(vhost->async_crq.msgs, 0, PAGE_SIZE);
 591		vhost->async_crq.cur = 0;
 592
 593		list_for_each_entry(tgt, &vhost->targets, queue)
 594			ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 595		scsi_block_requests(vhost->host);
 596		ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
 597		vhost->job_step = ibmvfc_npiv_login;
 598		wake_up(&vhost->work_wait_q);
 599	}
 600}
 601
 602/**
 603 * ibmvfc_send_crq - Send a CRQ
 604 * @vhost:	ibmvfc host struct
 605 * @word1:	the first 64 bits of the data
 606 * @word2:	the second 64 bits of the data
 607 *
 608 * Return value:
 609 *	0 on success / other on failure
 610 **/
 611static int ibmvfc_send_crq(struct ibmvfc_host *vhost, u64 word1, u64 word2)
 612{
 613	struct vio_dev *vdev = to_vio_dev(vhost->dev);
 614	return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
 615}
 616
 617/**
 618 * ibmvfc_send_crq_init - Send a CRQ init message
 619 * @vhost:	ibmvfc host struct
 620 *
 621 * Return value:
 622 *	0 on success / other on failure
 623 **/
 624static int ibmvfc_send_crq_init(struct ibmvfc_host *vhost)
 625{
 626	ibmvfc_dbg(vhost, "Sending CRQ init\n");
 627	return ibmvfc_send_crq(vhost, 0xC001000000000000LL, 0);
 628}
 629
 630/**
 631 * ibmvfc_send_crq_init_complete - Send a CRQ init complete message
 632 * @vhost:	ibmvfc host struct
 633 *
 634 * Return value:
 635 *	0 on success / other on failure
 636 **/
 637static int ibmvfc_send_crq_init_complete(struct ibmvfc_host *vhost)
 638{
 639	ibmvfc_dbg(vhost, "Sending CRQ init complete\n");
 640	return ibmvfc_send_crq(vhost, 0xC002000000000000LL, 0);
 641}
 642
 643/**
 644 * ibmvfc_release_crq_queue - Deallocates data and unregisters CRQ
 645 * @vhost:	ibmvfc host struct
 646 *
 647 * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
 648 * the crq with the hypervisor.
 649 **/
 650static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost)
 651{
 652	long rc = 0;
 653	struct vio_dev *vdev = to_vio_dev(vhost->dev);
 654	struct ibmvfc_crq_queue *crq = &vhost->crq;
 655
 656	ibmvfc_dbg(vhost, "Releasing CRQ\n");
 657	free_irq(vdev->irq, vhost);
 658	tasklet_kill(&vhost->tasklet);
 659	do {
 660		if (rc)
 661			msleep(100);
 662		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
 663	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
 664
 665	vhost->state = IBMVFC_NO_CRQ;
 666	vhost->logged_in = 0;
 667	dma_unmap_single(vhost->dev, crq->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL);
 668	free_page((unsigned long)crq->msgs);
 669}
 670
 671/**
 672 * ibmvfc_reenable_crq_queue - reenables the CRQ
 673 * @vhost:	ibmvfc host struct
 674 *
 675 * Return value:
 676 *	0 on success / other on failure
 677 **/
 678static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
 679{
 680	int rc = 0;
 681	struct vio_dev *vdev = to_vio_dev(vhost->dev);
 682
 683	/* Re-enable the CRQ */
 684	do {
 685		if (rc)
 686			msleep(100);
 687		rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
 688	} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
 689
 690	if (rc)
 691		dev_err(vhost->dev, "Error enabling adapter (rc=%d)\n", rc);
 692
 693	return rc;
 694}
 695
 696/**
 697 * ibmvfc_reset_crq - resets a crq after a failure
 698 * @vhost:	ibmvfc host struct
 699 *
 700 * Return value:
 701 *	0 on success / other on failure
 702 **/
 703static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
 704{
 705	int rc = 0;
 706	unsigned long flags;
 707	struct vio_dev *vdev = to_vio_dev(vhost->dev);
 708	struct ibmvfc_crq_queue *crq = &vhost->crq;
 709
 710	/* Close the CRQ */
 711	do {
 712		if (rc)
 713			msleep(100);
 714		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
 715	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
 716
 717	spin_lock_irqsave(vhost->host->host_lock, flags);
 718	vhost->state = IBMVFC_NO_CRQ;
 719	vhost->logged_in = 0;
 720	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
 721
 722	/* Clean out the queue */
 723	memset(crq->msgs, 0, PAGE_SIZE);
 724	crq->cur = 0;
 725
 726	/* And re-open it again */
 727	rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
 728				crq->msg_token, PAGE_SIZE);
 729
 730	if (rc == H_CLOSED)
 731		/* Adapter is good, but other end is not ready */
 732		dev_warn(vhost->dev, "Partner adapter not ready\n");
 733	else if (rc != 0)
 734		dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc);
 735	spin_unlock_irqrestore(vhost->host->host_lock, flags);
 736
 737	return rc;
 738}
 739
 740/**
 741 * ibmvfc_valid_event - Determines if event is valid.
 742 * @pool:	event_pool that contains the event
 743 * @evt:	ibmvfc event to be checked for validity
 744 *
 745 * Return value:
 746 *	1 if event is valid / 0 if event is not valid
 747 **/
 748static int ibmvfc_valid_event(struct ibmvfc_event_pool *pool,
 749			      struct ibmvfc_event *evt)
 750{
 751	int index = evt - pool->events;
 752	if (index < 0 || index >= pool->size)	/* outside of bounds */
 753		return 0;
 754	if (evt != pool->events + index)	/* unaligned */
 755		return 0;
 756	return 1;
 757}
 758
 759/**
 760 * ibmvfc_free_event - Free the specified event
 761 * @evt:	ibmvfc_event to be freed
 762 *
 763 **/
 764static void ibmvfc_free_event(struct ibmvfc_event *evt)
 765{
 766	struct ibmvfc_host *vhost = evt->vhost;
 767	struct ibmvfc_event_pool *pool = &vhost->pool;
 768
 769	BUG_ON(!ibmvfc_valid_event(pool, evt));
 770	BUG_ON(atomic_inc_return(&evt->free) != 1);
 771	list_add_tail(&evt->queue, &vhost->free);
 772}
 773
 774/**
 775 * ibmvfc_scsi_eh_done - EH done function for queuecommand commands
 776 * @evt:	ibmvfc event struct
 777 *
 778 * This function does not setup any error status, that must be done
 779 * before this function gets called.
 780 **/
 781static void ibmvfc_scsi_eh_done(struct ibmvfc_event *evt)
 782{
 783	struct scsi_cmnd *cmnd = evt->cmnd;
 784
 785	if (cmnd) {
 786		scsi_dma_unmap(cmnd);
 787		cmnd->scsi_done(cmnd);
 788	}
 789
 790	if (evt->eh_comp)
 791		complete(evt->eh_comp);
 792
 793	ibmvfc_free_event(evt);
 794}
 795
 796/**
 797 * ibmvfc_fail_request - Fail request with specified error code
 798 * @evt:		ibmvfc event struct
 799 * @error_code:	error code to fail request with
 800 *
 801 * Return value:
 802 *	none
 803 **/
 804static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code)
 805{
 806	if (evt->cmnd) {
 807		evt->cmnd->result = (error_code << 16);
 808		evt->done = ibmvfc_scsi_eh_done;
 809	} else
 810		evt->xfer_iu->mad_common.status = IBMVFC_MAD_DRIVER_FAILED;
 811
 812	list_del(&evt->queue);
 813	del_timer(&evt->timer);
 814	ibmvfc_trc_end(evt);
 815	evt->done(evt);
 816}
 817
 818/**
 819 * ibmvfc_purge_requests - Our virtual adapter just shut down. Purge any sent requests
 820 * @vhost:		ibmvfc host struct
 821 * @error_code:	error code to fail requests with
 822 *
 823 * Return value:
 824 *	none
 825 **/
 826static void ibmvfc_purge_requests(struct ibmvfc_host *vhost, int error_code)
 827{
 828	struct ibmvfc_event *evt, *pos;
 829
 830	ibmvfc_dbg(vhost, "Purging all requests\n");
 831	list_for_each_entry_safe(evt, pos, &vhost->sent, queue)
 832		ibmvfc_fail_request(evt, error_code);
 833}
 834
 835/**
 836 * ibmvfc_hard_reset_host - Reset the connection to the server by breaking the CRQ
 837 * @vhost:	struct ibmvfc host to reset
 838 **/
 839static void ibmvfc_hard_reset_host(struct ibmvfc_host *vhost)
 840{
 841	ibmvfc_purge_requests(vhost, DID_ERROR);
 842	ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN);
 843	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_RESET);
 844}
 845
 846/**
 847 * __ibmvfc_reset_host - Reset the connection to the server (no locking)
 848 * @vhost:	struct ibmvfc host to reset
 849 **/
 850static void __ibmvfc_reset_host(struct ibmvfc_host *vhost)
 851{
 852	if (vhost->logged_in && vhost->action != IBMVFC_HOST_ACTION_LOGO_WAIT &&
 853	    !ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
 854		scsi_block_requests(vhost->host);
 855		ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_LOGO);
 856		vhost->job_step = ibmvfc_npiv_logout;
 857		wake_up(&vhost->work_wait_q);
 858	} else
 859		ibmvfc_hard_reset_host(vhost);
 860}
 861
 862/**
 863 * ibmvfc_reset_host - Reset the connection to the server
 864 * @vhost:	ibmvfc host struct
 865 **/
 866static void ibmvfc_reset_host(struct ibmvfc_host *vhost)
 867{
 868	unsigned long flags;
 869
 870	spin_lock_irqsave(vhost->host->host_lock, flags);
 871	__ibmvfc_reset_host(vhost);
 872	spin_unlock_irqrestore(vhost->host->host_lock, flags);
 873}
 874
 875/**
 876 * ibmvfc_retry_host_init - Retry host initialization if allowed
 877 * @vhost:	ibmvfc host struct
 878 *
 879 * Returns: 1 if init will be retried / 0 if not
 880 *
 881 **/
 882static int ibmvfc_retry_host_init(struct ibmvfc_host *vhost)
 883{
 884	int retry = 0;
 885
 886	if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) {
 887		vhost->delay_init = 1;
 888		if (++vhost->init_retries > IBMVFC_MAX_HOST_INIT_RETRIES) {
 889			dev_err(vhost->dev,
 890				"Host initialization retries exceeded. Taking adapter offline\n");
 891			ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
 892		} else if (vhost->init_retries == IBMVFC_MAX_HOST_INIT_RETRIES)
 893			__ibmvfc_reset_host(vhost);
 894		else {
 895			ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
 896			retry = 1;
 897		}
 898	}
 899
 900	wake_up(&vhost->work_wait_q);
 901	return retry;
 902}
 903
 904/**
 905 * __ibmvfc_get_target - Find the specified scsi_target (no locking)
 906 * @starget:	scsi target struct
 907 *
 908 * Return value:
 909 *	ibmvfc_target struct / NULL if not found
 910 **/
 911static struct ibmvfc_target *__ibmvfc_get_target(struct scsi_target *starget)
 912{
 913	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 914	struct ibmvfc_host *vhost = shost_priv(shost);
 915	struct ibmvfc_target *tgt;
 916
 917	list_for_each_entry(tgt, &vhost->targets, queue)
 918		if (tgt->target_id == starget->id) {
 919			kref_get(&tgt->kref);
 920			return tgt;
 921		}
 922	return NULL;
 923}
 924
 925/**
 926 * ibmvfc_get_target - Find the specified scsi_target
 927 * @starget:	scsi target struct
 928 *
 929 * Return value:
 930 *	ibmvfc_target struct / NULL if not found
 931 **/
 932static struct ibmvfc_target *ibmvfc_get_target(struct scsi_target *starget)
 933{
 934	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 935	struct ibmvfc_target *tgt;
 936	unsigned long flags;
 937
 938	spin_lock_irqsave(shost->host_lock, flags);
 939	tgt = __ibmvfc_get_target(starget);
 940	spin_unlock_irqrestore(shost->host_lock, flags);
 941	return tgt;
 942}
 943
 944/**
 945 * ibmvfc_get_host_speed - Get host port speed
 946 * @shost:		scsi host struct
 947 *
 948 * Return value:
 949 * 	none
 950 **/
 951static void ibmvfc_get_host_speed(struct Scsi_Host *shost)
 952{
 953	struct ibmvfc_host *vhost = shost_priv(shost);
 954	unsigned long flags;
 955
 956	spin_lock_irqsave(shost->host_lock, flags);
 957	if (vhost->state == IBMVFC_ACTIVE) {
 958		switch (vhost->login_buf->resp.link_speed / 100) {
 959		case 1:
 960			fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
 961			break;
 962		case 2:
 963			fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
 964			break;
 965		case 4:
 966			fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
 967			break;
 968		case 8:
 969			fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
 970			break;
 971		case 10:
 972			fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
 973			break;
 974		case 16:
 975			fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
 976			break;
 977		default:
 978			ibmvfc_log(vhost, 3, "Unknown port speed: %lld Gbit\n",
 979				   vhost->login_buf->resp.link_speed / 100);
 980			fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 981			break;
 982		}
 983	} else
 984		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 985	spin_unlock_irqrestore(shost->host_lock, flags);
 986}
 987
 988/**
 989 * ibmvfc_get_host_port_state - Get host port state
 990 * @shost:		scsi host struct
 991 *
 992 * Return value:
 993 * 	none
 994 **/
 995static void ibmvfc_get_host_port_state(struct Scsi_Host *shost)
 996{
 997	struct ibmvfc_host *vhost = shost_priv(shost);
 998	unsigned long flags;
 999
1000	spin_lock_irqsave(shost->host_lock, flags);
1001	switch (vhost->state) {
1002	case IBMVFC_INITIALIZING:
1003	case IBMVFC_ACTIVE:
1004		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
1005		break;
1006	case IBMVFC_LINK_DOWN:
1007		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
1008		break;
1009	case IBMVFC_LINK_DEAD:
1010	case IBMVFC_HOST_OFFLINE:
1011		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
1012		break;
1013	case IBMVFC_HALTED:
1014		fc_host_port_state(shost) = FC_PORTSTATE_BLOCKED;
1015		break;
1016	case IBMVFC_NO_CRQ:
1017		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
1018		break;
1019	default:
1020		ibmvfc_log(vhost, 3, "Unknown port state: %d\n", vhost->state);
1021		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
1022		break;
1023	}
1024	spin_unlock_irqrestore(shost->host_lock, flags);
1025}
1026
1027/**
1028 * ibmvfc_set_rport_dev_loss_tmo - Set rport's device loss timeout
1029 * @rport:		rport struct
1030 * @timeout:	timeout value
1031 *
1032 * Return value:
1033 * 	none
1034 **/
1035static void ibmvfc_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
1036{
1037	if (timeout)
1038		rport->dev_loss_tmo = timeout;
1039	else
1040		rport->dev_loss_tmo = 1;
1041}
1042
1043/**
1044 * ibmvfc_release_tgt - Free memory allocated for a target
1045 * @kref:		kref struct
1046 *
1047 **/
1048static void ibmvfc_release_tgt(struct kref *kref)
1049{
1050	struct ibmvfc_target *tgt = container_of(kref, struct ibmvfc_target, kref);
1051	kfree(tgt);
1052}
1053
1054/**
1055 * ibmvfc_get_starget_node_name - Get SCSI target's node name
1056 * @starget:	scsi target struct
1057 *
1058 * Return value:
1059 * 	none
1060 **/
1061static void ibmvfc_get_starget_node_name(struct scsi_target *starget)
1062{
1063	struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
1064	fc_starget_port_name(starget) = tgt ? tgt->ids.node_name : 0;
1065	if (tgt)
1066		kref_put(&tgt->kref, ibmvfc_release_tgt);
1067}
1068
1069/**
1070 * ibmvfc_get_starget_port_name - Get SCSI target's port name
1071 * @starget:	scsi target struct
1072 *
1073 * Return value:
1074 * 	none
1075 **/
1076static void ibmvfc_get_starget_port_name(struct scsi_target *starget)
1077{
1078	struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
1079	fc_starget_port_name(starget) = tgt ? tgt->ids.port_name : 0;
1080	if (tgt)
1081		kref_put(&tgt->kref, ibmvfc_release_tgt);
1082}
1083
1084/**
1085 * ibmvfc_get_starget_port_id - Get SCSI target's port ID
1086 * @starget:	scsi target struct
1087 *
1088 * Return value:
1089 * 	none
1090 **/
1091static void ibmvfc_get_starget_port_id(struct scsi_target *starget)
1092{
1093	struct ibmvfc_target *tgt = ibmvfc_get_target(starget);
1094	fc_starget_port_id(starget) = tgt ? tgt->scsi_id : -1;
1095	if (tgt)
1096		kref_put(&tgt->kref, ibmvfc_release_tgt);
1097}
1098
1099/**
1100 * ibmvfc_wait_while_resetting - Wait while the host resets
1101 * @vhost:		ibmvfc host struct
1102 *
1103 * Return value:
1104 * 	0 on success / other on failure
1105 **/
1106static int ibmvfc_wait_while_resetting(struct ibmvfc_host *vhost)
1107{
1108	long timeout = wait_event_timeout(vhost->init_wait_q,
1109					  ((vhost->state == IBMVFC_ACTIVE ||
1110					    vhost->state == IBMVFC_HOST_OFFLINE ||
1111					    vhost->state == IBMVFC_LINK_DEAD) &&
1112					   vhost->action == IBMVFC_HOST_ACTION_NONE),
1113					  (init_timeout * HZ));
1114
1115	return timeout ? 0 : -EIO;
1116}
1117
1118/**
1119 * ibmvfc_issue_fc_host_lip - Re-initiate link initialization
1120 * @shost:		scsi host struct
1121 *
1122 * Return value:
1123 * 	0 on success / other on failure
1124 **/
1125static int ibmvfc_issue_fc_host_lip(struct Scsi_Host *shost)
1126{
1127	struct ibmvfc_host *vhost = shost_priv(shost);
1128
1129	dev_err(vhost->dev, "Initiating host LIP. Resetting connection\n");
1130	ibmvfc_reset_host(vhost);
1131	return ibmvfc_wait_while_resetting(vhost);
1132}
1133
1134/**
1135 * ibmvfc_gather_partition_info - Gather info about the LPAR
1136 *
1137 * Return value:
1138 *	none
1139 **/
1140static void ibmvfc_gather_partition_info(struct ibmvfc_host *vhost)
1141{
1142	struct device_node *rootdn;
1143	const char *name;
1144	const unsigned int *num;
1145
1146	rootdn = of_find_node_by_path("/");
1147	if (!rootdn)
1148		return;
1149
1150	name = of_get_property(rootdn, "ibm,partition-name", NULL);
1151	if (name)
1152		strncpy(vhost->partition_name, name, sizeof(vhost->partition_name));
1153	num = of_get_property(rootdn, "ibm,partition-no", NULL);
1154	if (num)
1155		vhost->partition_number = *num;
1156	of_node_put(rootdn);
1157}
1158
1159/**
1160 * ibmvfc_set_login_info - Setup info for NPIV login
1161 * @vhost:	ibmvfc host struct
1162 *
1163 * Return value:
1164 *	none
1165 **/
1166static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
1167{
1168	struct ibmvfc_npiv_login *login_info = &vhost->login_info;
1169	struct device_node *of_node = vhost->dev->of_node;
1170	const char *location;
1171
1172	memset(login_info, 0, sizeof(*login_info));
1173
1174	login_info->ostype = IBMVFC_OS_LINUX;
1175	login_info->max_dma_len = IBMVFC_MAX_SECTORS << 9;
1176	login_info->max_payload = sizeof(struct ibmvfc_fcp_cmd_iu);
1177	login_info->max_response = sizeof(struct ibmvfc_fcp_rsp);
1178	login_info->partition_num = vhost->partition_number;
1179	login_info->vfc_frame_version = 1;
1180	login_info->fcp_version = 3;
1181	login_info->flags = IBMVFC_FLUSH_ON_HALT;
1182	if (vhost->client_migrated)
1183		login_info->flags |= IBMVFC_CLIENT_MIGRATED;
1184
1185	login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ;
1186	login_info->capabilities = IBMVFC_CAN_MIGRATE;
1187	login_info->async.va = vhost->async_crq.msg_token;
1188	login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs);
1189	strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
1190	strncpy(login_info->device_name,
1191		dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME);
1192
1193	location = of_get_property(of_node, "ibm,loc-code", NULL);
1194	location = location ? location : dev_name(vhost->dev);
1195	strncpy(login_info->drc_name, location, IBMVFC_MAX_NAME);
1196}
1197
1198/**
1199 * ibmvfc_init_event_pool - Allocates and initializes the event pool for a host
1200 * @vhost:	ibmvfc host who owns the event pool
1201 *
1202 * Returns zero on success.
1203 **/
1204static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost)
1205{
1206	int i;
1207	struct ibmvfc_event_pool *pool = &vhost->pool;
1208
1209	ENTER;
1210	pool->size = max_requests + IBMVFC_NUM_INTERNAL_REQ;
1211	pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL);
1212	if (!pool->events)
1213		return -ENOMEM;
1214
1215	pool->iu_storage = dma_alloc_coherent(vhost->dev,
1216					      pool->size * sizeof(*pool->iu_storage),
1217					      &pool->iu_token, 0);
1218
1219	if (!pool->iu_storage) {
1220		kfree(pool->events);
1221		return -ENOMEM;
1222	}
1223
1224	for (i = 0; i < pool->size; ++i) {
1225		struct ibmvfc_event *evt = &pool->events[i];
1226		atomic_set(&evt->free, 1);
1227		evt->crq.valid = 0x80;
1228		evt->crq.ioba = pool->iu_token + (sizeof(*evt->xfer_iu) * i);
1229		evt->xfer_iu = pool->iu_storage + i;
1230		evt->vhost = vhost;
1231		evt->ext_list = NULL;
1232		list_add_tail(&evt->queue, &vhost->free);
1233	}
1234
1235	LEAVE;
1236	return 0;
1237}
1238
1239/**
1240 * ibmvfc_free_event_pool - Frees memory of the event pool of a host
1241 * @vhost:	ibmvfc host who owns the event pool
1242 *
1243 **/
1244static void ibmvfc_free_event_pool(struct ibmvfc_host *vhost)
1245{
1246	int i;
1247	struct ibmvfc_event_pool *pool = &vhost->pool;
1248
1249	ENTER;
1250	for (i = 0; i < pool->size; ++i) {
1251		list_del(&pool->events[i].queue);
1252		BUG_ON(atomic_read(&pool->events[i].free) != 1);
1253		if (pool->events[i].ext_list)
1254			dma_pool_free(vhost->sg_pool,
1255				      pool->events[i].ext_list,
1256				      pool->events[i].ext_list_token);
1257	}
1258
1259	kfree(pool->events);
1260	dma_free_coherent(vhost->dev,
1261			  pool->size * sizeof(*pool->iu_storage),
1262			  pool->iu_storage, pool->iu_token);
1263	LEAVE;
1264}
1265
1266/**
1267 * ibmvfc_get_event - Gets the next free event in pool
1268 * @vhost:	ibmvfc host struct
1269 *
1270 * Returns a free event from the pool.
1271 **/
1272static struct ibmvfc_event *ibmvfc_get_event(struct ibmvfc_host *vhost)
1273{
1274	struct ibmvfc_event *evt;
1275
1276	BUG_ON(list_empty(&vhost->free));
1277	evt = list_entry(vhost->free.next, struct ibmvfc_event, queue);
1278	atomic_set(&evt->free, 0);
1279	list_del(&evt->queue);
1280	return evt;
1281}
1282
1283/**
1284 * ibmvfc_init_event - Initialize fields in an event struct that are always
1285 *				required.
1286 * @evt:	The event
1287 * @done:	Routine to call when the event is responded to
1288 * @format:	SRP or MAD format
1289 **/
1290static void ibmvfc_init_event(struct ibmvfc_event *evt,
1291			      void (*done) (struct ibmvfc_event *), u8 format)
1292{
1293	evt->cmnd = NULL;
1294	evt->sync_iu = NULL;
1295	evt->crq.format = format;
1296	evt->done = done;
1297	evt->eh_comp = NULL;
1298}
1299
1300/**
1301 * ibmvfc_map_sg_list - Initialize scatterlist
1302 * @scmd:	scsi command struct
1303 * @nseg:	number of scatterlist segments
1304 * @md:	memory descriptor list to initialize
1305 **/
1306static void ibmvfc_map_sg_list(struct scsi_cmnd *scmd, int nseg,
1307			       struct srp_direct_buf *md)
1308{
1309	int i;
1310	struct scatterlist *sg;
1311
1312	scsi_for_each_sg(scmd, sg, nseg, i) {
1313		md[i].va = sg_dma_address(sg);
1314		md[i].len = sg_dma_len(sg);
1315		md[i].key = 0;
1316	}
1317}
1318
1319/**
1320 * ibmvfc_map_sg_data - Maps dma for a scatterlist and initializes decriptor fields
1321 * @scmd:		Scsi_Cmnd with the scatterlist
1322 * @evt:		ibmvfc event struct
1323 * @vfc_cmd:	vfc_cmd that contains the memory descriptor
1324 * @dev:		device for which to map dma memory
1325 *
1326 * Returns:
1327 *	0 on success / non-zero on failure
1328 **/
1329static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
1330			      struct ibmvfc_event *evt,
1331			      struct ibmvfc_cmd *vfc_cmd, struct device *dev)
1332{
1333
1334	int sg_mapped;
1335	struct srp_direct_buf *data = &vfc_cmd->ioba;
1336	struct ibmvfc_host *vhost = dev_get_drvdata(dev);
1337
1338	sg_mapped = scsi_dma_map(scmd);
1339	if (!sg_mapped) {
1340		vfc_cmd->flags |= IBMVFC_NO_MEM_DESC;
1341		return 0;
1342	} else if (unlikely(sg_mapped < 0)) {
1343		if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
1344			scmd_printk(KERN_ERR, scmd, "Failed to map DMA buffer for command\n");
1345		return sg_mapped;
1346	}
1347
1348	if (scmd->sc_data_direction == DMA_TO_DEVICE) {
1349		vfc_cmd->flags |= IBMVFC_WRITE;
1350		vfc_cmd->iu.add_cdb_len |= IBMVFC_WRDATA;
1351	} else {
1352		vfc_cmd->flags |= IBMVFC_READ;
1353		vfc_cmd->iu.add_cdb_len |= IBMVFC_RDDATA;
1354	}
1355
1356	if (sg_mapped == 1) {
1357		ibmvfc_map_sg_list(scmd, sg_mapped, data);
1358		return 0;
1359	}
1360
1361	vfc_cmd->flags |= IBMVFC_SCATTERLIST;
1362
1363	if (!evt->ext_list) {
1364		evt->ext_list = dma_pool_alloc(vhost->sg_pool, GFP_ATOMIC,
1365					       &evt->ext_list_token);
1366
1367		if (!evt->ext_list) {
1368			scsi_dma_unmap(scmd);
1369			if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
1370				scmd_printk(KERN_ERR, scmd, "Can't allocate memory for scatterlist\n");
1371			return -ENOMEM;
1372		}
1373	}
1374
1375	ibmvfc_map_sg_list(scmd, sg_mapped, evt->ext_list);
1376
1377	data->va = evt->ext_list_token;
1378	data->len = sg_mapped * sizeof(struct srp_direct_buf);
1379	data->key = 0;
1380	return 0;
1381}
1382
1383/**
1384 * ibmvfc_timeout - Internal command timeout handler
1385 * @evt:	struct ibmvfc_event that timed out
1386 *
1387 * Called when an internally generated command times out
1388 **/
1389static void ibmvfc_timeout(struct ibmvfc_event *evt)
1390{
1391	struct ibmvfc_host *vhost = evt->vhost;
1392	dev_err(vhost->dev, "Command timed out (%p). Resetting connection\n", evt);
1393	ibmvfc_reset_host(vhost);
1394}
1395
1396/**
1397 * ibmvfc_send_event - Transforms event to u64 array and calls send_crq()
1398 * @evt:		event to be sent
1399 * @vhost:		ibmvfc host struct
1400 * @timeout:	timeout in seconds - 0 means do not time command
1401 *
1402 * Returns the value returned from ibmvfc_send_crq(). (Zero for success)
1403 **/
1404static int ibmvfc_send_event(struct ibmvfc_event *evt,
1405			     struct ibmvfc_host *vhost, unsigned long timeout)
1406{
1407	u64 *crq_as_u64 = (u64 *) &evt->crq;
1408	int rc;
1409
1410	/* Copy the IU into the transfer area */
1411	*evt->xfer_iu = evt->iu;
1412	if (evt->crq.format == IBMVFC_CMD_FORMAT)
1413		evt->xfer_iu->cmd.tag = (u64)evt;
1414	else if (evt->crq.format == IBMVFC_MAD_FORMAT)
1415		evt->xfer_iu->mad_common.tag = (u64)evt;
1416	else
1417		BUG();
1418
1419	list_add_tail(&evt->queue, &vhost->sent);
1420	init_timer(&evt->timer);
1421
1422	if (timeout) {
1423		evt->timer.data = (unsigned long) evt;
1424		evt->timer.expires = jiffies + (timeout * HZ);
1425		evt->timer.function = (void (*)(unsigned long))ibmvfc_timeout;
1426		add_timer(&evt->timer);
1427	}
1428
1429	mb();
1430
1431	if ((rc = ibmvfc_send_crq(vhost, crq_as_u64[0], crq_as_u64[1]))) {
1432		list_del(&evt->queue);
1433		del_timer(&evt->timer);
1434
1435		/* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY.
1436		 * Firmware will send a CRQ with a transport event (0xFF) to
1437		 * tell this client what has happened to the transport. This
1438		 * will be handled in ibmvfc_handle_crq()
1439		 */
1440		if (rc == H_CLOSED) {
1441			if (printk_ratelimit())
1442				dev_warn(vhost->dev, "Send warning. Receive queue closed, will retry.\n");
1443			if (evt->cmnd)
1444				scsi_dma_unmap(evt->cmnd);
1445			ibmvfc_free_event(evt);
1446			return SCSI_MLQUEUE_HOST_BUSY;
1447		}
1448
1449		dev_err(vhost->dev, "Send error (rc=%d)\n", rc);
1450		if (evt->cmnd) {
1451			evt->cmnd->result = DID_ERROR << 16;
1452			evt->done = ibmvfc_scsi_eh_done;
1453		} else
1454			evt->xfer_iu->mad_common.status = IBMVFC_MAD_CRQ_ERROR;
1455
1456		evt->done(evt);
1457	} else
1458		ibmvfc_trc_start(evt);
1459
1460	return 0;
1461}
1462
1463/**
1464 * ibmvfc_log_error - Log an error for the failed command if appropriate
1465 * @evt:	ibmvfc event to log
1466 *
1467 **/
1468static void ibmvfc_log_error(struct ibmvfc_event *evt)
1469{
1470	struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
1471	struct ibmvfc_host *vhost = evt->vhost;
1472	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
1473	struct scsi_cmnd *cmnd = evt->cmnd;
1474	const char *err = unknown_error;
1475	int index = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
1476	int logerr = 0;
1477	int rsp_code = 0;
1478
1479	if (index >= 0) {
1480		logerr = cmd_status[index].log;
1481		err = cmd_status[index].name;
1482	}
1483
1484	if (!logerr && (vhost->log_level <= (IBMVFC_DEFAULT_LOG_LEVEL + 1)))
1485		return;
1486
1487	if (rsp->flags & FCP_RSP_LEN_VALID)
1488		rsp_code = rsp->data.info.rsp_code;
1489
1490	scmd_printk(KERN_ERR, cmnd, "Command (%02X) failed: %s (%x:%x) "
1491		    "flags: %x fcp_rsp: %x, resid=%d, scsi_status: %x\n",
1492		    cmnd->cmnd[0], err, vfc_cmd->status, vfc_cmd->error,
1493		    rsp->flags, rsp_code, scsi_get_resid(cmnd), rsp->scsi_status);
1494}
1495
1496/**
1497 * ibmvfc_relogin - Log back into the specified device
1498 * @sdev:	scsi device struct
1499 *
1500 **/
1501static void ibmvfc_relogin(struct scsi_device *sdev)
1502{
1503	struct ibmvfc_host *vhost = shost_priv(sdev->host);
1504	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
1505	struct ibmvfc_target *tgt;
1506
1507	list_for_each_entry(tgt, &vhost->targets, queue) {
1508		if (rport == tgt->rport) {
1509			ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
1510			break;
1511		}
1512	}
1513
1514	ibmvfc_reinit_host(vhost);
1515}
1516
1517/**
1518 * ibmvfc_scsi_done - Handle responses from commands
1519 * @evt:	ibmvfc event to be handled
1520 *
1521 * Used as a callback when sending scsi cmds.
1522 **/
1523static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
1524{
1525	struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
1526	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
1527	struct scsi_cmnd *cmnd = evt->cmnd;
1528	u32 rsp_len = 0;
1529	u32 sense_len = rsp->fcp_sense_len;
1530
1531	if (cmnd) {
1532		if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID)
1533			scsi_set_resid(cmnd, vfc_cmd->adapter_resid);
1534		else if (rsp->flags & FCP_RESID_UNDER)
1535			scsi_set_resid(cmnd, rsp->fcp_resid);
1536		else
1537			scsi_set_resid(cmnd, 0);
1538
1539		if (vfc_cmd->status) {
1540			cmnd->result = ibmvfc_get_err_result(vfc_cmd);
1541
1542			if (rsp->flags & FCP_RSP_LEN_VALID)
1543				rsp_len = rsp->fcp_rsp_len;
1544			if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE)
1545				sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len;
1546			if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8)
1547				memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len);
1548			if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED))
1549				ibmvfc_relogin(cmnd->device);
1550
1551			if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER)))
1552				cmnd->result = (DID_ERROR << 16);
1553
1554			ibmvfc_log_error(evt);
1555		}
1556
1557		if (!cmnd->result &&
1558		    (scsi_bufflen(cmnd) - scsi_get_resid(cmnd) < cmnd->underflow))
1559			cmnd->result = (DID_ERROR << 16);
1560
1561		scsi_dma_unmap(cmnd);
1562		cmnd->scsi_done(cmnd);
1563	}
1564
1565	if (evt->eh_comp)
1566		complete(evt->eh_comp);
1567
1568	ibmvfc_free_event(evt);
1569}
1570
1571/**
1572 * ibmvfc_host_chkready - Check if the host can accept commands
1573 * @vhost:	 struct ibmvfc host
1574 *
1575 * Returns:
1576 *	1 if host can accept command / 0 if not
1577 **/
1578static inline int ibmvfc_host_chkready(struct ibmvfc_host *vhost)
1579{
1580	int result = 0;
1581
1582	switch (vhost->state) {
1583	case IBMVFC_LINK_DEAD:
1584	case IBMVFC_HOST_OFFLINE:
1585		result = DID_NO_CONNECT << 16;
1586		break;
1587	case IBMVFC_NO_CRQ:
1588	case IBMVFC_INITIALIZING:
1589	case IBMVFC_HALTED:
1590	case IBMVFC_LINK_DOWN:
1591		result = DID_REQUEUE << 16;
1592		break;
1593	case IBMVFC_ACTIVE:
1594		result = 0;
1595		break;
1596	};
1597
1598	return result;
1599}
1600
1601/**
1602 * ibmvfc_queuecommand - The queuecommand function of the scsi template
1603 * @cmnd:	struct scsi_cmnd to be executed
1604 * @done:	Callback function to be called when cmnd is completed
1605 *
1606 * Returns:
1607 *	0 on success / other on failure
1608 **/
1609static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
1610			       void (*done) (struct scsi_cmnd *))
1611{
1612	struct ibmvfc_host *vhost = shost_priv(cmnd->device->host);
1613	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
1614	struct ibmvfc_cmd *vfc_cmd;
1615	struct ibmvfc_event *evt;
1616	u8 tag[2];
1617	int rc;
1618
1619	if (unlikely((rc = fc_remote_port_chkready(rport))) ||
1620	    unlikely((rc = ibmvfc_host_chkready(vhost)))) {
1621		cmnd->result = rc;
1622		done(cmnd);
1623		return 0;
1624	}
1625
1626	cmnd->result = (DID_OK << 16);
1627	evt = ibmvfc_get_event(vhost);
1628	ibmvfc_init_event(evt, ibmvfc_scsi_done, IBMVFC_CMD_FORMAT);
1629	evt->cmnd = cmnd;
1630	cmnd->scsi_done = done;
1631	vfc_cmd = &evt->iu.cmd;
1632	memset(vfc_cmd, 0, sizeof(*vfc_cmd));
1633	vfc_cmd->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
1634	vfc_cmd->resp.len = sizeof(vfc_cmd->rsp);
1635	vfc_cmd->frame_type = IBMVFC_SCSI_FCP_TYPE;
1636	vfc_cmd->payload_len = sizeof(vfc_cmd->iu);
1637	vfc_cmd->resp_len = sizeof(vfc_cmd->rsp);
1638	vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata;
1639	vfc_cmd->tgt_scsi_id = rport->port_id;
1640	vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd);
1641	int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun);
1642	memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len);
1643
1644	if (scsi_populate_tag_msg(cmnd, tag)) {
1645		vfc_cmd->task_tag = tag[1];
1646		switch (tag[0]) {
1647		case MSG_SIMPLE_TAG:
1648			vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK;
1649			break;
1650		case MSG_HEAD_TAG:
1651			vfc_cmd->iu.pri_task_attr = IBMVFC_HEAD_OF_QUEUE;
1652			break;
1653		case MSG_ORDERED_TAG:
1654			vfc_cmd->iu.pri_task_attr = IBMVFC_ORDERED_TASK;
1655			break;
1656		};
1657	}
1658
1659	if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev))))
1660		return ibmvfc_send_event(evt, vhost, 0);
1661
1662	ibmvfc_free_event(evt);
1663	if (rc == -ENOMEM)
1664		return SCSI_MLQUEUE_HOST_BUSY;
1665
1666	if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
1667		scmd_printk(KERN_ERR, cmnd,
1668			    "Failed to map DMA buffer for command. rc=%d\n", rc);
1669
1670	cmnd->result = DID_ERROR << 16;
1671	done(cmnd);
1672	return 0;
1673}
1674
1675static DEF_SCSI_QCMD(ibmvfc_queuecommand)
1676
1677/**
1678 * ibmvfc_sync_completion - Signal that a synchronous command has completed
1679 * @evt:	ibmvfc event struct
1680 *
1681 **/
1682static void ibmvfc_sync_completion(struct ibmvfc_event *evt)
1683{
1684	/* copy the response back */
1685	if (evt->sync_iu)
1686		*evt->sync_iu = *evt->xfer_iu;
1687
1688	complete(&evt->comp);
1689}
1690
1691/**
1692 * ibmvfc_bsg_timeout_done - Completion handler for cancelling BSG commands
1693 * @evt:	struct ibmvfc_event
1694 *
1695 **/
1696static void ibmvfc_bsg_timeout_done(struct ibmvfc_event *evt)
1697{
1698	struct ibmvfc_host *vhost = evt->vhost;
1699
1700	ibmvfc_free_event(evt);
1701	vhost->aborting_passthru = 0;
1702	dev_info(vhost->dev, "Passthru command cancelled\n");
1703}
1704
1705/**
1706 * ibmvfc_bsg_timeout - Handle a BSG timeout
1707 * @job:	struct fc_bsg_job that timed out
1708 *
1709 * Returns:
1710 *	0 on success / other on failure
1711 **/
1712static int ibmvfc_bsg_timeout(struct fc_bsg_job *job)
1713{
1714	struct ibmvfc_host *vhost = shost_priv(job->shost);
1715	unsigned long port_id = (unsigned long)job->dd_data;
1716	struct ibmvfc_event *evt;
1717	struct ibmvfc_tmf *tmf;
1718	unsigned long flags;
1719	int rc;
1720
1721	ENTER;
1722	spin_lock_irqsave(vhost->host->host_lock, flags);
1723	if (vhost->aborting_passthru || vhost->state != IBMVFC_ACTIVE) {
1724		__ibmvfc_reset_host(vhost);
1725		spin_unlock_irqrestore(vhost->host->host_lock, flags);
1726		return 0;
1727	}
1728
1729	vhost->aborting_passthru = 1;
1730	evt = ibmvfc_get_event(vhost);
1731	ibmvfc_init_event(evt, ibmvfc_bsg_timeout_done, IBMVFC_MAD_FORMAT);
1732
1733	tmf = &evt->iu.tmf;
1734	memset(tmf, 0, sizeof(*tmf));
1735	tmf->common.version = 1;
1736	tmf->common.opcode = IBMVFC_TMF_MAD;
1737	tmf->common.length = sizeof(*tmf);
1738	tmf->scsi_id = port_id;
1739	tmf->cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY;
1740	tmf->my_cancel_key = IBMVFC_INTERNAL_CANCEL_KEY;
1741	rc = ibmvfc_send_event(evt, vhost, default_timeout);
1742
1743	if (rc != 0) {
1744		vhost->aborting_passthru = 0;
1745		dev_err(vhost->dev, "Failed to send cancel event. rc=%d\n", rc);
1746		rc = -EIO;
1747	} else
1748		dev_info(vhost->dev, "Cancelling passthru command to port id 0x%lx\n",
1749			 port_id);
1750
1751	spin_unlock_irqrestore(vhost->host->host_lock, flags);
1752
1753	LEAVE;
1754	return rc;
1755}
1756
1757/**
1758 * ibmvfc_bsg_plogi - PLOGI into a target to handle a BSG command
1759 * @vhost:		struct ibmvfc_host to send command
1760 * @port_id:	port ID to send command
1761 *
1762 * Returns:
1763 *	0 on success / other on failure
1764 **/
1765static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id)
1766{
1767	struct ibmvfc_port_login *plogi;
1768	struct ibmvfc_target *tgt;
1769	struct ibmvfc_event *evt;
1770	union ibmvfc_iu rsp_iu;
1771	unsigned long flags;
1772	int rc = 0, issue_login = 1;
1773
1774	ENTER;
1775	spin_lock_irqsave(vhost->host->host_lock, flags);
1776	list_for_each_entry(tgt, &vhost->targets, queue) {
1777		if (tgt->scsi_id == port_id) {
1778			issue_login = 0;
1779			break;
1780		}
1781	}
1782
1783	if (!issue_login)
1784		goto unlock_out;
1785	if (unlikely((rc = ibmvfc_host_chkready(vhost))))
1786		goto unlock_out;
1787
1788	evt = ibmvfc_get_event(vhost);
1789	ibmvfc_init_event(evt, ibmvfc_sync_completion,

Large files files are truncated, but you can click here to view the full file