PageRenderTime 69ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/scsi/ibmvscsi/ibmvfc.c

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

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