request.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  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. #if !defined(_ISCI_REQUEST_H_)
  56. #define _ISCI_REQUEST_H_
  57. #include "isci.h"
  58. /**
  59. * struct isci_request_status - This enum defines the possible states of an I/O
  60. * request.
  61. *
  62. *
  63. */
  64. enum isci_request_status {
  65. unallocated = 0x00,
  66. allocated = 0x01,
  67. started = 0x02,
  68. completed = 0x03,
  69. aborting = 0x04,
  70. aborted = 0x05,
  71. terminating = 0x06
  72. };
  73. enum task_type {
  74. io_task = 0,
  75. tmf_task = 1
  76. };
  77. /**
  78. * struct isci_request - This class represents the request object used to track
  79. * IO, smp and TMF request internal. It wraps the SCIC request object.
  80. *
  81. *
  82. */
  83. struct isci_request {
  84. struct scic_sds_request *sci_request_handle;
  85. enum isci_request_status status;
  86. enum task_type ttype;
  87. unsigned short io_tag;
  88. bool complete_in_target;
  89. union ttype_ptr_union {
  90. struct sas_task *io_task_ptr; /* When ttype==io_task */
  91. struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */
  92. } ttype_ptr;
  93. struct isci_host *isci_host;
  94. struct isci_remote_device *isci_device;
  95. /* For use in the requests_to_{complete|abort} lists: */
  96. struct list_head completed_node;
  97. /* For use in the reqs_in_process list: */
  98. struct list_head dev_node;
  99. void *sci_request_mem_ptr;
  100. spinlock_t state_lock;
  101. dma_addr_t request_daddr;
  102. dma_addr_t zero_scatter_daddr;
  103. unsigned int num_sg_entries; /* returned by pci_alloc_sg */
  104. unsigned int request_alloc_size; /* size of block from dma_pool_alloc */
  105. /** Note: "io_request_completion" is completed in two different ways
  106. * depending on whether this is a TMF or regular request.
  107. * - TMF requests are completed in the thread that started them;
  108. * - regular requests are completed in the request completion callback
  109. * function.
  110. * This difference in operation allows the aborter of a TMF request
  111. * to be sure that once the TMF request completes, the I/O that the
  112. * TMF was aborting is guaranteed to have completed.
  113. */
  114. struct completion *io_request_completion;
  115. };
  116. /**
  117. * This function gets the status of the request object.
  118. * @request: This parameter points to the isci_request object
  119. *
  120. * status of the object as a isci_request_status enum.
  121. */
  122. static inline
  123. enum isci_request_status isci_request_get_state(
  124. struct isci_request *isci_request)
  125. {
  126. BUG_ON(isci_request == NULL);
  127. /*probably a bad sign... */
  128. if (isci_request->status == unallocated)
  129. dev_warn(&isci_request->isci_host->pdev->dev,
  130. "%s: isci_request->status == unallocated\n",
  131. __func__);
  132. return isci_request->status;
  133. }
  134. /**
  135. * isci_request_change_state() - This function sets the status of the request
  136. * object.
  137. * @request: This parameter points to the isci_request object
  138. * @status: This Parameter is the new status of the object
  139. *
  140. */
  141. static inline enum isci_request_status isci_request_change_state(
  142. struct isci_request *isci_request,
  143. enum isci_request_status status)
  144. {
  145. enum isci_request_status old_state;
  146. unsigned long flags;
  147. dev_dbg(&isci_request->isci_host->pdev->dev,
  148. "%s: isci_request = %p, state = 0x%x\n",
  149. __func__,
  150. isci_request,
  151. status);
  152. BUG_ON(isci_request == NULL);
  153. spin_lock_irqsave(&isci_request->state_lock, flags);
  154. old_state = isci_request->status;
  155. isci_request->status = status;
  156. spin_unlock_irqrestore(&isci_request->state_lock, flags);
  157. return old_state;
  158. }
  159. /**
  160. * isci_request_change_started_to_newstate() - This function sets the status of
  161. * the request object.
  162. * @request: This parameter points to the isci_request object
  163. * @status: This Parameter is the new status of the object
  164. *
  165. * state previous to any change.
  166. */
  167. static inline enum isci_request_status isci_request_change_started_to_newstate(
  168. struct isci_request *isci_request,
  169. struct completion *completion_ptr,
  170. enum isci_request_status newstate)
  171. {
  172. enum isci_request_status old_state;
  173. unsigned long flags;
  174. BUG_ON(isci_request == NULL);
  175. spin_lock_irqsave(&isci_request->state_lock, flags);
  176. old_state = isci_request->status;
  177. if (old_state == started) {
  178. BUG_ON(isci_request->io_request_completion != NULL);
  179. isci_request->io_request_completion = completion_ptr;
  180. isci_request->status = newstate;
  181. }
  182. spin_unlock_irqrestore(&isci_request->state_lock, flags);
  183. dev_dbg(&isci_request->isci_host->pdev->dev,
  184. "%s: isci_request = %p, old_state = 0x%x\n",
  185. __func__,
  186. isci_request,
  187. old_state);
  188. return old_state;
  189. }
  190. /**
  191. * isci_request_change_started_to_aborted() - This function sets the status of
  192. * the request object.
  193. * @request: This parameter points to the isci_request object
  194. * @completion_ptr: This parameter is saved as the kernel completion structure
  195. * signalled when the old request completes.
  196. *
  197. * state previous to any change.
  198. */
  199. static inline enum isci_request_status isci_request_change_started_to_aborted(
  200. struct isci_request *isci_request,
  201. struct completion *completion_ptr)
  202. {
  203. return isci_request_change_started_to_newstate(
  204. isci_request, completion_ptr, aborted
  205. );
  206. }
  207. /**
  208. * isci_request_free() - This function frees the request object.
  209. * @isci_host: This parameter specifies the ISCI host object
  210. * @isci_request: This parameter points to the isci_request object
  211. *
  212. */
  213. static inline void isci_request_free(
  214. struct isci_host *isci_host,
  215. struct isci_request *isci_request)
  216. {
  217. BUG_ON(isci_request == NULL);
  218. /* release the dma memory if we fail. */
  219. dma_pool_free(isci_host->dma_pool, isci_request,
  220. isci_request->request_daddr);
  221. }
  222. /* #define ISCI_REQUEST_VALIDATE_ACCESS
  223. */
  224. #ifdef ISCI_REQUEST_VALIDATE_ACCESS
  225. static inline
  226. struct sas_task *isci_request_access_task(struct isci_request *isci_request)
  227. {
  228. BUG_ON(isci_request->ttype != io_task);
  229. return isci_request->ttype_ptr.io_task_ptr;
  230. }
  231. static inline
  232. struct isci_tmf *isci_request_access_tmf(struct isci_request *isci_request)
  233. {
  234. BUG_ON(isci_request->ttype != tmf_task);
  235. return isci_request->ttype_ptr.tmf_task_ptr;
  236. }
  237. #else /* not ISCI_REQUEST_VALIDATE_ACCESS */
  238. #define isci_request_access_task(RequestPtr) \
  239. ((RequestPtr)->ttype_ptr.io_task_ptr)
  240. #define isci_request_access_tmf(RequestPtr) \
  241. ((RequestPtr)->ttype_ptr.tmf_task_ptr)
  242. #endif /* not ISCI_REQUEST_VALIDATE_ACCESS */
  243. int isci_request_alloc_tmf(
  244. struct isci_host *isci_host,
  245. struct isci_tmf *isci_tmf,
  246. struct isci_request **isci_request,
  247. struct isci_remote_device *isci_device,
  248. gfp_t gfp_flags);
  249. int isci_request_execute(
  250. struct isci_host *isci_host,
  251. struct sas_task *task,
  252. struct isci_request **request,
  253. gfp_t gfp_flags);
  254. /**
  255. * isci_request_unmap_sgl() - This function unmaps the DMA address of a given
  256. * sgl
  257. * @request: This parameter points to the isci_request object
  258. * @*pdev: This Parameter is the pci_device struct for the controller
  259. *
  260. */
  261. static inline void isci_request_unmap_sgl(
  262. struct isci_request *request,
  263. struct pci_dev *pdev)
  264. {
  265. struct sas_task *task = isci_request_access_task(request);
  266. dev_dbg(&request->isci_host->pdev->dev,
  267. "%s: request = %p, task = %p,\n"
  268. "task->data_dir = %d, is_sata = %d\n ",
  269. __func__,
  270. request,
  271. task,
  272. task->data_dir,
  273. sas_protocol_ata(task->task_proto));
  274. if ((task->data_dir != PCI_DMA_NONE) &&
  275. !sas_protocol_ata(task->task_proto)) {
  276. if (task->num_scatter == 0)
  277. /* 0 indicates a single dma address */
  278. dma_unmap_single(
  279. &pdev->dev,
  280. request->zero_scatter_daddr,
  281. task->total_xfer_len,
  282. task->data_dir
  283. );
  284. else /* unmap the sgl dma addresses */
  285. dma_unmap_sg(
  286. &pdev->dev,
  287. task->scatter,
  288. request->num_sg_entries,
  289. task->data_dir
  290. );
  291. }
  292. }
  293. void isci_request_io_request_complete(
  294. struct isci_host *isci_host,
  295. struct isci_request *request,
  296. enum sci_io_status completion_status);
  297. u32 isci_request_io_request_get_transfer_length(
  298. struct isci_request *request);
  299. SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction(
  300. struct isci_request *request);
  301. /**
  302. * isci_request_io_request_get_next_sge() - This function is called by the sci
  303. * core to retrieve the next sge for a given request.
  304. * @request: This parameter is the isci_request object.
  305. * @current_sge_address: This parameter is the last sge retrieved by the sci
  306. * core for this request.
  307. *
  308. * pointer to the next sge for specified request.
  309. */
  310. static inline void *isci_request_io_request_get_next_sge(
  311. struct isci_request *request,
  312. void *current_sge_address)
  313. {
  314. struct sas_task *task = isci_request_access_task(request);
  315. void *ret = NULL;
  316. dev_dbg(&request->isci_host->pdev->dev,
  317. "%s: request = %p, "
  318. "current_sge_address = %p, "
  319. "num_scatter = %d\n",
  320. __func__,
  321. request,
  322. current_sge_address,
  323. task->num_scatter);
  324. if (!current_sge_address) /* First time through.. */
  325. ret = task->scatter; /* always task->scatter */
  326. else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */
  327. ret = NULL; /* there is only one element. */
  328. else
  329. ret = sg_next(current_sge_address); /* sg_next returns NULL
  330. * for the last element
  331. */
  332. dev_dbg(&request->isci_host->pdev->dev,
  333. "%s: next sge address = %p\n",
  334. __func__,
  335. ret);
  336. return ret;
  337. }
  338. dma_addr_t isci_request_sge_get_address_field(
  339. struct isci_request *request,
  340. void *sge_address);
  341. u32 isci_request_sge_get_length_field(
  342. struct isci_request *request,
  343. void *sge_address);
  344. void *isci_request_ssp_io_request_get_cdb_address(
  345. struct isci_request *request);
  346. u32 isci_request_ssp_io_request_get_cdb_length(
  347. struct isci_request *request);
  348. u32 isci_request_ssp_io_request_get_lun(
  349. struct isci_request *request);
  350. u32 isci_request_ssp_io_request_get_task_attribute(
  351. struct isci_request *request);
  352. u32 isci_request_ssp_io_request_get_command_priority(
  353. struct isci_request *request);
  354. void isci_terminate_pending_requests(
  355. struct isci_host *isci_host,
  356. struct isci_remote_device *isci_device,
  357. enum isci_request_status new_request_state);
  358. #endif /* !defined(_ISCI_REQUEST_H_) */