smp_request.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. /*
  2. * This file is provided under a dual BSD/GPLv2 license. When using or
  3. * redistributing this file, you may do so under either license.
  4. *
  5. * GPL LICENSE SUMMARY
  6. *
  7. * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of version 2 of the GNU General Public License as
  11. * published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  21. * The full GNU General Public License is included in this distribution
  22. * in the file called LICENSE.GPL.
  23. *
  24. * BSD LICENSE
  25. *
  26. * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
  27. * All rights reserved.
  28. *
  29. * Redistribution and use in source and binary forms, with or without
  30. * modification, are permitted provided that the following conditions
  31. * are met:
  32. *
  33. * * Redistributions of source code must retain the above copyright
  34. * notice, this list of conditions and the following disclaimer.
  35. * * Redistributions in binary form must reproduce the above copyright
  36. * notice, this list of conditions and the following disclaimer in
  37. * the documentation and/or other materials provided with the
  38. * distribution.
  39. * * Neither the name of Intel Corporation nor the names of its
  40. * contributors may be used to endorse or promote products derived
  41. * from this software without specific prior written permission.
  42. *
  43. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  44. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  45. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  46. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  47. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  48. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  49. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  50. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  51. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  52. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  53. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  54. */
  55. #include <scsi/sas.h>
  56. #include "state_machine.h"
  57. #include "remote_device.h"
  58. #include "request.h"
  59. #include "scu_completion_codes.h"
  60. #include "scu_task_context.h"
  61. #include "host.h"
  62. static void scu_smp_request_construct_task_context(
  63. struct scic_sds_request *sci_req,
  64. struct smp_req *smp_req);
  65. void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req)
  66. {
  67. if (sci_req->was_tag_assigned_by_user == false)
  68. sci_req->task_context_buffer = &sci_req->tc;
  69. }
  70. /*
  71. * This function will fill in the SCU Task Context for a SMP request. The
  72. * following important settings are utilized: -# task_type ==
  73. * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type
  74. * (i.e. non-raw frame) is being utilized to perform task management. -#
  75. * control_frame == 1. This ensures that the proper endianess is set so
  76. * that the bytes are transmitted in the right order for a smp request frame.
  77. * @sci_req: This parameter specifies the smp request object being
  78. * constructed.
  79. *
  80. */
  81. static void
  82. scu_smp_request_construct_task_context(struct scic_sds_request *sci_req,
  83. struct smp_req *smp_req)
  84. {
  85. dma_addr_t dma_addr;
  86. struct scic_sds_controller *scic;
  87. struct scic_sds_remote_device *sci_dev;
  88. struct scic_sds_port *sci_port;
  89. struct scu_task_context *task_context;
  90. ssize_t word_cnt = sizeof(struct smp_req) / sizeof(u32);
  91. /* byte swap the smp request. */
  92. sci_swab32_cpy(&sci_req->smp.cmd, smp_req,
  93. word_cnt);
  94. task_context = scic_sds_request_get_task_context(sci_req);
  95. scic = scic_sds_request_get_controller(sci_req);
  96. sci_dev = scic_sds_request_get_device(sci_req);
  97. sci_port = scic_sds_request_get_port(sci_req);
  98. /*
  99. * Fill in the TC with the its required data
  100. * 00h
  101. */
  102. task_context->priority = 0;
  103. task_context->initiator_request = 1;
  104. task_context->connection_rate = sci_dev->connection_rate;
  105. task_context->protocol_engine_index =
  106. scic_sds_controller_get_protocol_engine_group(scic);
  107. task_context->logical_port_index = scic_sds_port_get_index(sci_port);
  108. task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
  109. task_context->abort = 0;
  110. task_context->valid = SCU_TASK_CONTEXT_VALID;
  111. task_context->context_type = SCU_TASK_CONTEXT_TYPE;
  112. /* 04h */
  113. task_context->remote_node_index = sci_dev->rnc.remote_node_index;
  114. task_context->command_code = 0;
  115. task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;
  116. /* 08h */
  117. task_context->link_layer_control = 0;
  118. task_context->do_not_dma_ssp_good_response = 1;
  119. task_context->strict_ordering = 0;
  120. task_context->control_frame = 1;
  121. task_context->timeout_enable = 0;
  122. task_context->block_guard_enable = 0;
  123. /* 0ch */
  124. task_context->address_modifier = 0;
  125. /* 10h */
  126. task_context->ssp_command_iu_length = smp_req->req_len;
  127. /* 14h */
  128. task_context->transfer_length_bytes = 0;
  129. /*
  130. * 18h ~ 30h, protocol specific
  131. * since commandIU has been build by framework at this point, we just
  132. * copy the frist DWord from command IU to this location. */
  133. memcpy(&task_context->type.smp, &sci_req->smp.cmd, sizeof(u32));
  134. /*
  135. * 40h
  136. * "For SMP you could program it to zero. We would prefer that way
  137. * so that done code will be consistent." - Venki
  138. */
  139. task_context->task_phase = 0;
  140. if (sci_req->was_tag_assigned_by_user) {
  141. /*
  142. * Build the task context now since we have already read
  143. * the data
  144. */
  145. sci_req->post_context =
  146. (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
  147. (scic_sds_controller_get_protocol_engine_group(scic) <<
  148. SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
  149. (scic_sds_port_get_index(sci_port) <<
  150. SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) |
  151. scic_sds_io_tag_get_index(sci_req->io_tag));
  152. } else {
  153. /*
  154. * Build the task context now since we have already read
  155. * the data.
  156. * I/O tag index is not assigned because we have to wait
  157. * until we get a TCi.
  158. */
  159. sci_req->post_context =
  160. (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
  161. (scic_sds_controller_get_protocol_engine_group(scic) <<
  162. SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
  163. (scic_sds_port_get_index(sci_port) <<
  164. SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT));
  165. }
  166. /*
  167. * Copy the physical address for the command buffer to the SCU Task
  168. * Context command buffer should not contain command header.
  169. */
  170. dma_addr = scic_io_request_get_dma_addr(sci_req,
  171. ((char *) &sci_req->smp.cmd) +
  172. sizeof(u32));
  173. task_context->command_iu_upper = upper_32_bits(dma_addr);
  174. task_context->command_iu_lower = lower_32_bits(dma_addr);
  175. /* SMP response comes as UF, so no need to set response IU address. */
  176. task_context->response_iu_upper = 0;
  177. task_context->response_iu_lower = 0;
  178. }
  179. /*
  180. * This function processes an unsolicited frame while the SMP request is waiting
  181. * for a response frame. It will copy the response data, release the
  182. * unsolicited frame, and transition the request to the
  183. * SCI_BASE_REQUEST_STATE_COMPLETED state.
  184. * @sci_req: This parameter specifies the request for which the
  185. * unsolicited frame was received.
  186. * @frame_index: This parameter indicates the unsolicited frame index that
  187. * should contain the response.
  188. *
  189. * This function returns an indication of whether the response frame was handled
  190. * successfully or not. SCI_SUCCESS Currently this value is always returned and
  191. * indicates successful processing of the TC response.
  192. */
  193. static enum sci_status
  194. scic_sds_smp_request_await_response_frame_handler(struct scic_sds_request *sci_req,
  195. u32 frame_index)
  196. {
  197. enum sci_status status;
  198. void *frame_header;
  199. struct smp_resp *rsp_hdr = &sci_req->smp.rsp;
  200. ssize_t word_cnt = SMP_RESP_HDR_SZ / sizeof(u32);
  201. status = scic_sds_unsolicited_frame_control_get_header(
  202. &(scic_sds_request_get_controller(sci_req)->uf_control),
  203. frame_index,
  204. &frame_header);
  205. /* byte swap the header. */
  206. sci_swab32_cpy(rsp_hdr, frame_header, word_cnt);
  207. if (rsp_hdr->frame_type == SMP_RESPONSE) {
  208. void *smp_resp;
  209. status = scic_sds_unsolicited_frame_control_get_buffer(
  210. &(scic_sds_request_get_controller(sci_req)->uf_control),
  211. frame_index,
  212. &smp_resp);
  213. word_cnt = (sizeof(struct smp_req) - SMP_RESP_HDR_SZ) /
  214. sizeof(u32);
  215. sci_swab32_cpy(((u8 *) rsp_hdr) + SMP_RESP_HDR_SZ,
  216. smp_resp, word_cnt);
  217. scic_sds_request_set_status(
  218. sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS);
  219. sci_base_state_machine_change_state(
  220. &sci_req->started_substate_machine,
  221. SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION);
  222. } else {
  223. /* This was not a response frame why did it get forwarded? */
  224. dev_err(scic_to_dev(sci_req->owning_controller),
  225. "%s: SCIC SMP Request 0x%p received unexpected frame "
  226. "%d type 0x%02x\n",
  227. __func__,
  228. sci_req,
  229. frame_index,
  230. rsp_hdr->frame_type);
  231. scic_sds_request_set_status(
  232. sci_req,
  233. SCU_TASK_DONE_SMP_FRM_TYPE_ERR,
  234. SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR);
  235. sci_base_state_machine_change_state(
  236. &sci_req->state_machine,
  237. SCI_BASE_REQUEST_STATE_COMPLETED);
  238. }
  239. scic_sds_controller_release_frame(sci_req->owning_controller,
  240. frame_index);
  241. return SCI_SUCCESS;
  242. }
  243. /**
  244. * This method processes an abnormal TC completion while the SMP request is
  245. * waiting for a response frame. It decides what happened to the IO based
  246. * on TC completion status.
  247. * @sci_req: This parameter specifies the request for which the TC
  248. * completion was received.
  249. * @completion_code: This parameter indicates the completion status information
  250. * for the TC.
  251. *
  252. * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
  253. * this method always returns success.
  254. */
  255. static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler(
  256. struct scic_sds_request *sci_req,
  257. u32 completion_code)
  258. {
  259. switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
  260. case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
  261. /*
  262. * In the AWAIT RESPONSE state, any TC completion is unexpected.
  263. * but if the TC has success status, we complete the IO anyway. */
  264. scic_sds_request_set_status(
  265. sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS
  266. );
  267. sci_base_state_machine_change_state(
  268. &sci_req->state_machine,
  269. SCI_BASE_REQUEST_STATE_COMPLETED);
  270. break;
  271. case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
  272. case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
  273. case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
  274. case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
  275. /*
  276. * These status has been seen in a specific LSI expander, which sometimes
  277. * is not able to send smp response within 2 ms. This causes our hardware
  278. * break the connection and set TC completion with one of these SMP_XXX_XX_ERR
  279. * status. For these type of error, we ask scic user to retry the request. */
  280. scic_sds_request_set_status(
  281. sci_req, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED
  282. );
  283. sci_base_state_machine_change_state(
  284. &sci_req->state_machine,
  285. SCI_BASE_REQUEST_STATE_COMPLETED);
  286. break;
  287. default:
  288. /*
  289. * All other completion status cause the IO to be complete. If a NAK
  290. * was received, then it is up to the user to retry the request. */
  291. scic_sds_request_set_status(
  292. sci_req,
  293. SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
  294. SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
  295. );
  296. sci_base_state_machine_change_state(
  297. &sci_req->state_machine,
  298. SCI_BASE_REQUEST_STATE_COMPLETED);
  299. break;
  300. }
  301. return SCI_SUCCESS;
  302. }
  303. /**
  304. * This method processes the completions transport layer (TL) status to
  305. * determine if the SMP request was sent successfully. If the SMP request
  306. * was sent successfully, then the state for the SMP request transits to
  307. * waiting for a response frame.
  308. * @sci_req: This parameter specifies the request for which the TC
  309. * completion was received.
  310. * @completion_code: This parameter indicates the completion status information
  311. * for the TC.
  312. *
  313. * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
  314. * this method always returns success.
  315. */
  316. static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler(
  317. struct scic_sds_request *sci_req,
  318. u32 completion_code)
  319. {
  320. switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
  321. case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
  322. scic_sds_request_set_status(
  323. sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS
  324. );
  325. sci_base_state_machine_change_state(
  326. &sci_req->state_machine,
  327. SCI_BASE_REQUEST_STATE_COMPLETED);
  328. break;
  329. default:
  330. /*
  331. * All other completion status cause the IO to be complete. If a NAK
  332. * was received, then it is up to the user to retry the request. */
  333. scic_sds_request_set_status(
  334. sci_req,
  335. SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
  336. SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
  337. );
  338. sci_base_state_machine_change_state(
  339. &sci_req->state_machine,
  340. SCI_BASE_REQUEST_STATE_COMPLETED);
  341. break;
  342. }
  343. return SCI_SUCCESS;
  344. }
  345. static const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = {
  346. [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
  347. .abort_handler = scic_sds_request_started_state_abort_handler,
  348. .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler,
  349. .frame_handler = scic_sds_smp_request_await_response_frame_handler,
  350. },
  351. [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
  352. .abort_handler = scic_sds_request_started_state_abort_handler,
  353. .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler,
  354. }
  355. };
  356. /**
  357. * This method performs the actions required when entering the
  358. * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This
  359. * includes setting the IO request state handlers for this sub-state.
  360. * @object: This parameter specifies the request object for which the sub-state
  361. * change is occurring.
  362. *
  363. * none.
  364. */
  365. static void scic_sds_smp_request_started_await_response_substate_enter(
  366. void *object)
  367. {
  368. struct scic_sds_request *sci_req = object;
  369. SET_STATE_HANDLER(
  370. sci_req,
  371. scic_sds_smp_request_started_substate_handler_table,
  372. SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
  373. );
  374. }
  375. /**
  376. * This method performs the actions required when entering the
  377. * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state.
  378. * This includes setting the SMP request state handlers for this sub-state.
  379. * @object: This parameter specifies the request object for which the sub-state
  380. * change is occurring.
  381. *
  382. * none.
  383. */
  384. static void scic_sds_smp_request_started_await_tc_completion_substate_enter(
  385. void *object)
  386. {
  387. struct scic_sds_request *sci_req = object;
  388. SET_STATE_HANDLER(
  389. sci_req,
  390. scic_sds_smp_request_started_substate_handler_table,
  391. SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
  392. );
  393. }
  394. static const struct sci_base_state scic_sds_smp_request_started_substate_table[] = {
  395. [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
  396. .enter_state = scic_sds_smp_request_started_await_response_substate_enter,
  397. },
  398. [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
  399. .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter,
  400. },
  401. };
  402. /**
  403. * This method is called by the SCI user to build an SMP IO request.
  404. *
  405. * - The user must have previously called scic_io_request_construct() on the
  406. * supplied IO request. Indicate if the controller successfully built the IO
  407. * request. SCI_SUCCESS This value is returned if the IO request was
  408. * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
  409. * if the remote_device does not support the SMP protocol.
  410. * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
  411. * properly set the association between the SCIC IO request and the user's IO
  412. * request.
  413. */
  414. enum sci_status scic_io_request_construct_smp(struct scic_sds_request *sci_req)
  415. {
  416. struct smp_req *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL);
  417. if (!smp_req)
  418. return SCI_FAILURE_INSUFFICIENT_RESOURCES;
  419. sci_req->protocol = SCIC_SMP_PROTOCOL;
  420. sci_req->has_started_substate_machine = true;
  421. /* Construct the started sub-state machine. */
  422. sci_base_state_machine_construct(
  423. &sci_req->started_substate_machine,
  424. sci_req,
  425. scic_sds_smp_request_started_substate_table,
  426. SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
  427. );
  428. /* Construct the SMP SCU Task Context */
  429. memcpy(smp_req, &sci_req->smp.cmd, sizeof(*smp_req));
  430. /*
  431. * Look at the SMP requests' header fields; for certain SAS 1.x SMP
  432. * functions under SAS 2.0, a zero request length really indicates
  433. * a non-zero default length. */
  434. if (smp_req->req_len == 0) {
  435. switch (smp_req->func) {
  436. case SMP_DISCOVER:
  437. case SMP_REPORT_PHY_ERR_LOG:
  438. case SMP_REPORT_PHY_SATA:
  439. case SMP_REPORT_ROUTE_INFO:
  440. smp_req->req_len = 2;
  441. break;
  442. case SMP_CONF_ROUTE_INFO:
  443. case SMP_PHY_CONTROL:
  444. case SMP_PHY_TEST_FUNCTION:
  445. smp_req->req_len = 9;
  446. break;
  447. /* Default - zero is a valid default for 2.0. */
  448. }
  449. }
  450. scu_smp_request_construct_task_context(sci_req, smp_req);
  451. sci_base_state_machine_change_state(&sci_req->state_machine,
  452. SCI_BASE_REQUEST_STATE_CONSTRUCTED);
  453. kfree(smp_req);
  454. return SCI_SUCCESS;
  455. }