1 /* cxgb3i_iscsi.c: Chelsio S3xx iSCSI driver.
3 * Copyright (c) 2008 Chelsio Communications, Inc.
4 * Copyright (c) 2008 Mike Christie
5 * Copyright (c) 2008 Red Hat, Inc. All rights reserved.
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.
11 * Written by: Karen Xie (kxie@chelsio.com)
14 #include <linux/inet.h>
15 #include <linux/crypto.h>
17 #include <scsi/scsi_cmnd.h>
18 #include <scsi/scsi_device.h>
19 #include <scsi/scsi_eh.h>
20 #include <scsi/scsi_host.h>
21 #include <scsi/scsi.h>
22 #include <scsi/iscsi_proto.h>
23 #include <scsi/libiscsi.h>
24 #include <scsi/scsi_transport_iscsi.h>
27 #include "cxgb3i_pdu.h"
29 #ifdef __DEBUG_CXGB3I_TAG__
30 #define cxgb3i_tag_debug cxgb3i_log_debug
32 #define cxgb3i_tag_debug(fmt...)
35 #ifdef __DEBUG_CXGB3I_API__
36 #define cxgb3i_api_debug cxgb3i_log_debug
38 #define cxgb3i_api_debug(fmt...)
42 * align pdu size to multiple of 512 for better performance
44 #define align_pdu_size(n) do { n = (n) & (~511); } while (0)
46 static struct scsi_transport_template
*cxgb3i_scsi_transport
;
47 static struct scsi_host_template cxgb3i_host_template
;
48 static struct iscsi_transport cxgb3i_iscsi_transport
;
49 static unsigned char sw_tag_idx_bits
;
50 static unsigned char sw_tag_age_bits
;
52 static LIST_HEAD(cxgb3i_snic_list
);
53 static DEFINE_RWLOCK(cxgb3i_snic_rwlock
);
56 * cxgb3i_adapter_add - init a s3 adapter structure and any h/w settings
57 * @t3dev: t3cdev adapter
58 * return the resulting cxgb3i_adapter struct
60 struct cxgb3i_adapter
*cxgb3i_adapter_add(struct t3cdev
*t3dev
)
62 struct cxgb3i_adapter
*snic
;
63 struct adapter
*adapter
= tdev2adap(t3dev
);
66 snic
= kzalloc(sizeof(*snic
), GFP_KERNEL
);
68 cxgb3i_api_debug("cxgb3 %s, OOM.\n", t3dev
->name
);
71 spin_lock_init(&snic
->lock
);
74 snic
->pdev
= adapter
->pdev
;
75 snic
->tag_format
.sw_bits
= sw_tag_idx_bits
+ sw_tag_age_bits
;
77 if (cxgb3i_adapter_ddp_init(t3dev
, &snic
->tag_format
,
79 &snic
->rx_max_size
) < 0)
82 for_each_port(adapter
, i
) {
83 snic
->hba
[i
] = cxgb3i_hba_host_add(snic
, adapter
->port
[i
]);
87 snic
->hba_cnt
= adapter
->params
.nports
;
90 write_lock(&cxgb3i_snic_rwlock
);
91 list_add_tail(&snic
->list_head
, &cxgb3i_snic_list
);
92 write_unlock(&cxgb3i_snic_rwlock
);
97 cxgb3i_adapter_ddp_cleanup(t3dev
);
104 * cxgb3i_adapter_remove - release all the resources held and cleanup any
106 * @t3dev: t3cdev adapter
108 void cxgb3i_adapter_remove(struct t3cdev
*t3dev
)
111 struct cxgb3i_adapter
*snic
;
113 /* remove from the list */
114 write_lock(&cxgb3i_snic_rwlock
);
115 list_for_each_entry(snic
, &cxgb3i_snic_list
, list_head
) {
116 if (snic
->tdev
== t3dev
) {
117 list_del(&snic
->list_head
);
121 write_unlock(&cxgb3i_snic_rwlock
);
124 for (i
= 0; i
< snic
->hba_cnt
; i
++) {
126 cxgb3i_hba_host_remove(snic
->hba
[i
]);
131 /* release ddp resources */
132 cxgb3i_adapter_ddp_cleanup(snic
->tdev
);
138 * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure with a given
140 * @t3dev: t3cdev adapter
142 struct cxgb3i_hba
*cxgb3i_hba_find_by_netdev(struct net_device
*ndev
)
144 struct cxgb3i_adapter
*snic
;
147 read_lock(&cxgb3i_snic_rwlock
);
148 list_for_each_entry(snic
, &cxgb3i_snic_list
, list_head
) {
149 for (i
= 0; i
< snic
->hba_cnt
; i
++) {
150 if (snic
->hba
[i
]->ndev
== ndev
) {
151 read_unlock(&cxgb3i_snic_rwlock
);
156 read_unlock(&cxgb3i_snic_rwlock
);
161 * cxgb3i_hba_host_add - register a new host with scsi/iscsi
162 * @snic: the cxgb3i adapter
163 * @ndev: associated net_device
165 struct cxgb3i_hba
*cxgb3i_hba_host_add(struct cxgb3i_adapter
*snic
,
166 struct net_device
*ndev
)
168 struct cxgb3i_hba
*hba
;
169 struct Scsi_Host
*shost
;
172 shost
= iscsi_host_alloc(&cxgb3i_host_template
,
173 sizeof(struct cxgb3i_hba
),
174 CXGB3I_SCSI_QDEPTH_DFLT
);
176 cxgb3i_log_info("iscsi_host_alloc failed.\n");
180 shost
->transportt
= cxgb3i_scsi_transport
;
181 shost
->max_lun
= CXGB3I_MAX_LUN
;
182 shost
->max_id
= CXGB3I_MAX_TARGET
;
183 shost
->max_channel
= 0;
184 shost
->max_cmd_len
= 16;
186 hba
= iscsi_host_priv(shost
);
191 pci_dev_get(snic
->pdev
);
192 err
= iscsi_host_add(shost
, &snic
->pdev
->dev
);
194 cxgb3i_log_info("iscsi_host_add failed.\n");
198 cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
199 shost
, hba
, shost
->host_no
);
204 pci_dev_put(snic
->pdev
);
205 scsi_host_put(shost
);
210 * cxgb3i_hba_host_remove - de-register the host with scsi/iscsi
211 * @hba: the cxgb3i hba
213 void cxgb3i_hba_host_remove(struct cxgb3i_hba
*hba
)
215 cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
216 hba
->shost
, hba
, hba
->shost
->host_no
);
217 iscsi_host_remove(hba
->shost
);
218 pci_dev_put(hba
->snic
->pdev
);
219 iscsi_host_free(hba
->shost
);
223 * cxgb3i_ep_connect - establish TCP connection to target portal
224 * @dst_addr: target IP address
225 * @non_blocking: blocking or non-blocking call
227 * Initiates a TCP/IP connection to the dst_addr
229 static struct iscsi_endpoint
*cxgb3i_ep_connect(struct sockaddr
*dst_addr
,
232 struct iscsi_endpoint
*ep
;
233 struct cxgb3i_endpoint
*cep
;
234 struct cxgb3i_hba
*hba
;
235 struct s3_conn
*c3cn
= NULL
;
238 c3cn
= cxgb3i_c3cn_create();
240 cxgb3i_log_info("ep connect OOM.\n");
245 err
= cxgb3i_c3cn_connect(c3cn
, (struct sockaddr_in
*)dst_addr
);
247 cxgb3i_log_info("ep connect failed.\n");
250 hba
= cxgb3i_hba_find_by_netdev(c3cn
->dst_cache
->dev
);
253 cxgb3i_log_info("NOT going through cxgbi device.\n");
256 if (c3cn_is_closing(c3cn
)) {
258 cxgb3i_log_info("ep connect unable to connect.\n");
262 ep
= iscsi_create_endpoint(sizeof(*cep
));
265 cxgb3i_log_info("iscsi alloc ep, OOM.\n");
272 cxgb3i_api_debug("ep 0x%p, 0x%p, c3cn 0x%p, hba 0x%p.\n",
277 cxgb3i_api_debug("conn 0x%p failed, release.\n", c3cn
);
279 cxgb3i_c3cn_release(c3cn
);
284 * cxgb3i_ep_poll - polls for TCP connection establishement
285 * @ep: TCP connection (endpoint) handle
286 * @timeout_ms: timeout value in milli secs
288 * polls for TCP connect request to complete
290 static int cxgb3i_ep_poll(struct iscsi_endpoint
*ep
, int timeout_ms
)
292 struct cxgb3i_endpoint
*cep
= ep
->dd_data
;
293 struct s3_conn
*c3cn
= cep
->c3cn
;
295 if (!c3cn_is_established(c3cn
))
297 cxgb3i_api_debug("ep 0x%p, c3cn 0x%p established.\n", ep
, c3cn
);
302 * cxgb3i_ep_disconnect - teardown TCP connection
303 * @ep: TCP connection (endpoint) handle
305 * teardown TCP connection
307 static void cxgb3i_ep_disconnect(struct iscsi_endpoint
*ep
)
309 struct cxgb3i_endpoint
*cep
= ep
->dd_data
;
310 struct cxgb3i_conn
*cconn
= cep
->cconn
;
312 cxgb3i_api_debug("ep 0x%p, cep 0x%p.\n", ep
, cep
);
314 if (cconn
&& cconn
->conn
) {
316 * stop the xmit path so the xmit_pdu function is
319 iscsi_suspend_tx(cconn
->conn
);
321 write_lock_bh(&cep
->c3cn
->callback_lock
);
322 cep
->c3cn
->user_data
= NULL
;
324 write_unlock_bh(&cep
->c3cn
->callback_lock
);
327 cxgb3i_api_debug("ep 0x%p, cep 0x%p, release c3cn 0x%p.\n",
329 cxgb3i_c3cn_release(cep
->c3cn
);
330 iscsi_destroy_endpoint(ep
);
334 * cxgb3i_session_create - create a new iscsi session
335 * @cmds_max: max # of commands
336 * @qdepth: scsi queue depth
337 * @initial_cmdsn: initial iscsi CMDSN for this session
338 * @host_no: pointer to return host no
340 * Creates a new iSCSI session
342 static struct iscsi_cls_session
*
343 cxgb3i_session_create(struct iscsi_endpoint
*ep
, u16 cmds_max
, u16 qdepth
,
344 u32 initial_cmdsn
, u32
*host_no
)
346 struct cxgb3i_endpoint
*cep
;
347 struct cxgb3i_hba
*hba
;
348 struct Scsi_Host
*shost
;
349 struct iscsi_cls_session
*cls_session
;
350 struct iscsi_session
*session
;
353 cxgb3i_log_error("%s, missing endpoint.\n", __func__
);
360 cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep
, cep
, hba
);
361 BUG_ON(hba
!= iscsi_host_priv(shost
));
363 *host_no
= shost
->host_no
;
365 cls_session
= iscsi_session_setup(&cxgb3i_iscsi_transport
, shost
,
367 sizeof(struct iscsi_tcp_task
),
368 initial_cmdsn
, ISCSI_MAX_TARGET
);
371 session
= cls_session
->dd_data
;
372 if (iscsi_tcp_r2tpool_alloc(session
))
378 iscsi_session_teardown(cls_session
);
383 * cxgb3i_session_destroy - destroys iscsi session
384 * @cls_session: pointer to iscsi cls session
386 * Destroys an iSCSI session instance and releases its all resources held
388 static void cxgb3i_session_destroy(struct iscsi_cls_session
*cls_session
)
390 cxgb3i_api_debug("sess 0x%p.\n", cls_session
);
391 iscsi_tcp_r2tpool_free(cls_session
->dd_data
);
392 iscsi_session_teardown(cls_session
);
396 * cxgb3i_conn_max_xmit_dlength -- check the max. xmit pdu segment size,
397 * reduce it to be within the hardware limit if needed
398 * @conn: iscsi connection
400 static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn
*conn
)
403 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
404 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
405 unsigned int max
= min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD
,
406 cconn
->hba
->snic
->tx_max_size
-
407 ISCSI_PDU_NONPAYLOAD_MAX
);
409 if (conn
->max_xmit_dlength
)
410 conn
->max_xmit_dlength
= min_t(unsigned int,
411 conn
->max_xmit_dlength
, max
);
413 conn
->max_xmit_dlength
= max
;
414 align_pdu_size(conn
->max_xmit_dlength
);
415 cxgb3i_log_info("conn 0x%p, max xmit %u.\n",
416 conn
, conn
->max_xmit_dlength
);
421 * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size against
423 * @conn: iscsi connection
424 * return 0 if the value is valid, < 0 otherwise.
426 static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn
*conn
)
428 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
429 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
430 unsigned int max
= min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD
,
431 cconn
->hba
->snic
->rx_max_size
-
432 ISCSI_PDU_NONPAYLOAD_MAX
);
435 if (conn
->max_recv_dlength
) {
436 if (conn
->max_recv_dlength
> max
) {
437 cxgb3i_log_error("MaxRecvDataSegmentLength %u too big."
438 " Need to be <= %u.\n",
439 conn
->max_recv_dlength
, max
);
442 conn
->max_recv_dlength
= min_t(unsigned int,
443 conn
->max_recv_dlength
, max
);
444 align_pdu_size(conn
->max_recv_dlength
);
446 conn
->max_recv_dlength
= max
;
447 cxgb3i_api_debug("conn 0x%p, max recv %u.\n",
448 conn
, conn
->max_recv_dlength
);
453 * cxgb3i_conn_create - create iscsi connection instance
454 * @cls_session: pointer to iscsi cls session
457 * Creates a new iSCSI connection instance for a given session
459 static struct iscsi_cls_conn
*cxgb3i_conn_create(struct iscsi_cls_session
460 *cls_session
, u32 cid
)
462 struct iscsi_cls_conn
*cls_conn
;
463 struct iscsi_conn
*conn
;
464 struct iscsi_tcp_conn
*tcp_conn
;
465 struct cxgb3i_conn
*cconn
;
467 cxgb3i_api_debug("sess 0x%p, cid %u.\n", cls_session
, cid
);
469 cls_conn
= iscsi_tcp_conn_setup(cls_session
, sizeof(*cconn
), cid
);
472 conn
= cls_conn
->dd_data
;
473 tcp_conn
= conn
->dd_data
;
474 cconn
= tcp_conn
->dd_data
;
481 * cxgb3i_conn_bind - binds iscsi sess, conn and endpoint together
482 * @cls_session: pointer to iscsi cls session
483 * @cls_conn: pointer to iscsi cls conn
484 * @transport_eph: 64-bit EP handle
485 * @is_leading: leading connection on this session?
487 * Binds together an iSCSI session, an iSCSI connection and a
488 * TCP connection. This routine returns error code if the TCP
489 * connection does not belong on the device iSCSI sess/conn is bound
492 static int cxgb3i_conn_bind(struct iscsi_cls_session
*cls_session
,
493 struct iscsi_cls_conn
*cls_conn
,
494 u64 transport_eph
, int is_leading
)
496 struct iscsi_conn
*conn
= cls_conn
->dd_data
;
497 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
498 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
499 struct cxgb3i_adapter
*snic
;
500 struct iscsi_endpoint
*ep
;
501 struct cxgb3i_endpoint
*cep
;
502 struct s3_conn
*c3cn
;
505 ep
= iscsi_lookup_endpoint(transport_eph
);
509 /* setup ddp pagesize */
512 snic
= cep
->hba
->snic
;
513 err
= cxgb3i_setup_conn_host_pagesize(snic
->tdev
, c3cn
->tid
, 0);
517 cxgb3i_api_debug("ep 0x%p, cls sess 0x%p, cls conn 0x%p.\n",
518 ep
, cls_session
, cls_conn
);
520 err
= iscsi_conn_bind(cls_session
, cls_conn
, is_leading
);
524 /* calculate the tag idx bits needed for this conn based on cmds_max */
525 cconn
->task_idx_bits
= (__ilog2_u32(conn
->session
->cmds_max
- 1)) + 1;
526 cxgb3i_api_debug("session cmds_max 0x%x, bits %u.\n",
527 conn
->session
->cmds_max
, cconn
->task_idx_bits
);
529 read_lock(&c3cn
->callback_lock
);
530 c3cn
->user_data
= conn
;
531 cconn
->hba
= cep
->hba
;
534 read_unlock(&c3cn
->callback_lock
);
536 cxgb3i_conn_max_xmit_dlength(conn
);
537 cxgb3i_conn_max_recv_dlength(conn
);
539 spin_lock_bh(&conn
->session
->lock
);
540 sprintf(conn
->portal_address
, NIPQUAD_FMT
,
541 NIPQUAD(c3cn
->daddr
.sin_addr
.s_addr
));
542 conn
->portal_port
= ntohs(c3cn
->daddr
.sin_port
);
543 spin_unlock_bh(&conn
->session
->lock
);
545 /* init recv engine */
546 iscsi_tcp_hdr_recv_prep(tcp_conn
);
552 * cxgb3i_conn_get_param - return iscsi connection parameter to caller
553 * @cls_conn: pointer to iscsi cls conn
554 * @param: parameter type identifier
555 * @buf: buffer pointer
557 * returns iSCSI connection parameters
559 static int cxgb3i_conn_get_param(struct iscsi_cls_conn
*cls_conn
,
560 enum iscsi_param param
, char *buf
)
562 struct iscsi_conn
*conn
= cls_conn
->dd_data
;
565 cxgb3i_api_debug("cls_conn 0x%p, param %d.\n", cls_conn
, param
);
568 case ISCSI_PARAM_CONN_PORT
:
569 spin_lock_bh(&conn
->session
->lock
);
570 len
= sprintf(buf
, "%hu\n", conn
->portal_port
);
571 spin_unlock_bh(&conn
->session
->lock
);
573 case ISCSI_PARAM_CONN_ADDRESS
:
574 spin_lock_bh(&conn
->session
->lock
);
575 len
= sprintf(buf
, "%s\n", conn
->portal_address
);
576 spin_unlock_bh(&conn
->session
->lock
);
579 return iscsi_conn_get_param(cls_conn
, param
, buf
);
586 * cxgb3i_conn_set_param - set iscsi connection parameter
587 * @cls_conn: pointer to iscsi cls conn
588 * @param: parameter type identifier
589 * @buf: buffer pointer
590 * @buflen: buffer length
592 * set iSCSI connection parameters
594 static int cxgb3i_conn_set_param(struct iscsi_cls_conn
*cls_conn
,
595 enum iscsi_param param
, char *buf
, int buflen
)
597 struct iscsi_conn
*conn
= cls_conn
->dd_data
;
598 struct iscsi_session
*session
= conn
->session
;
599 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
600 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
601 struct cxgb3i_adapter
*snic
= cconn
->hba
->snic
;
602 struct s3_conn
*c3cn
= cconn
->cep
->c3cn
;
606 case ISCSI_PARAM_HDRDGST_EN
:
607 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
608 if (!err
&& conn
->hdrdgst_en
)
609 err
= cxgb3i_setup_conn_digest(snic
->tdev
, c3cn
->tid
,
611 conn
->datadgst_en
, 0);
613 case ISCSI_PARAM_DATADGST_EN
:
614 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
615 if (!err
&& conn
->datadgst_en
)
616 err
= cxgb3i_setup_conn_digest(snic
->tdev
, c3cn
->tid
,
618 conn
->datadgst_en
, 0);
620 case ISCSI_PARAM_MAX_R2T
:
621 sscanf(buf
, "%d", &value
);
622 if (value
<= 0 || !is_power_of_2(value
))
624 if (session
->max_r2t
== value
)
626 iscsi_tcp_r2tpool_free(session
);
627 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
628 if (!err
&& iscsi_tcp_r2tpool_alloc(session
))
630 case ISCSI_PARAM_MAX_RECV_DLENGTH
:
631 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
633 err
= cxgb3i_conn_max_recv_dlength(conn
);
635 case ISCSI_PARAM_MAX_XMIT_DLENGTH
:
636 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
638 err
= cxgb3i_conn_max_xmit_dlength(conn
);
641 return iscsi_set_param(cls_conn
, param
, buf
, buflen
);
647 * cxgb3i_host_set_param - configure host (adapter) related parameters
648 * @shost: scsi host pointer
649 * @param: parameter type identifier
650 * @buf: buffer pointer
652 static int cxgb3i_host_set_param(struct Scsi_Host
*shost
,
653 enum iscsi_host_param param
,
654 char *buf
, int buflen
)
656 struct cxgb3i_hba
*hba
= iscsi_host_priv(shost
);
658 cxgb3i_api_debug("param %d, buf %s.\n", param
, buf
);
661 case ISCSI_HOST_PARAM_IPADDRESS
:
663 __be32 addr
= in_aton(buf
);
664 cxgb3i_set_private_ipv4addr(hba
->ndev
, addr
);
667 case ISCSI_HOST_PARAM_HWADDRESS
:
668 case ISCSI_HOST_PARAM_NETDEV_NAME
:
672 return iscsi_host_set_param(shost
, param
, buf
, buflen
);
677 * cxgb3i_host_get_param - returns host (adapter) related parameters
678 * @shost: scsi host pointer
679 * @param: parameter type identifier
680 * @buf: buffer pointer
682 static int cxgb3i_host_get_param(struct Scsi_Host
*shost
,
683 enum iscsi_host_param param
, char *buf
)
685 struct cxgb3i_hba
*hba
= iscsi_host_priv(shost
);
688 cxgb3i_api_debug("hba %s, param %d.\n", hba
->ndev
->name
, param
);
691 case ISCSI_HOST_PARAM_HWADDRESS
:
692 len
= sysfs_format_mac(buf
, hba
->ndev
->dev_addr
, 6);
694 case ISCSI_HOST_PARAM_NETDEV_NAME
:
695 len
= sprintf(buf
, "%s\n", hba
->ndev
->name
);
697 case ISCSI_HOST_PARAM_IPADDRESS
:
701 addr
= cxgb3i_get_private_ipv4addr(hba
->ndev
);
702 len
= sprintf(buf
, NIPQUAD_FMT
, NIPQUAD(addr
));
706 return iscsi_host_get_param(shost
, param
, buf
);
712 * cxgb3i_conn_get_stats - returns iSCSI stats
713 * @cls_conn: pointer to iscsi cls conn
714 * @stats: pointer to iscsi statistic struct
716 static void cxgb3i_conn_get_stats(struct iscsi_cls_conn
*cls_conn
,
717 struct iscsi_stats
*stats
)
719 struct iscsi_conn
*conn
= cls_conn
->dd_data
;
721 stats
->txdata_octets
= conn
->txdata_octets
;
722 stats
->rxdata_octets
= conn
->rxdata_octets
;
723 stats
->scsicmd_pdus
= conn
->scsicmd_pdus_cnt
;
724 stats
->dataout_pdus
= conn
->dataout_pdus_cnt
;
725 stats
->scsirsp_pdus
= conn
->scsirsp_pdus_cnt
;
726 stats
->datain_pdus
= conn
->datain_pdus_cnt
;
727 stats
->r2t_pdus
= conn
->r2t_pdus_cnt
;
728 stats
->tmfcmd_pdus
= conn
->tmfcmd_pdus_cnt
;
729 stats
->tmfrsp_pdus
= conn
->tmfrsp_pdus_cnt
;
730 stats
->digest_err
= 0;
731 stats
->timeout_err
= 0;
732 stats
->custom_length
= 1;
733 strcpy(stats
->custom
[0].desc
, "eh_abort_cnt");
734 stats
->custom
[0].value
= conn
->eh_abort_cnt
;
738 * cxgb3i_parse_itt - get the idx and age bits from a given tag
739 * @conn: iscsi connection
741 * @idx: task index, filled in by this function
742 * @age: session age, filled in by this function
744 static void cxgb3i_parse_itt(struct iscsi_conn
*conn
, itt_t itt
,
747 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
748 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
749 struct cxgb3i_adapter
*snic
= cconn
->hba
->snic
;
750 u32 tag
= ntohl((__force u32
) itt
);
753 sw_bits
= cxgb3i_tag_nonrsvd_bits(&snic
->tag_format
, tag
);
755 *idx
= sw_bits
& ((1 << cconn
->task_idx_bits
) - 1);
757 *age
= (sw_bits
>> cconn
->task_idx_bits
) & ISCSI_AGE_MASK
;
759 cxgb3i_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n",
760 tag
, itt
, sw_bits
, idx
? *idx
: 0xFFFFF,
765 * cxgb3i_reserve_itt - generate tag for a give task
766 * Try to set up ddp for a scsi read task.
768 * @hdr_itt: tag, filled in by this function
770 int cxgb3i_reserve_itt(struct iscsi_task
*task
, itt_t
*hdr_itt
)
772 struct scsi_cmnd
*sc
= task
->sc
;
773 struct iscsi_conn
*conn
= task
->conn
;
774 struct iscsi_session
*sess
= conn
->session
;
775 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
776 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
777 struct cxgb3i_adapter
*snic
= cconn
->hba
->snic
;
778 struct cxgb3i_tag_format
*tformat
= &snic
->tag_format
;
779 u32 sw_tag
= (sess
->age
<< cconn
->task_idx_bits
) | task
->itt
;
784 (scsi_bidi_cmnd(sc
) || sc
->sc_data_direction
== DMA_FROM_DEVICE
) &&
785 cxgb3i_sw_tag_usable(tformat
, sw_tag
)) {
786 struct s3_conn
*c3cn
= cconn
->cep
->c3cn
;
787 struct cxgb3i_gather_list
*gl
;
789 gl
= cxgb3i_ddp_make_gl(scsi_in(sc
)->length
,
790 scsi_in(sc
)->table
.sgl
,
791 scsi_in(sc
)->table
.nents
,
796 err
= cxgb3i_ddp_tag_reserve(snic
->tdev
, c3cn
->tid
,
800 cxgb3i_ddp_release_gl(gl
, snic
->pdev
);
805 tag
= cxgb3i_set_non_ddp_tag(tformat
, sw_tag
);
806 /* the itt need to sent in big-endian order */
807 *hdr_itt
= (__force itt_t
)htonl(tag
);
809 cxgb3i_tag_debug("new tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n",
810 tag
, *hdr_itt
, task
->itt
, sess
->age
);
815 * cxgb3i_release_itt - release the tag for a given task
816 * if the tag is a ddp tag, release the ddp setup
820 void cxgb3i_release_itt(struct iscsi_task
*task
, itt_t hdr_itt
)
822 struct scsi_cmnd
*sc
= task
->sc
;
823 struct iscsi_tcp_conn
*tcp_conn
= task
->conn
->dd_data
;
824 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
825 struct cxgb3i_adapter
*snic
= cconn
->hba
->snic
;
826 struct cxgb3i_tag_format
*tformat
= &snic
->tag_format
;
827 u32 tag
= ntohl((__force u32
)hdr_itt
);
829 cxgb3i_tag_debug("release tag 0x%x.\n", tag
);
832 (scsi_bidi_cmnd(sc
) || sc
->sc_data_direction
== DMA_FROM_DEVICE
) &&
833 cxgb3i_is_ddp_tag(tformat
, tag
))
834 cxgb3i_ddp_tag_release(snic
->tdev
, tag
);
838 * cxgb3i_host_template -- Scsi_Host_Template structure
839 * used when registering with the scsi mid layer
841 static struct scsi_host_template cxgb3i_host_template
= {
842 .module
= THIS_MODULE
,
843 .name
= "Chelsio S3xx iSCSI Initiator",
844 .proc_name
= "cxgb3i",
845 .queuecommand
= iscsi_queuecommand
,
846 .change_queue_depth
= iscsi_change_queue_depth
,
847 .can_queue
= 128 * (ISCSI_DEF_XMIT_CMDS_MAX
- 1),
848 .sg_tablesize
= SG_ALL
,
849 .max_sectors
= 0xFFFF,
850 .cmd_per_lun
= ISCSI_DEF_CMD_PER_LUN
,
851 .eh_abort_handler
= iscsi_eh_abort
,
852 .eh_device_reset_handler
= iscsi_eh_device_reset
,
853 .eh_target_reset_handler
= iscsi_eh_target_reset
,
854 .use_clustering
= DISABLE_CLUSTERING
,
858 static struct iscsi_transport cxgb3i_iscsi_transport
= {
859 .owner
= THIS_MODULE
,
861 .caps
= CAP_RECOVERY_L0
| CAP_MULTI_R2T
| CAP_HDRDGST
862 | CAP_DATADGST
| CAP_DIGEST_OFFLOAD
|
864 .param_mask
= ISCSI_MAX_RECV_DLENGTH
|
865 ISCSI_MAX_XMIT_DLENGTH
|
868 ISCSI_INITIAL_R2T_EN
|
873 ISCSI_PDU_INORDER_EN
|
874 ISCSI_DATASEQ_INORDER_EN
|
879 ISCSI_PERSISTENT_PORT
|
880 ISCSI_PERSISTENT_ADDRESS
|
881 ISCSI_TARGET_NAME
| ISCSI_TPGT
|
882 ISCSI_USERNAME
| ISCSI_PASSWORD
|
883 ISCSI_USERNAME_IN
| ISCSI_PASSWORD_IN
|
884 ISCSI_FAST_ABORT
| ISCSI_ABORT_TMO
|
886 ISCSI_PING_TMO
| ISCSI_RECV_TMO
|
887 ISCSI_IFACE_NAME
| ISCSI_INITIATOR_NAME
,
888 .host_param_mask
= ISCSI_HOST_HWADDRESS
| ISCSI_HOST_IPADDRESS
|
889 ISCSI_HOST_INITIATOR_NAME
| ISCSI_HOST_NETDEV_NAME
,
890 .get_host_param
= cxgb3i_host_get_param
,
891 .set_host_param
= cxgb3i_host_set_param
,
892 /* session management */
893 .create_session
= cxgb3i_session_create
,
894 .destroy_session
= cxgb3i_session_destroy
,
895 .get_session_param
= iscsi_session_get_param
,
896 /* connection management */
897 .create_conn
= cxgb3i_conn_create
,
898 .bind_conn
= cxgb3i_conn_bind
,
899 .destroy_conn
= iscsi_tcp_conn_teardown
,
900 .start_conn
= iscsi_conn_start
,
901 .stop_conn
= iscsi_conn_stop
,
902 .get_conn_param
= cxgb3i_conn_get_param
,
903 .set_param
= cxgb3i_conn_set_param
,
904 .get_stats
= cxgb3i_conn_get_stats
,
905 /* pdu xmit req. from user space */
906 .send_pdu
= iscsi_conn_send_pdu
,
908 .init_task
= iscsi_tcp_task_init
,
909 .xmit_task
= iscsi_tcp_task_xmit
,
910 .cleanup_task
= cxgb3i_conn_cleanup_task
,
913 .alloc_pdu
= cxgb3i_conn_alloc_pdu
,
914 .init_pdu
= cxgb3i_conn_init_pdu
,
915 .xmit_pdu
= cxgb3i_conn_xmit_pdu
,
916 .parse_pdu_itt
= cxgb3i_parse_itt
,
918 /* TCP connect/disconnect */
919 .ep_connect
= cxgb3i_ep_connect
,
920 .ep_poll
= cxgb3i_ep_poll
,
921 .ep_disconnect
= cxgb3i_ep_disconnect
,
922 /* Error recovery timeout call */
923 .session_recovery_timedout
= iscsi_session_recovery_timedout
,
926 int cxgb3i_iscsi_init(void)
928 sw_tag_idx_bits
= (__ilog2_u32(ISCSI_ITT_MASK
)) + 1;
929 sw_tag_age_bits
= (__ilog2_u32(ISCSI_AGE_MASK
)) + 1;
930 cxgb3i_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
931 ISCSI_ITT_MASK
, sw_tag_idx_bits
,
932 ISCSI_AGE_MASK
, sw_tag_age_bits
);
934 cxgb3i_scsi_transport
=
935 iscsi_register_transport(&cxgb3i_iscsi_transport
);
936 if (!cxgb3i_scsi_transport
) {
937 cxgb3i_log_error("Could not register cxgb3i transport.\n");
940 cxgb3i_api_debug("cxgb3i transport 0x%p.\n", cxgb3i_scsi_transport
);
944 void cxgb3i_iscsi_cleanup(void)
946 if (cxgb3i_scsi_transport
) {
947 cxgb3i_api_debug("cxgb3i transport 0x%p.\n",
948 cxgb3i_scsi_transport
);
949 iscsi_unregister_transport(&cxgb3i_iscsi_transport
);