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/slab.h>
16 #include <linux/crypto.h>
17 #include <linux/if_vlan.h>
20 #include <scsi/scsi_cmnd.h>
21 #include <scsi/scsi_device.h>
22 #include <scsi/scsi_eh.h>
23 #include <scsi/scsi_host.h>
24 #include <scsi/scsi.h>
25 #include <scsi/iscsi_proto.h>
26 #include <scsi/libiscsi.h>
27 #include <scsi/scsi_transport_iscsi.h>
30 #include "cxgb3i_pdu.h"
32 #ifdef __DEBUG_CXGB3I_TAG__
33 #define cxgb3i_tag_debug cxgb3i_log_debug
35 #define cxgb3i_tag_debug(fmt...)
38 #ifdef __DEBUG_CXGB3I_API__
39 #define cxgb3i_api_debug cxgb3i_log_debug
41 #define cxgb3i_api_debug(fmt...)
45 * align pdu size to multiple of 512 for better performance
47 #define align_pdu_size(n) do { n = (n) & (~511); } while (0)
49 static struct scsi_transport_template
*cxgb3i_scsi_transport
;
50 static struct scsi_host_template cxgb3i_host_template
;
51 static struct iscsi_transport cxgb3i_iscsi_transport
;
52 static unsigned char sw_tag_idx_bits
;
53 static unsigned char sw_tag_age_bits
;
55 static LIST_HEAD(cxgb3i_snic_list
);
56 static DEFINE_RWLOCK(cxgb3i_snic_rwlock
);
59 * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev
60 * @tdev: t3cdev pointer
62 struct cxgb3i_adapter
*cxgb3i_adapter_find_by_tdev(struct t3cdev
*tdev
)
64 struct cxgb3i_adapter
*snic
;
66 read_lock(&cxgb3i_snic_rwlock
);
67 list_for_each_entry(snic
, &cxgb3i_snic_list
, list_head
) {
68 if (snic
->tdev
== tdev
) {
69 read_unlock(&cxgb3i_snic_rwlock
);
73 read_unlock(&cxgb3i_snic_rwlock
);
77 static inline int adapter_update(struct cxgb3i_adapter
*snic
)
79 cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
81 return cxgb3i_adapter_ddp_info(snic
->tdev
, &snic
->tag_format
,
86 static int adapter_add(struct cxgb3i_adapter
*snic
)
88 struct t3cdev
*t3dev
= snic
->tdev
;
89 struct adapter
*adapter
= tdev2adap(t3dev
);
92 snic
->pdev
= adapter
->pdev
;
93 snic
->tag_format
.sw_bits
= sw_tag_idx_bits
+ sw_tag_age_bits
;
95 err
= cxgb3i_adapter_ddp_info(t3dev
, &snic
->tag_format
,
101 for_each_port(adapter
, i
) {
102 snic
->hba
[i
] = cxgb3i_hba_host_add(snic
, adapter
->port
[i
]);
106 snic
->hba_cnt
= adapter
->params
.nports
;
108 /* add to the list */
109 write_lock(&cxgb3i_snic_rwlock
);
110 list_add_tail(&snic
->list_head
, &cxgb3i_snic_list
);
111 write_unlock(&cxgb3i_snic_rwlock
);
113 cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
114 t3dev
, snic
, snic
->hba_cnt
);
119 * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
120 * @t3dev: t3cdev adapter
122 void cxgb3i_adapter_open(struct t3cdev
*t3dev
)
124 struct cxgb3i_adapter
*snic
= cxgb3i_adapter_find_by_tdev(t3dev
);
128 err
= adapter_update(snic
);
130 snic
= kzalloc(sizeof(*snic
), GFP_KERNEL
);
132 spin_lock_init(&snic
->lock
);
134 err
= adapter_add(snic
);
140 cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
141 snic
, snic
? snic
->flags
: 0, t3dev
, err
);
143 snic
->flags
&= ~CXGB3I_ADAPTER_FLAG_RESET
;
144 cxgb3i_adapter_close(t3dev
);
150 * cxgb3i_adapter_close - release the resources held and cleanup h/w settings
151 * @t3dev: t3cdev adapter
153 void cxgb3i_adapter_close(struct t3cdev
*t3dev
)
155 struct cxgb3i_adapter
*snic
= cxgb3i_adapter_find_by_tdev(t3dev
);
158 if (!snic
|| snic
->flags
& CXGB3I_ADAPTER_FLAG_RESET
) {
159 cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
160 t3dev
, snic
, snic
? snic
->flags
: 0);
164 /* remove from the list */
165 write_lock(&cxgb3i_snic_rwlock
);
166 list_del(&snic
->list_head
);
167 write_unlock(&cxgb3i_snic_rwlock
);
169 for (i
= 0; i
< snic
->hba_cnt
; i
++) {
171 cxgb3i_hba_host_remove(snic
->hba
[i
]);
175 cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
176 t3dev
, snic
, snic
->hba_cnt
);
181 * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
182 * @t3dev: t3cdev adapter
184 static struct cxgb3i_hba
*cxgb3i_hba_find_by_netdev(struct net_device
*ndev
)
186 struct cxgb3i_adapter
*snic
;
189 if (ndev
->priv_flags
& IFF_802_1Q_VLAN
)
190 ndev
= vlan_dev_real_dev(ndev
);
192 read_lock(&cxgb3i_snic_rwlock
);
193 list_for_each_entry(snic
, &cxgb3i_snic_list
, list_head
) {
194 for (i
= 0; i
< snic
->hba_cnt
; i
++) {
195 if (snic
->hba
[i
]->ndev
== ndev
) {
196 read_unlock(&cxgb3i_snic_rwlock
);
201 read_unlock(&cxgb3i_snic_rwlock
);
206 * cxgb3i_hba_host_add - register a new host with scsi/iscsi
207 * @snic: the cxgb3i adapter
208 * @ndev: associated net_device
210 struct cxgb3i_hba
*cxgb3i_hba_host_add(struct cxgb3i_adapter
*snic
,
211 struct net_device
*ndev
)
213 struct cxgb3i_hba
*hba
;
214 struct Scsi_Host
*shost
;
217 shost
= iscsi_host_alloc(&cxgb3i_host_template
,
218 sizeof(struct cxgb3i_hba
), 1);
220 cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
225 shost
->transportt
= cxgb3i_scsi_transport
;
226 shost
->max_lun
= CXGB3I_MAX_LUN
;
227 shost
->max_id
= CXGB3I_MAX_TARGET
;
228 shost
->max_channel
= 0;
229 shost
->max_cmd_len
= 16;
231 hba
= iscsi_host_priv(shost
);
236 pci_dev_get(snic
->pdev
);
237 err
= iscsi_host_add(shost
, &snic
->pdev
->dev
);
239 cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
244 cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
245 shost
, hba
, shost
->host_no
);
250 pci_dev_put(snic
->pdev
);
251 scsi_host_put(shost
);
256 * cxgb3i_hba_host_remove - de-register the host with scsi/iscsi
257 * @hba: the cxgb3i hba
259 void cxgb3i_hba_host_remove(struct cxgb3i_hba
*hba
)
261 cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
262 hba
->shost
, hba
, hba
->shost
->host_no
);
263 iscsi_host_remove(hba
->shost
);
264 pci_dev_put(hba
->snic
->pdev
);
265 iscsi_host_free(hba
->shost
);
269 * cxgb3i_ep_connect - establish TCP connection to target portal
270 * @shost: scsi host to use
271 * @dst_addr: target IP address
272 * @non_blocking: blocking or non-blocking call
274 * Initiates a TCP/IP connection to the dst_addr
276 static struct iscsi_endpoint
*cxgb3i_ep_connect(struct Scsi_Host
*shost
,
277 struct sockaddr
*dst_addr
,
280 struct iscsi_endpoint
*ep
;
281 struct cxgb3i_endpoint
*cep
;
282 struct cxgb3i_hba
*hba
= NULL
;
283 struct s3_conn
*c3cn
= NULL
;
287 hba
= iscsi_host_priv(shost
);
289 cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost
, hba
);
291 c3cn
= cxgb3i_c3cn_create();
293 cxgb3i_log_info("ep connect OOM.\n");
298 err
= cxgb3i_c3cn_connect(hba
? hba
->ndev
: NULL
, c3cn
,
299 (struct sockaddr_in
*)dst_addr
);
301 cxgb3i_log_info("ep connect failed.\n");
305 hba
= cxgb3i_hba_find_by_netdev(c3cn
->dst_cache
->dev
);
308 cxgb3i_log_info("NOT going through cxgbi device.\n");
312 if (shost
&& hba
!= iscsi_host_priv(shost
)) {
314 cxgb3i_log_info("Could not connect through request host%u\n",
319 if (c3cn_is_closing(c3cn
)) {
321 cxgb3i_log_info("ep connect unable to connect.\n");
325 ep
= iscsi_create_endpoint(sizeof(*cep
));
328 cxgb3i_log_info("iscsi alloc ep, OOM.\n");
335 cxgb3i_api_debug("ep 0x%p, 0x%p, c3cn 0x%p, hba 0x%p.\n",
340 cxgb3i_api_debug("conn 0x%p failed, release.\n", c3cn
);
342 cxgb3i_c3cn_release(c3cn
);
347 * cxgb3i_ep_poll - polls for TCP connection establishement
348 * @ep: TCP connection (endpoint) handle
349 * @timeout_ms: timeout value in milli secs
351 * polls for TCP connect request to complete
353 static int cxgb3i_ep_poll(struct iscsi_endpoint
*ep
, int timeout_ms
)
355 struct cxgb3i_endpoint
*cep
= ep
->dd_data
;
356 struct s3_conn
*c3cn
= cep
->c3cn
;
358 if (!c3cn_is_established(c3cn
))
360 cxgb3i_api_debug("ep 0x%p, c3cn 0x%p established.\n", ep
, c3cn
);
365 * cxgb3i_ep_disconnect - teardown TCP connection
366 * @ep: TCP connection (endpoint) handle
368 * teardown TCP connection
370 static void cxgb3i_ep_disconnect(struct iscsi_endpoint
*ep
)
372 struct cxgb3i_endpoint
*cep
= ep
->dd_data
;
373 struct cxgb3i_conn
*cconn
= cep
->cconn
;
375 cxgb3i_api_debug("ep 0x%p, cep 0x%p.\n", ep
, cep
);
377 if (cconn
&& cconn
->conn
) {
379 * stop the xmit path so the xmit_pdu function is
382 iscsi_suspend_tx(cconn
->conn
);
384 write_lock_bh(&cep
->c3cn
->callback_lock
);
385 cep
->c3cn
->user_data
= NULL
;
387 write_unlock_bh(&cep
->c3cn
->callback_lock
);
390 cxgb3i_api_debug("ep 0x%p, cep 0x%p, release c3cn 0x%p.\n",
392 cxgb3i_c3cn_release(cep
->c3cn
);
393 iscsi_destroy_endpoint(ep
);
397 * cxgb3i_session_create - create a new iscsi session
398 * @cmds_max: max # of commands
399 * @qdepth: scsi queue depth
400 * @initial_cmdsn: initial iscsi CMDSN for this session
402 * Creates a new iSCSI session
404 static struct iscsi_cls_session
*
405 cxgb3i_session_create(struct iscsi_endpoint
*ep
, u16 cmds_max
, u16 qdepth
,
408 struct cxgb3i_endpoint
*cep
;
409 struct cxgb3i_hba
*hba
;
410 struct Scsi_Host
*shost
;
411 struct iscsi_cls_session
*cls_session
;
412 struct iscsi_session
*session
;
415 cxgb3i_log_error("%s, missing endpoint.\n", __func__
);
422 cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep
, cep
, hba
);
423 BUG_ON(hba
!= iscsi_host_priv(shost
));
425 cls_session
= iscsi_session_setup(&cxgb3i_iscsi_transport
, shost
,
427 sizeof(struct iscsi_tcp_task
) +
428 sizeof(struct cxgb3i_task_data
),
429 initial_cmdsn
, ISCSI_MAX_TARGET
);
432 session
= cls_session
->dd_data
;
433 if (iscsi_tcp_r2tpool_alloc(session
))
439 iscsi_session_teardown(cls_session
);
444 * cxgb3i_session_destroy - destroys iscsi session
445 * @cls_session: pointer to iscsi cls session
447 * Destroys an iSCSI session instance and releases its all resources held
449 static void cxgb3i_session_destroy(struct iscsi_cls_session
*cls_session
)
451 cxgb3i_api_debug("sess 0x%p.\n", cls_session
);
452 iscsi_tcp_r2tpool_free(cls_session
->dd_data
);
453 iscsi_session_teardown(cls_session
);
457 * cxgb3i_conn_max_xmit_dlength -- calc the max. xmit pdu segment size
458 * @conn: iscsi connection
459 * check the max. xmit pdu payload, reduce it if needed
461 static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn
*conn
)
464 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
465 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
466 unsigned int max
= max(512 * MAX_SKB_FRAGS
, SKB_TX_HEADROOM
);
468 max
= min(cconn
->hba
->snic
->tx_max_size
, max
);
469 if (conn
->max_xmit_dlength
)
470 conn
->max_xmit_dlength
= min(conn
->max_xmit_dlength
, max
);
472 conn
->max_xmit_dlength
= max
;
473 align_pdu_size(conn
->max_xmit_dlength
);
474 cxgb3i_api_debug("conn 0x%p, max xmit %u.\n",
475 conn
, conn
->max_xmit_dlength
);
480 * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size
481 * @conn: iscsi connection
482 * return 0 if the value is valid, < 0 otherwise.
484 static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn
*conn
)
486 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
487 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
488 unsigned int max
= cconn
->hba
->snic
->rx_max_size
;
491 if (conn
->max_recv_dlength
) {
492 if (conn
->max_recv_dlength
> max
) {
493 cxgb3i_log_error("MaxRecvDataSegmentLength %u too big."
494 " Need to be <= %u.\n",
495 conn
->max_recv_dlength
, max
);
498 conn
->max_recv_dlength
= min(conn
->max_recv_dlength
, max
);
499 align_pdu_size(conn
->max_recv_dlength
);
501 conn
->max_recv_dlength
= max
;
502 cxgb3i_api_debug("conn 0x%p, max recv %u.\n",
503 conn
, conn
->max_recv_dlength
);
508 * cxgb3i_conn_create - create iscsi connection instance
509 * @cls_session: pointer to iscsi cls session
512 * Creates a new iSCSI connection instance for a given session
514 static struct iscsi_cls_conn
*cxgb3i_conn_create(struct iscsi_cls_session
515 *cls_session
, u32 cid
)
517 struct iscsi_cls_conn
*cls_conn
;
518 struct iscsi_conn
*conn
;
519 struct iscsi_tcp_conn
*tcp_conn
;
520 struct cxgb3i_conn
*cconn
;
522 cxgb3i_api_debug("sess 0x%p, cid %u.\n", cls_session
, cid
);
524 cls_conn
= iscsi_tcp_conn_setup(cls_session
, sizeof(*cconn
), cid
);
527 conn
= cls_conn
->dd_data
;
528 tcp_conn
= conn
->dd_data
;
529 cconn
= tcp_conn
->dd_data
;
536 * cxgb3i_conn_bind - binds iscsi sess, conn and endpoint together
537 * @cls_session: pointer to iscsi cls session
538 * @cls_conn: pointer to iscsi cls conn
539 * @transport_eph: 64-bit EP handle
540 * @is_leading: leading connection on this session?
542 * Binds together an iSCSI session, an iSCSI connection and a
543 * TCP connection. This routine returns error code if the TCP
544 * connection does not belong on the device iSCSI sess/conn is bound
547 static int cxgb3i_conn_bind(struct iscsi_cls_session
*cls_session
,
548 struct iscsi_cls_conn
*cls_conn
,
549 u64 transport_eph
, int is_leading
)
551 struct iscsi_conn
*conn
= cls_conn
->dd_data
;
552 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
553 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
554 struct cxgb3i_adapter
*snic
;
555 struct iscsi_endpoint
*ep
;
556 struct cxgb3i_endpoint
*cep
;
557 struct s3_conn
*c3cn
;
560 ep
= iscsi_lookup_endpoint(transport_eph
);
564 /* setup ddp pagesize */
567 snic
= cep
->hba
->snic
;
568 err
= cxgb3i_setup_conn_host_pagesize(snic
->tdev
, c3cn
->tid
, 0);
572 cxgb3i_api_debug("ep 0x%p, cls sess 0x%p, cls conn 0x%p.\n",
573 ep
, cls_session
, cls_conn
);
575 err
= iscsi_conn_bind(cls_session
, cls_conn
, is_leading
);
579 /* calculate the tag idx bits needed for this conn based on cmds_max */
580 cconn
->task_idx_bits
= (__ilog2_u32(conn
->session
->cmds_max
- 1)) + 1;
581 cxgb3i_api_debug("session cmds_max 0x%x, bits %u.\n",
582 conn
->session
->cmds_max
, cconn
->task_idx_bits
);
584 read_lock(&c3cn
->callback_lock
);
585 c3cn
->user_data
= conn
;
586 cconn
->hba
= cep
->hba
;
589 read_unlock(&c3cn
->callback_lock
);
591 cxgb3i_conn_max_xmit_dlength(conn
);
592 cxgb3i_conn_max_recv_dlength(conn
);
594 spin_lock_bh(&conn
->session
->lock
);
595 sprintf(conn
->portal_address
, "%pI4", &c3cn
->daddr
.sin_addr
.s_addr
);
596 conn
->portal_port
= ntohs(c3cn
->daddr
.sin_port
);
597 spin_unlock_bh(&conn
->session
->lock
);
599 /* init recv engine */
600 iscsi_tcp_hdr_recv_prep(tcp_conn
);
606 * cxgb3i_conn_get_param - return iscsi connection parameter to caller
607 * @cls_conn: pointer to iscsi cls conn
608 * @param: parameter type identifier
609 * @buf: buffer pointer
611 * returns iSCSI connection parameters
613 static int cxgb3i_conn_get_param(struct iscsi_cls_conn
*cls_conn
,
614 enum iscsi_param param
, char *buf
)
616 struct iscsi_conn
*conn
= cls_conn
->dd_data
;
619 cxgb3i_api_debug("cls_conn 0x%p, param %d.\n", cls_conn
, param
);
622 case ISCSI_PARAM_CONN_PORT
:
623 spin_lock_bh(&conn
->session
->lock
);
624 len
= sprintf(buf
, "%hu\n", conn
->portal_port
);
625 spin_unlock_bh(&conn
->session
->lock
);
627 case ISCSI_PARAM_CONN_ADDRESS
:
628 spin_lock_bh(&conn
->session
->lock
);
629 len
= sprintf(buf
, "%s\n", conn
->portal_address
);
630 spin_unlock_bh(&conn
->session
->lock
);
633 return iscsi_conn_get_param(cls_conn
, param
, buf
);
640 * cxgb3i_conn_set_param - set iscsi connection parameter
641 * @cls_conn: pointer to iscsi cls conn
642 * @param: parameter type identifier
643 * @buf: buffer pointer
644 * @buflen: buffer length
646 * set iSCSI connection parameters
648 static int cxgb3i_conn_set_param(struct iscsi_cls_conn
*cls_conn
,
649 enum iscsi_param param
, char *buf
, int buflen
)
651 struct iscsi_conn
*conn
= cls_conn
->dd_data
;
652 struct iscsi_session
*session
= conn
->session
;
653 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
654 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
655 struct cxgb3i_adapter
*snic
= cconn
->hba
->snic
;
656 struct s3_conn
*c3cn
= cconn
->cep
->c3cn
;
660 case ISCSI_PARAM_HDRDGST_EN
:
661 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
662 if (!err
&& conn
->hdrdgst_en
)
663 err
= cxgb3i_setup_conn_digest(snic
->tdev
, c3cn
->tid
,
665 conn
->datadgst_en
, 0);
667 case ISCSI_PARAM_DATADGST_EN
:
668 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
669 if (!err
&& conn
->datadgst_en
)
670 err
= cxgb3i_setup_conn_digest(snic
->tdev
, c3cn
->tid
,
672 conn
->datadgst_en
, 0);
674 case ISCSI_PARAM_MAX_R2T
:
675 sscanf(buf
, "%d", &value
);
676 if (value
<= 0 || !is_power_of_2(value
))
678 if (session
->max_r2t
== value
)
680 iscsi_tcp_r2tpool_free(session
);
681 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
682 if (!err
&& iscsi_tcp_r2tpool_alloc(session
))
684 case ISCSI_PARAM_MAX_RECV_DLENGTH
:
685 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
687 err
= cxgb3i_conn_max_recv_dlength(conn
);
689 case ISCSI_PARAM_MAX_XMIT_DLENGTH
:
690 err
= iscsi_set_param(cls_conn
, param
, buf
, buflen
);
692 err
= cxgb3i_conn_max_xmit_dlength(conn
);
695 return iscsi_set_param(cls_conn
, param
, buf
, buflen
);
701 * cxgb3i_host_set_param - configure host (adapter) related parameters
702 * @shost: scsi host pointer
703 * @param: parameter type identifier
704 * @buf: buffer pointer
706 static int cxgb3i_host_set_param(struct Scsi_Host
*shost
,
707 enum iscsi_host_param param
,
708 char *buf
, int buflen
)
710 struct cxgb3i_hba
*hba
= iscsi_host_priv(shost
);
713 shost_printk(KERN_ERR
, shost
, "Could not set host param. "
714 "Netdev for host not set.\n");
718 cxgb3i_api_debug("param %d, buf %s.\n", param
, buf
);
721 case ISCSI_HOST_PARAM_IPADDRESS
:
723 __be32 addr
= in_aton(buf
);
724 cxgb3i_set_private_ipv4addr(hba
->ndev
, addr
);
727 case ISCSI_HOST_PARAM_HWADDRESS
:
728 case ISCSI_HOST_PARAM_NETDEV_NAME
:
732 return iscsi_host_set_param(shost
, param
, buf
, buflen
);
737 * cxgb3i_host_get_param - returns host (adapter) related parameters
738 * @shost: scsi host pointer
739 * @param: parameter type identifier
740 * @buf: buffer pointer
742 static int cxgb3i_host_get_param(struct Scsi_Host
*shost
,
743 enum iscsi_host_param param
, char *buf
)
745 struct cxgb3i_hba
*hba
= iscsi_host_priv(shost
);
749 shost_printk(KERN_ERR
, shost
, "Could not set host param. "
750 "Netdev for host not set.\n");
754 cxgb3i_api_debug("hba %s, param %d.\n", hba
->ndev
->name
, param
);
757 case ISCSI_HOST_PARAM_HWADDRESS
:
758 len
= sysfs_format_mac(buf
, hba
->ndev
->dev_addr
, 6);
760 case ISCSI_HOST_PARAM_NETDEV_NAME
:
761 len
= sprintf(buf
, "%s\n", hba
->ndev
->name
);
763 case ISCSI_HOST_PARAM_IPADDRESS
:
767 addr
= cxgb3i_get_private_ipv4addr(hba
->ndev
);
768 len
= sprintf(buf
, "%pI4", &addr
);
772 return iscsi_host_get_param(shost
, param
, buf
);
778 * cxgb3i_conn_get_stats - returns iSCSI stats
779 * @cls_conn: pointer to iscsi cls conn
780 * @stats: pointer to iscsi statistic struct
782 static void cxgb3i_conn_get_stats(struct iscsi_cls_conn
*cls_conn
,
783 struct iscsi_stats
*stats
)
785 struct iscsi_conn
*conn
= cls_conn
->dd_data
;
787 stats
->txdata_octets
= conn
->txdata_octets
;
788 stats
->rxdata_octets
= conn
->rxdata_octets
;
789 stats
->scsicmd_pdus
= conn
->scsicmd_pdus_cnt
;
790 stats
->dataout_pdus
= conn
->dataout_pdus_cnt
;
791 stats
->scsirsp_pdus
= conn
->scsirsp_pdus_cnt
;
792 stats
->datain_pdus
= conn
->datain_pdus_cnt
;
793 stats
->r2t_pdus
= conn
->r2t_pdus_cnt
;
794 stats
->tmfcmd_pdus
= conn
->tmfcmd_pdus_cnt
;
795 stats
->tmfrsp_pdus
= conn
->tmfrsp_pdus_cnt
;
796 stats
->digest_err
= 0;
797 stats
->timeout_err
= 0;
798 stats
->custom_length
= 1;
799 strcpy(stats
->custom
[0].desc
, "eh_abort_cnt");
800 stats
->custom
[0].value
= conn
->eh_abort_cnt
;
804 * cxgb3i_parse_itt - get the idx and age bits from a given tag
805 * @conn: iscsi connection
807 * @idx: task index, filled in by this function
808 * @age: session age, filled in by this function
810 static void cxgb3i_parse_itt(struct iscsi_conn
*conn
, itt_t itt
,
813 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
814 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
815 struct cxgb3i_adapter
*snic
= cconn
->hba
->snic
;
816 u32 tag
= ntohl((__force u32
) itt
);
819 sw_bits
= cxgb3i_tag_nonrsvd_bits(&snic
->tag_format
, tag
);
821 *idx
= sw_bits
& ((1 << cconn
->task_idx_bits
) - 1);
823 *age
= (sw_bits
>> cconn
->task_idx_bits
) & ISCSI_AGE_MASK
;
825 cxgb3i_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n",
826 tag
, itt
, sw_bits
, idx
? *idx
: 0xFFFFF,
831 * cxgb3i_reserve_itt - generate tag for a give task
833 * @hdr_itt: tag, filled in by this function
834 * Set up ddp for scsi read tasks if possible.
836 int cxgb3i_reserve_itt(struct iscsi_task
*task
, itt_t
*hdr_itt
)
838 struct scsi_cmnd
*sc
= task
->sc
;
839 struct iscsi_conn
*conn
= task
->conn
;
840 struct iscsi_session
*sess
= conn
->session
;
841 struct iscsi_tcp_conn
*tcp_conn
= conn
->dd_data
;
842 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
843 struct cxgb3i_adapter
*snic
= cconn
->hba
->snic
;
844 struct cxgb3i_tag_format
*tformat
= &snic
->tag_format
;
845 u32 sw_tag
= (sess
->age
<< cconn
->task_idx_bits
) | task
->itt
;
850 (scsi_bidi_cmnd(sc
) || sc
->sc_data_direction
== DMA_FROM_DEVICE
) &&
851 cxgb3i_sw_tag_usable(tformat
, sw_tag
)) {
852 struct s3_conn
*c3cn
= cconn
->cep
->c3cn
;
853 struct cxgb3i_gather_list
*gl
;
855 gl
= cxgb3i_ddp_make_gl(scsi_in(sc
)->length
,
856 scsi_in(sc
)->table
.sgl
,
857 scsi_in(sc
)->table
.nents
,
862 err
= cxgb3i_ddp_tag_reserve(snic
->tdev
, c3cn
->tid
,
866 cxgb3i_ddp_release_gl(gl
, snic
->pdev
);
871 tag
= cxgb3i_set_non_ddp_tag(tformat
, sw_tag
);
872 /* the itt need to sent in big-endian order */
873 *hdr_itt
= (__force itt_t
)htonl(tag
);
875 cxgb3i_tag_debug("new tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n",
876 tag
, *hdr_itt
, task
->itt
, sess
->age
);
881 * cxgb3i_release_itt - release the tag for a given task
884 * If the tag is a ddp tag, release the ddp setup
886 void cxgb3i_release_itt(struct iscsi_task
*task
, itt_t hdr_itt
)
888 struct scsi_cmnd
*sc
= task
->sc
;
889 struct iscsi_tcp_conn
*tcp_conn
= task
->conn
->dd_data
;
890 struct cxgb3i_conn
*cconn
= tcp_conn
->dd_data
;
891 struct cxgb3i_adapter
*snic
= cconn
->hba
->snic
;
892 struct cxgb3i_tag_format
*tformat
= &snic
->tag_format
;
893 u32 tag
= ntohl((__force u32
)hdr_itt
);
895 cxgb3i_tag_debug("release tag 0x%x.\n", tag
);
898 (scsi_bidi_cmnd(sc
) || sc
->sc_data_direction
== DMA_FROM_DEVICE
) &&
899 cxgb3i_is_ddp_tag(tformat
, tag
))
900 cxgb3i_ddp_tag_release(snic
->tdev
, tag
);
904 * cxgb3i_host_template -- Scsi_Host_Template structure
905 * used when registering with the scsi mid layer
907 static struct scsi_host_template cxgb3i_host_template
= {
908 .module
= THIS_MODULE
,
909 .name
= "Chelsio S3xx iSCSI Initiator",
910 .proc_name
= "cxgb3i",
911 .queuecommand
= iscsi_queuecommand
,
912 .change_queue_depth
= iscsi_change_queue_depth
,
913 .can_queue
= CXGB3I_SCSI_HOST_QDEPTH
,
914 .sg_tablesize
= SG_ALL
,
915 .max_sectors
= 0xFFFF,
916 .cmd_per_lun
= ISCSI_DEF_CMD_PER_LUN
,
917 .eh_abort_handler
= iscsi_eh_abort
,
918 .eh_device_reset_handler
= iscsi_eh_device_reset
,
919 .eh_target_reset_handler
= iscsi_eh_recover_target
,
920 .target_alloc
= iscsi_target_alloc
,
921 .use_clustering
= DISABLE_CLUSTERING
,
925 static struct iscsi_transport cxgb3i_iscsi_transport
= {
926 .owner
= THIS_MODULE
,
928 .caps
= CAP_RECOVERY_L0
| CAP_MULTI_R2T
| CAP_HDRDGST
929 | CAP_DATADGST
| CAP_DIGEST_OFFLOAD
|
931 .param_mask
= ISCSI_MAX_RECV_DLENGTH
|
932 ISCSI_MAX_XMIT_DLENGTH
|
935 ISCSI_INITIAL_R2T_EN
|
940 ISCSI_PDU_INORDER_EN
|
941 ISCSI_DATASEQ_INORDER_EN
|
946 ISCSI_PERSISTENT_PORT
|
947 ISCSI_PERSISTENT_ADDRESS
|
948 ISCSI_TARGET_NAME
| ISCSI_TPGT
|
949 ISCSI_USERNAME
| ISCSI_PASSWORD
|
950 ISCSI_USERNAME_IN
| ISCSI_PASSWORD_IN
|
951 ISCSI_FAST_ABORT
| ISCSI_ABORT_TMO
|
952 ISCSI_LU_RESET_TMO
| ISCSI_TGT_RESET_TMO
|
953 ISCSI_PING_TMO
| ISCSI_RECV_TMO
|
954 ISCSI_IFACE_NAME
| ISCSI_INITIATOR_NAME
,
955 .host_param_mask
= ISCSI_HOST_HWADDRESS
| ISCSI_HOST_IPADDRESS
|
956 ISCSI_HOST_INITIATOR_NAME
| ISCSI_HOST_NETDEV_NAME
,
957 .get_host_param
= cxgb3i_host_get_param
,
958 .set_host_param
= cxgb3i_host_set_param
,
959 /* session management */
960 .create_session
= cxgb3i_session_create
,
961 .destroy_session
= cxgb3i_session_destroy
,
962 .get_session_param
= iscsi_session_get_param
,
963 /* connection management */
964 .create_conn
= cxgb3i_conn_create
,
965 .bind_conn
= cxgb3i_conn_bind
,
966 .destroy_conn
= iscsi_tcp_conn_teardown
,
967 .start_conn
= iscsi_conn_start
,
968 .stop_conn
= iscsi_conn_stop
,
969 .get_conn_param
= cxgb3i_conn_get_param
,
970 .set_param
= cxgb3i_conn_set_param
,
971 .get_stats
= cxgb3i_conn_get_stats
,
972 /* pdu xmit req. from user space */
973 .send_pdu
= iscsi_conn_send_pdu
,
975 .init_task
= iscsi_tcp_task_init
,
976 .xmit_task
= iscsi_tcp_task_xmit
,
977 .cleanup_task
= cxgb3i_conn_cleanup_task
,
980 .alloc_pdu
= cxgb3i_conn_alloc_pdu
,
981 .init_pdu
= cxgb3i_conn_init_pdu
,
982 .xmit_pdu
= cxgb3i_conn_xmit_pdu
,
983 .parse_pdu_itt
= cxgb3i_parse_itt
,
985 /* TCP connect/disconnect */
986 .ep_connect
= cxgb3i_ep_connect
,
987 .ep_poll
= cxgb3i_ep_poll
,
988 .ep_disconnect
= cxgb3i_ep_disconnect
,
989 /* Error recovery timeout call */
990 .session_recovery_timedout
= iscsi_session_recovery_timedout
,
993 int cxgb3i_iscsi_init(void)
995 sw_tag_idx_bits
= (__ilog2_u32(ISCSI_ITT_MASK
)) + 1;
996 sw_tag_age_bits
= (__ilog2_u32(ISCSI_AGE_MASK
)) + 1;
997 cxgb3i_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
998 ISCSI_ITT_MASK
, sw_tag_idx_bits
,
999 ISCSI_AGE_MASK
, sw_tag_age_bits
);
1001 cxgb3i_scsi_transport
=
1002 iscsi_register_transport(&cxgb3i_iscsi_transport
);
1003 if (!cxgb3i_scsi_transport
) {
1004 cxgb3i_log_error("Could not register cxgb3i transport.\n");
1007 cxgb3i_api_debug("cxgb3i transport 0x%p.\n", cxgb3i_scsi_transport
);
1011 void cxgb3i_iscsi_cleanup(void)
1013 if (cxgb3i_scsi_transport
) {
1014 cxgb3i_api_debug("cxgb3i transport 0x%p.\n",
1015 cxgb3i_scsi_transport
);
1016 iscsi_unregister_transport(&cxgb3i_iscsi_transport
);