request.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. #ifndef _ISCI_REQUEST_H_
  56. #define _ISCI_REQUEST_H_
  57. #include "isci.h"
  58. #include "host.h"
  59. #include "scic_sds_request.h"
  60. /**
  61. * struct isci_request_status - This enum defines the possible states of an I/O
  62. * request.
  63. *
  64. *
  65. */
  66. enum isci_request_status {
  67. unallocated = 0x00,
  68. allocated = 0x01,
  69. started = 0x02,
  70. completed = 0x03,
  71. aborting = 0x04,
  72. aborted = 0x05,
  73. terminating = 0x06,
  74. dead = 0x07
  75. };
  76. enum task_type {
  77. io_task = 0,
  78. tmf_task = 1
  79. };
  80. struct isci_request {
  81. enum isci_request_status status;
  82. enum task_type ttype;
  83. unsigned short io_tag;
  84. bool complete_in_target;
  85. bool terminated;
  86. union ttype_ptr_union {
  87. struct sas_task *io_task_ptr; /* When ttype==io_task */
  88. struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */
  89. } ttype_ptr;
  90. struct isci_host *isci_host;
  91. struct isci_remote_device *isci_device;
  92. /* For use in the requests_to_{complete|abort} lists: */
  93. struct list_head completed_node;
  94. /* For use in the reqs_in_process list: */
  95. struct list_head dev_node;
  96. spinlock_t state_lock;
  97. dma_addr_t request_daddr;
  98. dma_addr_t zero_scatter_daddr;
  99. unsigned int num_sg_entries; /* returned by pci_alloc_sg */
  100. /** Note: "io_request_completion" is completed in two different ways
  101. * depending on whether this is a TMF or regular request.
  102. * - TMF requests are completed in the thread that started them;
  103. * - regular requests are completed in the request completion callback
  104. * function.
  105. * This difference in operation allows the aborter of a TMF request
  106. * to be sure that once the TMF request completes, the I/O that the
  107. * TMF was aborting is guaranteed to have completed.
  108. */
  109. struct completion *io_request_completion;
  110. struct scic_sds_request sci;
  111. };
  112. static inline struct isci_request *sci_req_to_ireq(struct scic_sds_request *sci_req)
  113. {
  114. struct isci_request *ireq = container_of(sci_req, typeof(*ireq), sci);
  115. return ireq;
  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. spin_lock_irqsave(&isci_request->state_lock, flags);
  176. old_state = isci_request->status;
  177. if (old_state == started || old_state == aborting) {
  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. if (!isci_request)
  218. return;
  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. /**
  299. * isci_request_io_request_get_next_sge() - This function is called by the sci
  300. * core to retrieve the next sge for a given request.
  301. * @request: This parameter is the isci_request object.
  302. * @current_sge_address: This parameter is the last sge retrieved by the sci
  303. * core for this request.
  304. *
  305. * pointer to the next sge for specified request.
  306. */
  307. static inline void *isci_request_io_request_get_next_sge(
  308. struct isci_request *request,
  309. void *current_sge_address)
  310. {
  311. struct sas_task *task = isci_request_access_task(request);
  312. void *ret = NULL;
  313. dev_dbg(&request->isci_host->pdev->dev,
  314. "%s: request = %p, "
  315. "current_sge_address = %p, "
  316. "num_scatter = %d\n",
  317. __func__,
  318. request,
  319. current_sge_address,
  320. task->num_scatter);
  321. if (!current_sge_address) /* First time through.. */
  322. ret = task->scatter; /* always task->scatter */
  323. else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */
  324. ret = NULL; /* there is only one element. */
  325. else
  326. ret = sg_next(current_sge_address); /* sg_next returns NULL
  327. * for the last element
  328. */
  329. dev_dbg(&request->isci_host->pdev->dev,
  330. "%s: next sge address = %p\n",
  331. __func__,
  332. ret);
  333. return ret;
  334. }
  335. void isci_terminate_pending_requests(
  336. struct isci_host *isci_host,
  337. struct isci_remote_device *isci_device,
  338. enum isci_request_status new_request_state);
  339. #endif /* !defined(_ISCI_REQUEST_H_) */