cxgb3i_pdu.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /*
  2. * cxgb3i_pdu.c: Chelsio S3xx iSCSI driver.
  3. *
  4. * Copyright (c) 2008 Chelsio Communications, Inc.
  5. * Copyright (c) 2008 Mike Christie
  6. * Copyright (c) 2008 Red Hat, Inc. All rights reserved.
  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.
  11. *
  12. * Written by: Karen Xie (kxie@chelsio.com)
  13. */
  14. #include <linux/skbuff.h>
  15. #include <linux/crypto.h>
  16. #include <scsi/scsi_cmnd.h>
  17. #include <scsi/scsi_host.h>
  18. #include "cxgb3i.h"
  19. #include "cxgb3i_pdu.h"
  20. #ifdef __DEBUG_CXGB3I_RX__
  21. #define cxgb3i_rx_debug cxgb3i_log_debug
  22. #else
  23. #define cxgb3i_rx_debug(fmt...)
  24. #endif
  25. #ifdef __DEBUG_CXGB3I_TX__
  26. #define cxgb3i_tx_debug cxgb3i_log_debug
  27. #else
  28. #define cxgb3i_tx_debug(fmt...)
  29. #endif
  30. static struct page *pad_page;
  31. /*
  32. * pdu receive, interact with libiscsi_tcp
  33. */
  34. static inline int read_pdu_skb(struct iscsi_conn *conn, struct sk_buff *skb,
  35. unsigned int offset, int offloaded)
  36. {
  37. int status = 0;
  38. int bytes_read;
  39. bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
  40. switch (status) {
  41. case ISCSI_TCP_CONN_ERR:
  42. return -EIO;
  43. case ISCSI_TCP_SUSPENDED:
  44. /* no transfer - just have caller flush queue */
  45. return bytes_read;
  46. case ISCSI_TCP_SKB_DONE:
  47. /*
  48. * pdus should always fit in the skb and we should get
  49. * segment done notifcation.
  50. */
  51. iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
  52. return -EFAULT;
  53. case ISCSI_TCP_SEGMENT_DONE:
  54. return bytes_read;
  55. default:
  56. iscsi_conn_printk(KERN_ERR, conn, "Invalid iscsi_tcp_recv_skb "
  57. "status %d\n", status);
  58. return -EINVAL;
  59. }
  60. }
  61. static int cxgb3i_conn_read_pdu_skb(struct iscsi_conn *conn,
  62. struct sk_buff *skb)
  63. {
  64. struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  65. bool offloaded = 0;
  66. unsigned int offset;
  67. int rc;
  68. cxgb3i_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
  69. conn, skb, skb->len, skb_ulp_mode(skb));
  70. if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
  71. iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
  72. return -EIO;
  73. }
  74. if (conn->hdrdgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_HCRC_ERROR)) {
  75. iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
  76. return -EIO;
  77. }
  78. if (conn->datadgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_DCRC_ERROR)) {
  79. iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
  80. return -EIO;
  81. }
  82. /* iscsi hdr */
  83. rc = read_pdu_skb(conn, skb, 0, 0);
  84. if (rc <= 0)
  85. return rc;
  86. if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
  87. return 0;
  88. offset = rc;
  89. if (conn->hdrdgst_en)
  90. offset += ISCSI_DIGEST_SIZE;
  91. /* iscsi data */
  92. if (skb_ulp_mode(skb) & ULP2_FLAG_DATA_DDPED) {
  93. cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, ddp'ed, "
  94. "itt 0x%x.\n",
  95. skb,
  96. tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
  97. tcp_conn->in.datalen,
  98. ntohl(tcp_conn->in.hdr->itt));
  99. offloaded = 1;
  100. } else {
  101. cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, NOT ddp'ed, "
  102. "itt 0x%x.\n",
  103. skb,
  104. tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
  105. tcp_conn->in.datalen,
  106. ntohl(tcp_conn->in.hdr->itt));
  107. offset += sizeof(struct cpl_iscsi_hdr_norss);
  108. }
  109. rc = read_pdu_skb(conn, skb, offset, offloaded);
  110. if (rc < 0)
  111. return rc;
  112. else
  113. return 0;
  114. }
  115. /*
  116. * pdu transmit, interact with libiscsi_tcp
  117. */
  118. static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
  119. {
  120. u8 submode = 0;
  121. if (hcrc)
  122. submode |= 1;
  123. if (dcrc)
  124. submode |= 2;
  125. skb_ulp_mode(skb) = (ULP_MODE_ISCSI << 4) | submode;
  126. }
  127. void cxgb3i_conn_cleanup_task(struct iscsi_task *task)
  128. {
  129. struct iscsi_tcp_task *tcp_task = task->dd_data;
  130. /* never reached the xmit task callout */
  131. if (tcp_task->dd_data)
  132. kfree_skb(tcp_task->dd_data);
  133. tcp_task->dd_data = NULL;
  134. /* MNC - Do we need a check in case this is called but
  135. * cxgb3i_conn_alloc_pdu has never been called on the task */
  136. cxgb3i_release_itt(task, task->hdr_itt);
  137. iscsi_tcp_cleanup_task(task);
  138. }
  139. /*
  140. * We do not support ahs yet
  141. */
  142. int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
  143. {
  144. struct iscsi_tcp_task *tcp_task = task->dd_data;
  145. struct sk_buff *skb;
  146. task->hdr = NULL;
  147. /* always allocate rooms for AHS */
  148. skb = alloc_skb(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE +
  149. TX_HEADER_LEN, GFP_ATOMIC);
  150. if (!skb)
  151. return -ENOMEM;
  152. cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n",
  153. task, opcode, skb);
  154. tcp_task->dd_data = skb;
  155. skb_reserve(skb, TX_HEADER_LEN);
  156. task->hdr = (struct iscsi_hdr *)skb->data;
  157. task->hdr_max = sizeof(struct iscsi_hdr);
  158. /* data_out uses scsi_cmd's itt */
  159. if (opcode != ISCSI_OP_SCSI_DATA_OUT)
  160. cxgb3i_reserve_itt(task, &task->hdr->itt);
  161. return 0;
  162. }
  163. int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
  164. unsigned int count)
  165. {
  166. struct iscsi_tcp_task *tcp_task = task->dd_data;
  167. struct sk_buff *skb = tcp_task->dd_data;
  168. struct iscsi_conn *conn = task->conn;
  169. struct page *pg;
  170. unsigned int datalen = count;
  171. int i, padlen = iscsi_padding(count);
  172. skb_frag_t *frag;
  173. cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n",
  174. task, task->sc, offset, count, skb);
  175. skb_put(skb, task->hdr_len);
  176. tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0);
  177. if (!count)
  178. return 0;
  179. if (task->sc) {
  180. struct scatterlist *sg;
  181. struct scsi_data_buffer *sdb;
  182. unsigned int sgoffset = offset;
  183. struct page *sgpg;
  184. unsigned int sglen;
  185. sdb = scsi_out(task->sc);
  186. sg = sdb->table.sgl;
  187. for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
  188. cxgb3i_tx_debug("sg %d, page 0x%p, len %u offset %u\n",
  189. i, sg_page(sg), sg->length, sg->offset);
  190. if (sgoffset < sg->length)
  191. break;
  192. sgoffset -= sg->length;
  193. }
  194. sgpg = sg_page(sg);
  195. sglen = sg->length - sgoffset;
  196. do {
  197. int j = skb_shinfo(skb)->nr_frags;
  198. unsigned int copy;
  199. if (!sglen) {
  200. sg = sg_next(sg);
  201. sgpg = sg_page(sg);
  202. sgoffset = 0;
  203. sglen = sg->length;
  204. ++i;
  205. }
  206. copy = min(sglen, datalen);
  207. if (j && skb_can_coalesce(skb, j, sgpg,
  208. sg->offset + sgoffset)) {
  209. skb_shinfo(skb)->frags[j - 1].size += copy;
  210. } else {
  211. get_page(sgpg);
  212. skb_fill_page_desc(skb, j, sgpg,
  213. sg->offset + sgoffset, copy);
  214. }
  215. sgoffset += copy;
  216. sglen -= copy;
  217. datalen -= copy;
  218. } while (datalen);
  219. } else {
  220. pg = virt_to_page(task->data);
  221. while (datalen) {
  222. i = skb_shinfo(skb)->nr_frags;
  223. frag = &skb_shinfo(skb)->frags[i];
  224. get_page(pg);
  225. frag->page = pg;
  226. frag->page_offset = 0;
  227. frag->size = min((unsigned int)PAGE_SIZE, datalen);
  228. skb_shinfo(skb)->nr_frags++;
  229. datalen -= frag->size;
  230. pg++;
  231. }
  232. }
  233. if (padlen) {
  234. i = skb_shinfo(skb)->nr_frags;
  235. frag = &skb_shinfo(skb)->frags[i];
  236. frag->page = pad_page;
  237. frag->page_offset = 0;
  238. frag->size = padlen;
  239. skb_shinfo(skb)->nr_frags++;
  240. }
  241. datalen = count + padlen;
  242. skb->data_len += datalen;
  243. skb->truesize += datalen;
  244. skb->len += datalen;
  245. return 0;
  246. }
  247. int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
  248. {
  249. struct iscsi_tcp_task *tcp_task = task->dd_data;
  250. struct sk_buff *skb = tcp_task->dd_data;
  251. struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
  252. struct cxgb3i_conn *cconn = tcp_conn->dd_data;
  253. unsigned int datalen;
  254. int err;
  255. if (!skb)
  256. return 0;
  257. datalen = skb->data_len;
  258. tcp_task->dd_data = NULL;
  259. err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb);
  260. cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
  261. task, skb, skb->len, skb->data_len, err);
  262. if (err > 0) {
  263. int pdulen = err;
  264. if (task->conn->hdrdgst_en)
  265. pdulen += ISCSI_DIGEST_SIZE;
  266. if (datalen && task->conn->datadgst_en)
  267. pdulen += ISCSI_DIGEST_SIZE;
  268. task->conn->txdata_octets += pdulen;
  269. return 0;
  270. }
  271. if (err < 0 && err != -EAGAIN) {
  272. kfree_skb(skb);
  273. cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
  274. task->itt, skb, skb->len, skb->data_len, err);
  275. iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
  276. iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
  277. return err;
  278. }
  279. /* reset skb to send when we are called again */
  280. tcp_task->dd_data = skb;
  281. return -EAGAIN;
  282. }
  283. int cxgb3i_pdu_init(void)
  284. {
  285. pad_page = alloc_page(GFP_KERNEL);
  286. if (!pad_page)
  287. return -ENOMEM;
  288. memset(page_address(pad_page), 0, PAGE_SIZE);
  289. return 0;
  290. }
  291. void cxgb3i_pdu_cleanup(void)
  292. {
  293. if (pad_page) {
  294. __free_page(pad_page);
  295. pad_page = NULL;
  296. }
  297. }
  298. void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
  299. {
  300. struct sk_buff *skb;
  301. unsigned int read = 0;
  302. struct iscsi_conn *conn = c3cn->user_data;
  303. int err = 0;
  304. cxgb3i_rx_debug("cn 0x%p.\n", c3cn);
  305. read_lock(&c3cn->callback_lock);
  306. if (unlikely(!conn || conn->suspend_rx)) {
  307. cxgb3i_rx_debug("conn 0x%p, id %d, suspend_rx %lu!\n",
  308. conn, conn ? conn->id : 0xFF,
  309. conn ? conn->suspend_rx : 0xFF);
  310. read_unlock(&c3cn->callback_lock);
  311. return;
  312. }
  313. skb = skb_peek(&c3cn->receive_queue);
  314. while (!err && skb) {
  315. __skb_unlink(skb, &c3cn->receive_queue);
  316. read += skb_ulp_pdulen(skb);
  317. err = cxgb3i_conn_read_pdu_skb(conn, skb);
  318. __kfree_skb(skb);
  319. skb = skb_peek(&c3cn->receive_queue);
  320. }
  321. read_unlock(&c3cn->callback_lock);
  322. if (c3cn) {
  323. c3cn->copied_seq += read;
  324. cxgb3i_c3cn_rx_credits(c3cn, read);
  325. }
  326. conn->rxdata_octets += read;
  327. }
  328. void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
  329. {
  330. struct iscsi_conn *conn = c3cn->user_data;
  331. cxgb3i_tx_debug("cn 0x%p.\n", c3cn);
  332. if (conn) {
  333. cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id);
  334. scsi_queue_work(conn->session->host, &conn->xmitwork);
  335. }
  336. }
  337. void cxgb3i_conn_closing(struct s3_conn *c3cn)
  338. {
  339. struct iscsi_conn *conn;
  340. read_lock(&c3cn->callback_lock);
  341. conn = c3cn->user_data;
  342. if (conn && c3cn->state != C3CN_STATE_ESTABLISHED)
  343. iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
  344. read_unlock(&c3cn->callback_lock);
  345. }