request.h 12 KB

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