cxgb3i_iscsi.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. /* cxgb3i_iscsi.c: Chelsio S3xx iSCSI driver.
  2. *
  3. * Copyright (c) 2008 Chelsio Communications, Inc.
  4. * Copyright (c) 2008 Mike Christie
  5. * Copyright (c) 2008 Red Hat, Inc. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation.
  10. *
  11. * Written by: Karen Xie (kxie@chelsio.com)
  12. */
  13. #include <linux/inet.h>
  14. #include <linux/crypto.h>
  15. #include <net/tcp.h>
  16. #include <scsi/scsi_cmnd.h>
  17. #include <scsi/scsi_device.h>
  18. #include <scsi/scsi_eh.h>
  19. #include <scsi/scsi_host.h>
  20. #include <scsi/scsi.h>
  21. #include <scsi/iscsi_proto.h>
  22. #include <scsi/libiscsi.h>
  23. #include <scsi/scsi_transport_iscsi.h>
  24. #include "cxgb3i.h"
  25. #include "cxgb3i_pdu.h"
  26. #ifdef __DEBUG_CXGB3I_TAG__
  27. #define cxgb3i_tag_debug cxgb3i_log_debug
  28. #else
  29. #define cxgb3i_tag_debug(fmt...)
  30. #endif
  31. #ifdef __DEBUG_CXGB3I_API__
  32. #define cxgb3i_api_debug cxgb3i_log_debug
  33. #else
  34. #define cxgb3i_api_debug(fmt...)
  35. #endif
  36. /*
  37. * align pdu size to multiple of 512 for better performance
  38. */
  39. #define align_pdu_size(n) do { n = (n) & (~511); } while (0)
  40. static struct scsi_transport_template *cxgb3i_scsi_transport;
  41. static struct scsi_host_template cxgb3i_host_template;
  42. static struct iscsi_transport cxgb3i_iscsi_transport;
  43. static unsigned char sw_tag_idx_bits;
  44. static unsigned char sw_tag_age_bits;
  45. static LIST_HEAD(cxgb3i_snic_list);
  46. static DEFINE_RWLOCK(cxgb3i_snic_rwlock);
  47. /**
  48. * cxgb3i_adapter_add - init a s3 adapter structure and any h/w settings
  49. * @t3dev: t3cdev adapter
  50. * return the resulting cxgb3i_adapter struct
  51. */
  52. struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev)
  53. {
  54. struct cxgb3i_adapter *snic;
  55. struct adapter *adapter = tdev2adap(t3dev);
  56. int i;
  57. snic = kzalloc(sizeof(*snic), GFP_KERNEL);
  58. if (!snic) {
  59. cxgb3i_api_debug("cxgb3 %s, OOM.\n", t3dev->name);
  60. return NULL;
  61. }
  62. spin_lock_init(&snic->lock);
  63. snic->tdev = t3dev;
  64. snic->pdev = adapter->pdev;
  65. snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
  66. if (cxgb3i_adapter_ddp_init(t3dev, &snic->tag_format,
  67. &snic->tx_max_size,
  68. &snic->rx_max_size) < 0)
  69. goto free_snic;
  70. for_each_port(adapter, i) {
  71. snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
  72. if (!snic->hba[i])
  73. goto ulp_cleanup;
  74. }
  75. snic->hba_cnt = adapter->params.nports;
  76. /* add to the list */
  77. write_lock(&cxgb3i_snic_rwlock);
  78. list_add_tail(&snic->list_head, &cxgb3i_snic_list);
  79. write_unlock(&cxgb3i_snic_rwlock);
  80. return snic;
  81. ulp_cleanup:
  82. cxgb3i_adapter_ddp_cleanup(t3dev);
  83. free_snic:
  84. kfree(snic);
  85. return NULL;
  86. }
  87. /**
  88. * cxgb3i_adapter_remove - release the resources held and cleanup h/w settings
  89. * @t3dev: t3cdev adapter
  90. */
  91. void cxgb3i_adapter_remove(struct t3cdev *t3dev)
  92. {
  93. int i;
  94. struct cxgb3i_adapter *snic;
  95. /* remove from the list */
  96. write_lock(&cxgb3i_snic_rwlock);
  97. list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
  98. if (snic->tdev == t3dev) {
  99. list_del(&snic->list_head);
  100. break;
  101. }
  102. }
  103. write_unlock(&cxgb3i_snic_rwlock);
  104. if (snic) {
  105. for (i = 0; i < snic->hba_cnt; i++) {
  106. if (snic->hba[i]) {
  107. cxgb3i_hba_host_remove(snic->hba[i]);
  108. snic->hba[i] = NULL;
  109. }
  110. }
  111. /* release ddp resources */
  112. cxgb3i_adapter_ddp_cleanup(snic->tdev);
  113. kfree(snic);
  114. }
  115. }
  116. /**
  117. * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
  118. * @t3dev: t3cdev adapter
  119. */
  120. struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
  121. {
  122. struct cxgb3i_adapter *snic;
  123. int i;
  124. read_lock(&cxgb3i_snic_rwlock);
  125. list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
  126. for (i = 0; i < snic->hba_cnt; i++) {
  127. if (snic->hba[i]->ndev == ndev) {
  128. read_unlock(&cxgb3i_snic_rwlock);
  129. return snic->hba[i];
  130. }
  131. }
  132. }
  133. read_unlock(&cxgb3i_snic_rwlock);
  134. return NULL;
  135. }
  136. /**
  137. * cxgb3i_hba_host_add - register a new host with scsi/iscsi
  138. * @snic: the cxgb3i adapter
  139. * @ndev: associated net_device
  140. */
  141. struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
  142. struct net_device *ndev)
  143. {
  144. struct cxgb3i_hba *hba;
  145. struct Scsi_Host *shost;
  146. int err;
  147. shost = iscsi_host_alloc(&cxgb3i_host_template,
  148. sizeof(struct cxgb3i_hba), 1);
  149. if (!shost) {
  150. cxgb3i_log_info("iscsi_host_alloc failed.\n");
  151. return NULL;
  152. }
  153. shost->transportt = cxgb3i_scsi_transport;
  154. shost->max_lun = CXGB3I_MAX_LUN;
  155. shost->max_id = CXGB3I_MAX_TARGET;
  156. shost->max_channel = 0;
  157. shost->max_cmd_len = 16;
  158. hba = iscsi_host_priv(shost);
  159. hba->snic = snic;
  160. hba->ndev = ndev;
  161. hba->shost = shost;
  162. pci_dev_get(snic->pdev);
  163. err = iscsi_host_add(shost, &snic->pdev->dev);
  164. if (err) {
  165. cxgb3i_log_info("iscsi_host_add failed.\n");
  166. goto pci_dev_put;
  167. }
  168. cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
  169. shost, hba, shost->host_no);
  170. return hba;
  171. pci_dev_put:
  172. pci_dev_put(snic->pdev);
  173. scsi_host_put(shost);
  174. return NULL;
  175. }
  176. /**
  177. * cxgb3i_hba_host_remove - de-register the host with scsi/iscsi
  178. * @hba: the cxgb3i hba
  179. */
  180. void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)
  181. {
  182. cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
  183. hba->shost, hba, hba->shost->host_no);
  184. iscsi_host_remove(hba->shost);
  185. pci_dev_put(hba->snic->pdev);
  186. iscsi_host_free(hba->shost);
  187. }
  188. /**
  189. * cxgb3i_ep_connect - establish TCP connection to target portal
  190. * @dst_addr: target IP address
  191. * @non_blocking: blocking or non-blocking call
  192. *
  193. * Initiates a TCP/IP connection to the dst_addr
  194. */
  195. static struct iscsi_endpoint *cxgb3i_ep_connect(struct sockaddr *dst_addr,
  196. int non_blocking)
  197. {
  198. struct iscsi_endpoint *ep;
  199. struct cxgb3i_endpoint *cep;
  200. struct cxgb3i_hba *hba;
  201. struct s3_conn *c3cn = NULL;
  202. int err = 0;
  203. c3cn = cxgb3i_c3cn_create();
  204. if (!c3cn) {
  205. cxgb3i_log_info("ep connect OOM.\n");
  206. err = -ENOMEM;
  207. goto release_conn;
  208. }
  209. err = cxgb3i_c3cn_connect(c3cn, (struct sockaddr_in *)dst_addr);
  210. if (err < 0) {
  211. cxgb3i_log_info("ep connect failed.\n");
  212. goto release_conn;
  213. }
  214. hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev);
  215. if (!hba) {
  216. err = -ENOSPC;
  217. cxgb3i_log_info("NOT going through cxgbi device.\n");
  218. goto release_conn;
  219. }
  220. if (c3cn_is_closing(c3cn)) {
  221. err = -ENOSPC;
  222. cxgb3i_log_info("ep connect unable to connect.\n");
  223. goto release_conn;
  224. }
  225. ep = iscsi_create_endpoint(sizeof(*cep));
  226. if (!ep) {
  227. err = -ENOMEM;
  228. cxgb3i_log_info("iscsi alloc ep, OOM.\n");
  229. goto release_conn;
  230. }
  231. cep = ep->dd_data;
  232. cep->c3cn = c3cn;
  233. cep->hba = hba;
  234. cxgb3i_api_debug("ep 0x%p, 0x%p, c3cn 0x%p, hba 0x%p.\n",
  235. ep, cep, c3cn, hba);
  236. return ep;
  237. release_conn:
  238. cxgb3i_api_debug("conn 0x%p failed, release.\n", c3cn);
  239. if (c3cn)
  240. cxgb3i_c3cn_release(c3cn);
  241. return ERR_PTR(err);
  242. }
  243. /**
  244. * cxgb3i_ep_poll - polls for TCP connection establishement
  245. * @ep: TCP connection (endpoint) handle
  246. * @timeout_ms: timeout value in milli secs
  247. *
  248. * polls for TCP connect request to complete
  249. */
  250. static int cxgb3i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
  251. {
  252. struct cxgb3i_endpoint *cep = ep->dd_data;
  253. struct s3_conn *c3cn = cep->c3cn;
  254. if (!c3cn_is_established(c3cn))
  255. return 0;
  256. cxgb3i_api_debug("ep 0x%p, c3cn 0x%p established.\n", ep, c3cn);
  257. return 1;
  258. }
  259. /**
  260. * cxgb3i_ep_disconnect - teardown TCP connection
  261. * @ep: TCP connection (endpoint) handle
  262. *
  263. * teardown TCP connection
  264. */
  265. static void cxgb3i_ep_disconnect(struct iscsi_endpoint *ep)
  266. {
  267. struct cxgb3i_endpoint *cep = ep->dd_data;
  268. struct cxgb3i_conn *cconn = cep->cconn;
  269. cxgb3i_api_debug("ep 0x%p, cep 0x%p.\n", ep, cep);
  270. if (cconn && cconn->conn) {
  271. /*
  272. * stop the xmit path so the xmit_pdu function is
  273. * not being called
  274. */
  275. iscsi_suspend_tx(cconn->conn);
  276. write_lock_bh(&cep->c3cn->callback_lock);
  277. cep->c3cn->user_data = NULL;
  278. cconn->cep = NULL;
  279. write_unlock_bh(&cep->c3cn->callback_lock);
  280. }
  281. cxgb3i_api_debug("ep 0x%p, cep 0x%p, release c3cn 0x%p.\n",
  282. ep, cep, cep->c3cn);
  283. cxgb3i_c3cn_release(cep->c3cn);
  284. iscsi_destroy_endpoint(ep);
  285. }
  286. /**
  287. * cxgb3i_session_create - create a new iscsi session
  288. * @cmds_max: max # of commands
  289. * @qdepth: scsi queue depth
  290. * @initial_cmdsn: initial iscsi CMDSN for this session
  291. *
  292. * Creates a new iSCSI session
  293. */
  294. static struct iscsi_cls_session *
  295. cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
  296. u32 initial_cmdsn)
  297. {
  298. struct cxgb3i_endpoint *cep;
  299. struct cxgb3i_hba *hba;
  300. struct Scsi_Host *shost;
  301. struct iscsi_cls_session *cls_session;
  302. struct iscsi_session *session;
  303. if (!ep) {
  304. cxgb3i_log_error("%s, missing endpoint.\n", __func__);
  305. return NULL;
  306. }
  307. cep = ep->dd_data;
  308. hba = cep->hba;
  309. shost = hba->shost;
  310. cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep, cep, hba);
  311. BUG_ON(hba != iscsi_host_priv(shost));
  312. cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
  313. cmds_max,
  314. sizeof(struct iscsi_tcp_task) +
  315. sizeof(struct cxgb3i_task_data),
  316. initial_cmdsn, ISCSI_MAX_TARGET);
  317. if (!cls_session)
  318. return NULL;
  319. session = cls_session->dd_data;
  320. if (iscsi_tcp_r2tpool_alloc(session))
  321. goto remove_session;
  322. return cls_session;
  323. remove_session:
  324. iscsi_session_teardown(cls_session);
  325. return NULL;
  326. }
  327. /**
  328. * cxgb3i_session_destroy - destroys iscsi session
  329. * @cls_session: pointer to iscsi cls session
  330. *
  331. * Destroys an iSCSI session instance and releases its all resources held
  332. */
  333. static void cxgb3i_session_destroy(struct iscsi_cls_session *cls_session)
  334. {
  335. cxgb3i_api_debug("sess 0x%p.\n", cls_session);
  336. iscsi_tcp_r2tpool_free(cls_session->dd_data);
  337. iscsi_session_teardown(cls_session);
  338. }
  339. /**
  340. * cxgb3i_conn_max_xmit_dlength -- calc the max. xmit pdu segment size
  341. * @conn: iscsi connection
  342. * check the max. xmit pdu payload, reduce it if needed
  343. */
  344. static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn)
  345. {
  346. struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  347. struct cxgb3i_conn *cconn = tcp_conn->dd_data;
  348. unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM);
  349. max = min(cconn->hba->snic->tx_max_size, max);
  350. if (conn->max_xmit_dlength)
  351. conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
  352. else
  353. conn->max_xmit_dlength = max;
  354. align_pdu_size(conn->max_xmit_dlength);
  355. cxgb3i_api_debug("conn 0x%p, max xmit %u.\n",
  356. conn, conn->max_xmit_dlength);
  357. return 0;
  358. }
  359. /**
  360. * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size
  361. * @conn: iscsi connection
  362. * return 0 if the value is valid, < 0 otherwise.
  363. */
  364. static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn)
  365. {
  366. struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  367. struct cxgb3i_conn *cconn = tcp_conn->dd_data;
  368. unsigned int max = cconn->hba->snic->rx_max_size;
  369. align_pdu_size(max);
  370. if (conn->max_recv_dlength) {
  371. if (conn->max_recv_dlength > max) {
  372. cxgb3i_log_error("MaxRecvDataSegmentLength %u too big."
  373. " Need to be <= %u.\n",
  374. conn->max_recv_dlength, max);
  375. return -EINVAL;
  376. }
  377. conn->max_recv_dlength = min(conn->max_recv_dlength, max);
  378. align_pdu_size(conn->max_recv_dlength);
  379. } else
  380. conn->max_recv_dlength = max;
  381. cxgb3i_api_debug("conn 0x%p, max recv %u.\n",
  382. conn, conn->max_recv_dlength);
  383. return 0;
  384. }
  385. /**
  386. * cxgb3i_conn_create - create iscsi connection instance
  387. * @cls_session: pointer to iscsi cls session
  388. * @cid: iscsi cid
  389. *
  390. * Creates a new iSCSI connection instance for a given session
  391. */
  392. static struct iscsi_cls_conn *cxgb3i_conn_create(struct iscsi_cls_session
  393. *cls_session, u32 cid)
  394. {
  395. struct iscsi_cls_conn *cls_conn;
  396. struct iscsi_conn *conn;
  397. struct iscsi_tcp_conn *tcp_conn;
  398. struct cxgb3i_conn *cconn;
  399. cxgb3i_api_debug("sess 0x%p, cid %u.\n", cls_session, cid);
  400. cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
  401. if (!cls_conn)
  402. return NULL;
  403. conn = cls_conn->dd_data;
  404. tcp_conn = conn->dd_data;
  405. cconn = tcp_conn->dd_data;
  406. cconn->conn = conn;
  407. return cls_conn;
  408. }
  409. /**
  410. * cxgb3i_conn_bind - binds iscsi sess, conn and endpoint together
  411. * @cls_session: pointer to iscsi cls session
  412. * @cls_conn: pointer to iscsi cls conn
  413. * @transport_eph: 64-bit EP handle
  414. * @is_leading: leading connection on this session?
  415. *
  416. * Binds together an iSCSI session, an iSCSI connection and a
  417. * TCP connection. This routine returns error code if the TCP
  418. * connection does not belong on the device iSCSI sess/conn is bound
  419. */
  420. static int cxgb3i_conn_bind(struct iscsi_cls_session *cls_session,
  421. struct iscsi_cls_conn *cls_conn,
  422. u64 transport_eph, int is_leading)
  423. {
  424. struct iscsi_conn *conn = cls_conn->dd_data;
  425. struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  426. struct cxgb3i_conn *cconn = tcp_conn->dd_data;
  427. struct cxgb3i_adapter *snic;
  428. struct iscsi_endpoint *ep;
  429. struct cxgb3i_endpoint *cep;
  430. struct s3_conn *c3cn;
  431. int err;
  432. ep = iscsi_lookup_endpoint(transport_eph);
  433. if (!ep)
  434. return -EINVAL;
  435. /* setup ddp pagesize */
  436. cep = ep->dd_data;
  437. c3cn = cep->c3cn;
  438. snic = cep->hba->snic;
  439. err = cxgb3i_setup_conn_host_pagesize(snic->tdev, c3cn->tid, 0);
  440. if (err < 0)
  441. return err;
  442. cxgb3i_api_debug("ep 0x%p, cls sess 0x%p, cls conn 0x%p.\n",
  443. ep, cls_session, cls_conn);
  444. err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
  445. if (err)
  446. return -EINVAL;
  447. /* calculate the tag idx bits needed for this conn based on cmds_max */
  448. cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
  449. cxgb3i_api_debug("session cmds_max 0x%x, bits %u.\n",
  450. conn->session->cmds_max, cconn->task_idx_bits);
  451. read_lock(&c3cn->callback_lock);
  452. c3cn->user_data = conn;
  453. cconn->hba = cep->hba;
  454. cconn->cep = cep;
  455. cep->cconn = cconn;
  456. read_unlock(&c3cn->callback_lock);
  457. cxgb3i_conn_max_xmit_dlength(conn);
  458. cxgb3i_conn_max_recv_dlength(conn);
  459. spin_lock_bh(&conn->session->lock);
  460. sprintf(conn->portal_address, NIPQUAD_FMT,
  461. NIPQUAD(c3cn->daddr.sin_addr.s_addr));
  462. conn->portal_port = ntohs(c3cn->daddr.sin_port);
  463. spin_unlock_bh(&conn->session->lock);
  464. /* init recv engine */
  465. iscsi_tcp_hdr_recv_prep(tcp_conn);
  466. return 0;
  467. }
  468. /**
  469. * cxgb3i_conn_get_param - return iscsi connection parameter to caller
  470. * @cls_conn: pointer to iscsi cls conn
  471. * @param: parameter type identifier
  472. * @buf: buffer pointer
  473. *
  474. * returns iSCSI connection parameters
  475. */
  476. static int cxgb3i_conn_get_param(struct iscsi_cls_conn *cls_conn,
  477. enum iscsi_param param, char *buf)
  478. {
  479. struct iscsi_conn *conn = cls_conn->dd_data;
  480. int len;
  481. cxgb3i_api_debug("cls_conn 0x%p, param %d.\n", cls_conn, param);
  482. switch (param) {
  483. case ISCSI_PARAM_CONN_PORT:
  484. spin_lock_bh(&conn->session->lock);
  485. len = sprintf(buf, "%hu\n", conn->portal_port);
  486. spin_unlock_bh(&conn->session->lock);
  487. break;
  488. case ISCSI_PARAM_CONN_ADDRESS:
  489. spin_lock_bh(&conn->session->lock);
  490. len = sprintf(buf, "%s\n", conn->portal_address);
  491. spin_unlock_bh(&conn->session->lock);
  492. break;
  493. default:
  494. return iscsi_conn_get_param(cls_conn, param, buf);
  495. }
  496. return len;
  497. }
  498. /**
  499. * cxgb3i_conn_set_param - set iscsi connection parameter
  500. * @cls_conn: pointer to iscsi cls conn
  501. * @param: parameter type identifier
  502. * @buf: buffer pointer
  503. * @buflen: buffer length
  504. *
  505. * set iSCSI connection parameters
  506. */
  507. static int cxgb3i_conn_set_param(struct iscsi_cls_conn *cls_conn,
  508. enum iscsi_param param, char *buf, int buflen)
  509. {
  510. struct iscsi_conn *conn = cls_conn->dd_data;
  511. struct iscsi_session *session = conn->session;
  512. struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  513. struct cxgb3i_conn *cconn = tcp_conn->dd_data;
  514. struct cxgb3i_adapter *snic = cconn->hba->snic;
  515. struct s3_conn *c3cn = cconn->cep->c3cn;
  516. int value, err = 0;
  517. switch (param) {
  518. case ISCSI_PARAM_HDRDGST_EN:
  519. err = iscsi_set_param(cls_conn, param, buf, buflen);
  520. if (!err && conn->hdrdgst_en)
  521. err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid,
  522. conn->hdrdgst_en,
  523. conn->datadgst_en, 0);
  524. break;
  525. case ISCSI_PARAM_DATADGST_EN:
  526. err = iscsi_set_param(cls_conn, param, buf, buflen);
  527. if (!err && conn->datadgst_en)
  528. err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid,
  529. conn->hdrdgst_en,
  530. conn->datadgst_en, 0);
  531. break;
  532. case ISCSI_PARAM_MAX_R2T:
  533. sscanf(buf, "%d", &value);
  534. if (value <= 0 || !is_power_of_2(value))
  535. return -EINVAL;
  536. if (session->max_r2t == value)
  537. break;
  538. iscsi_tcp_r2tpool_free(session);
  539. err = iscsi_set_param(cls_conn, param, buf, buflen);
  540. if (!err && iscsi_tcp_r2tpool_alloc(session))
  541. return -ENOMEM;
  542. case ISCSI_PARAM_MAX_RECV_DLENGTH:
  543. err = iscsi_set_param(cls_conn, param, buf, buflen);
  544. if (!err)
  545. err = cxgb3i_conn_max_recv_dlength(conn);
  546. break;
  547. case ISCSI_PARAM_MAX_XMIT_DLENGTH:
  548. err = iscsi_set_param(cls_conn, param, buf, buflen);
  549. if (!err)
  550. err = cxgb3i_conn_max_xmit_dlength(conn);
  551. break;
  552. default:
  553. return iscsi_set_param(cls_conn, param, buf, buflen);
  554. }
  555. return err;
  556. }
  557. /**
  558. * cxgb3i_host_set_param - configure host (adapter) related parameters
  559. * @shost: scsi host pointer
  560. * @param: parameter type identifier
  561. * @buf: buffer pointer
  562. */
  563. static int cxgb3i_host_set_param(struct Scsi_Host *shost,
  564. enum iscsi_host_param param,
  565. char *buf, int buflen)
  566. {
  567. struct cxgb3i_hba *hba = iscsi_host_priv(shost);
  568. cxgb3i_api_debug("param %d, buf %s.\n", param, buf);
  569. switch (param) {
  570. case ISCSI_HOST_PARAM_IPADDRESS:
  571. {
  572. __be32 addr = in_aton(buf);
  573. cxgb3i_set_private_ipv4addr(hba->ndev, addr);
  574. return 0;
  575. }
  576. case ISCSI_HOST_PARAM_HWADDRESS:
  577. case ISCSI_HOST_PARAM_NETDEV_NAME:
  578. /* ignore */
  579. return 0;
  580. default:
  581. return iscsi_host_set_param(shost, param, buf, buflen);
  582. }
  583. }
  584. /**
  585. * cxgb3i_host_get_param - returns host (adapter) related parameters
  586. * @shost: scsi host pointer
  587. * @param: parameter type identifier
  588. * @buf: buffer pointer
  589. */
  590. static int cxgb3i_host_get_param(struct Scsi_Host *shost,
  591. enum iscsi_host_param param, char *buf)
  592. {
  593. struct cxgb3i_hba *hba = iscsi_host_priv(shost);
  594. int len = 0;
  595. cxgb3i_api_debug("hba %s, param %d.\n", hba->ndev->name, param);
  596. switch (param) {
  597. case ISCSI_HOST_PARAM_HWADDRESS:
  598. len = sysfs_format_mac(buf, hba->ndev->dev_addr, 6);
  599. break;
  600. case ISCSI_HOST_PARAM_NETDEV_NAME:
  601. len = sprintf(buf, "%s\n", hba->ndev->name);
  602. break;
  603. case ISCSI_HOST_PARAM_IPADDRESS:
  604. {
  605. __be32 addr;
  606. addr = cxgb3i_get_private_ipv4addr(hba->ndev);
  607. len = sprintf(buf, NIPQUAD_FMT, NIPQUAD(addr));
  608. break;
  609. }
  610. default:
  611. return iscsi_host_get_param(shost, param, buf);
  612. }
  613. return len;
  614. }
  615. /**
  616. * cxgb3i_conn_get_stats - returns iSCSI stats
  617. * @cls_conn: pointer to iscsi cls conn
  618. * @stats: pointer to iscsi statistic struct
  619. */
  620. static void cxgb3i_conn_get_stats(struct iscsi_cls_conn *cls_conn,
  621. struct iscsi_stats *stats)
  622. {
  623. struct iscsi_conn *conn = cls_conn->dd_data;
  624. stats->txdata_octets = conn->txdata_octets;
  625. stats->rxdata_octets = conn->rxdata_octets;
  626. stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
  627. stats->dataout_pdus = conn->dataout_pdus_cnt;
  628. stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
  629. stats->datain_pdus = conn->datain_pdus_cnt;
  630. stats->r2t_pdus = conn->r2t_pdus_cnt;
  631. stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
  632. stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
  633. stats->digest_err = 0;
  634. stats->timeout_err = 0;
  635. stats->custom_length = 1;
  636. strcpy(stats->custom[0].desc, "eh_abort_cnt");
  637. stats->custom[0].value = conn->eh_abort_cnt;
  638. }
  639. /**
  640. * cxgb3i_parse_itt - get the idx and age bits from a given tag
  641. * @conn: iscsi connection
  642. * @itt: itt tag
  643. * @idx: task index, filled in by this function
  644. * @age: session age, filled in by this function
  645. */
  646. static void cxgb3i_parse_itt(struct iscsi_conn *conn, itt_t itt,
  647. int *idx, int *age)
  648. {
  649. struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  650. struct cxgb3i_conn *cconn = tcp_conn->dd_data;
  651. struct cxgb3i_adapter *snic = cconn->hba->snic;
  652. u32 tag = ntohl((__force u32) itt);
  653. u32 sw_bits;
  654. sw_bits = cxgb3i_tag_nonrsvd_bits(&snic->tag_format, tag);
  655. if (idx)
  656. *idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
  657. if (age)
  658. *age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
  659. cxgb3i_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n",
  660. tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
  661. age ? *age : 0xFF);
  662. }
  663. /**
  664. * cxgb3i_reserve_itt - generate tag for a give task
  665. * @task: iscsi task
  666. * @hdr_itt: tag, filled in by this function
  667. * Set up ddp for scsi read tasks if possible.
  668. */
  669. int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
  670. {
  671. struct scsi_cmnd *sc = task->sc;
  672. struct iscsi_conn *conn = task->conn;
  673. struct iscsi_session *sess = conn->session;
  674. struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
  675. struct cxgb3i_conn *cconn = tcp_conn->dd_data;
  676. struct cxgb3i_adapter *snic = cconn->hba->snic;
  677. struct cxgb3i_tag_format *tformat = &snic->tag_format;
  678. u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
  679. u32 tag;
  680. int err = -EINVAL;
  681. if (sc &&
  682. (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
  683. cxgb3i_sw_tag_usable(tformat, sw_tag)) {
  684. struct s3_conn *c3cn = cconn->cep->c3cn;
  685. struct cxgb3i_gather_list *gl;
  686. gl = cxgb3i_ddp_make_gl(scsi_in(sc)->length,
  687. scsi_in(sc)->table.sgl,
  688. scsi_in(sc)->table.nents,
  689. snic->pdev,
  690. GFP_ATOMIC);
  691. if (gl) {
  692. tag = sw_tag;
  693. err = cxgb3i_ddp_tag_reserve(snic->tdev, c3cn->tid,
  694. tformat, &tag,
  695. gl, GFP_ATOMIC);
  696. if (err < 0)
  697. cxgb3i_ddp_release_gl(gl, snic->pdev);
  698. }
  699. }
  700. if (err < 0)
  701. tag = cxgb3i_set_non_ddp_tag(tformat, sw_tag);
  702. /* the itt need to sent in big-endian order */
  703. *hdr_itt = (__force itt_t)htonl(tag);
  704. cxgb3i_tag_debug("new tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n",
  705. tag, *hdr_itt, task->itt, sess->age);
  706. return 0;
  707. }
  708. /**
  709. * cxgb3i_release_itt - release the tag for a given task
  710. * @task: iscsi task
  711. * @hdr_itt: tag
  712. * If the tag is a ddp tag, release the ddp setup
  713. */
  714. void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt)
  715. {
  716. struct scsi_cmnd *sc = task->sc;
  717. struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
  718. struct cxgb3i_conn *cconn = tcp_conn->dd_data;
  719. struct cxgb3i_adapter *snic = cconn->hba->snic;
  720. struct cxgb3i_tag_format *tformat = &snic->tag_format;
  721. u32 tag = ntohl((__force u32)hdr_itt);
  722. cxgb3i_tag_debug("release tag 0x%x.\n", tag);
  723. if (sc &&
  724. (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
  725. cxgb3i_is_ddp_tag(tformat, tag))
  726. cxgb3i_ddp_tag_release(snic->tdev, tag);
  727. }
  728. /**
  729. * cxgb3i_host_template -- Scsi_Host_Template structure
  730. * used when registering with the scsi mid layer
  731. */
  732. static struct scsi_host_template cxgb3i_host_template = {
  733. .module = THIS_MODULE,
  734. .name = "Chelsio S3xx iSCSI Initiator",
  735. .proc_name = "cxgb3i",
  736. .queuecommand = iscsi_queuecommand,
  737. .change_queue_depth = iscsi_change_queue_depth,
  738. .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1,
  739. .sg_tablesize = SG_ALL,
  740. .max_sectors = 0xFFFF,
  741. .cmd_per_lun = CXGB3I_SCSI_QDEPTH_DFLT,
  742. .eh_abort_handler = iscsi_eh_abort,
  743. .eh_device_reset_handler = iscsi_eh_device_reset,
  744. .eh_target_reset_handler = iscsi_eh_target_reset,
  745. .use_clustering = DISABLE_CLUSTERING,
  746. .this_id = -1,
  747. };
  748. static struct iscsi_transport cxgb3i_iscsi_transport = {
  749. .owner = THIS_MODULE,
  750. .name = "cxgb3i",
  751. .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
  752. | CAP_DATADGST | CAP_DIGEST_OFFLOAD |
  753. CAP_PADDING_OFFLOAD,
  754. .param_mask = ISCSI_MAX_RECV_DLENGTH |
  755. ISCSI_MAX_XMIT_DLENGTH |
  756. ISCSI_HDRDGST_EN |
  757. ISCSI_DATADGST_EN |
  758. ISCSI_INITIAL_R2T_EN |
  759. ISCSI_MAX_R2T |
  760. ISCSI_IMM_DATA_EN |
  761. ISCSI_FIRST_BURST |
  762. ISCSI_MAX_BURST |
  763. ISCSI_PDU_INORDER_EN |
  764. ISCSI_DATASEQ_INORDER_EN |
  765. ISCSI_ERL |
  766. ISCSI_CONN_PORT |
  767. ISCSI_CONN_ADDRESS |
  768. ISCSI_EXP_STATSN |
  769. ISCSI_PERSISTENT_PORT |
  770. ISCSI_PERSISTENT_ADDRESS |
  771. ISCSI_TARGET_NAME | ISCSI_TPGT |
  772. ISCSI_USERNAME | ISCSI_PASSWORD |
  773. ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
  774. ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
  775. ISCSI_LU_RESET_TMO |
  776. ISCSI_PING_TMO | ISCSI_RECV_TMO |
  777. ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
  778. .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
  779. ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_NETDEV_NAME,
  780. .get_host_param = cxgb3i_host_get_param,
  781. .set_host_param = cxgb3i_host_set_param,
  782. /* session management */
  783. .create_session = cxgb3i_session_create,
  784. .destroy_session = cxgb3i_session_destroy,
  785. .get_session_param = iscsi_session_get_param,
  786. /* connection management */
  787. .create_conn = cxgb3i_conn_create,
  788. .bind_conn = cxgb3i_conn_bind,
  789. .destroy_conn = iscsi_tcp_conn_teardown,
  790. .start_conn = iscsi_conn_start,
  791. .stop_conn = iscsi_conn_stop,
  792. .get_conn_param = cxgb3i_conn_get_param,
  793. .set_param = cxgb3i_conn_set_param,
  794. .get_stats = cxgb3i_conn_get_stats,
  795. /* pdu xmit req. from user space */
  796. .send_pdu = iscsi_conn_send_pdu,
  797. /* task */
  798. .init_task = iscsi_tcp_task_init,
  799. .xmit_task = iscsi_tcp_task_xmit,
  800. .cleanup_task = cxgb3i_conn_cleanup_task,
  801. /* pdu */
  802. .alloc_pdu = cxgb3i_conn_alloc_pdu,
  803. .init_pdu = cxgb3i_conn_init_pdu,
  804. .xmit_pdu = cxgb3i_conn_xmit_pdu,
  805. .parse_pdu_itt = cxgb3i_parse_itt,
  806. /* TCP connect/disconnect */
  807. .ep_connect = cxgb3i_ep_connect,
  808. .ep_poll = cxgb3i_ep_poll,
  809. .ep_disconnect = cxgb3i_ep_disconnect,
  810. /* Error recovery timeout call */
  811. .session_recovery_timedout = iscsi_session_recovery_timedout,
  812. };
  813. int cxgb3i_iscsi_init(void)
  814. {
  815. sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
  816. sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
  817. cxgb3i_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
  818. ISCSI_ITT_MASK, sw_tag_idx_bits,
  819. ISCSI_AGE_MASK, sw_tag_age_bits);
  820. cxgb3i_scsi_transport =
  821. iscsi_register_transport(&cxgb3i_iscsi_transport);
  822. if (!cxgb3i_scsi_transport) {
  823. cxgb3i_log_error("Could not register cxgb3i transport.\n");
  824. return -ENODEV;
  825. }
  826. cxgb3i_api_debug("cxgb3i transport 0x%p.\n", cxgb3i_scsi_transport);
  827. return 0;
  828. }
  829. void cxgb3i_iscsi_cleanup(void)
  830. {
  831. if (cxgb3i_scsi_transport) {
  832. cxgb3i_api_debug("cxgb3i transport 0x%p.\n",
  833. cxgb3i_scsi_transport);
  834. iscsi_unregister_transport(&cxgb3i_iscsi_transport);
  835. }
  836. }