16 #include <linux/slab.h>
32 static int bnx2i_adapter_ready(
struct bnx2i_hba *hba)
54 static void bnx2i_get_write_cmd_bd_idx(
struct bnx2i_cmd *
cmd,
u32 buf_off,
55 u32 *start_bd_off,
u32 *start_bd_idx)
62 while (buf_off >= (cur_offset + bd_tbl->buffer_length)) {
63 cur_offset += bd_tbl->buffer_length;
69 *start_bd_off = buf_off - cur_offset;
70 *start_bd_idx = cur_bd_idx;
87 u32 buffer_offset = 0;
93 if (!iscsi_task_has_unsol_data(task) && !task->
imm_count)
101 if (iscsi_task_has_unsol_data(task)) {
102 bnx2i_get_write_cmd_bd_idx(cmd, buffer_offset,
103 &start_bd_offset, &start_bd_idx);
104 cmd->
req.ud_buffer_offset = start_bd_offset;
105 cmd->
req.ud_start_bd_index = start_bd_idx;
106 buffer_offset += task->
unsol_r2t.data_length;
109 if (buffer_offset != cmd_len) {
110 bnx2i_get_write_cmd_bd_idx(cmd, buffer_offset,
111 &start_bd_offset, &start_bd_idx);
112 if ((start_bd_offset > task->
conn->session->first_burst) ||
113 (start_bd_idx > scsi_sg_count(cmd->
scsi_cmd))) {
117 "bnx2i- error, buf offset 0x%x "
118 "bd_valid %d use_sg %d\n",
119 buffer_offset, cmd->
io_tbl.bd_valid,
121 for (i = 0; i < cmd->
io_tbl.bd_valid; i++)
123 "bnx2i err, bd[%d]: len %x\n",
124 i, cmd->
io_tbl.bd_tbl[i].\
buffer_length);
126 cmd->
req.sd_buffer_offset = start_bd_offset;
127 cmd->
req.sd_start_bd_index = start_bd_idx;
161 bd[bd_count].buffer_length = sg_len;
162 bd[bd_count].flags = 0;
164 bd[bd_count].flags = ISCSI_BD_FIRST_IN_BD_CHAIN;
166 byte_count += sg_len;
171 bd[bd_count - 1].flags |= ISCSI_BD_LAST_IN_BD_CHAIN;
173 BUG_ON(byte_count != scsi_bufflen(sc));
183 static void bnx2i_iscsi_map_sg_list(
struct bnx2i_cmd *cmd)
187 bd_count = bnx2i_map_scsi_sg(cmd->
conn->hba, cmd);
192 bd[0].buffer_length = bd[0].flags = 0;
194 cmd->
io_tbl.bd_valid = bd_count;
208 if (cmd->
io_tbl.bd_valid && sc) {
214 static void bnx2i_setup_cmd_wqe_template(
struct bnx2i_cmd *cmd)
217 cmd->
req.op_code = 0xFF;
218 cmd->
req.bd_list_addr_lo = (
u32) cmd->
io_tbl.bd_tbl_dma;
219 cmd->
req.bd_list_addr_hi =
235 static int bnx2i_bind_conn_to_iscsi_cid(
struct bnx2i_hba *hba,
239 if (hba && hba->
cid_que.conn_cid_tbl[iscsi_cid]) {
241 "conn bind - entry #%d not free\n", iscsi_cid);
245 hba->
cid_que.conn_cid_tbl[iscsi_cid] = bnx2i_conn;
258 if (!hba->
cid_que.conn_cid_tbl) {
266 return hba->
cid_que.conn_cid_tbl[iscsi_cid];
278 if (!hba->
cid_que.cid_free_cnt)
281 idx = hba->
cid_que.cid_q_cons_idx;
284 hba->
cid_que.cid_q_cons_idx = 0;
296 static void bnx2i_free_iscsi_cid(
struct bnx2i_hba *hba,
u16 iscsi_cid)
300 if (iscsi_cid == (
u16) -1)
305 idx = hba->
cid_que.cid_q_prod_idx;
310 hba->
cid_que.cid_q_prod_idx = 0;
321 static int bnx2i_setup_free_cid_que(
struct bnx2i_hba *hba)
330 if (!hba->
cid_que.cid_que_base)
336 if (!hba->
cid_que.conn_cid_tbl) {
343 hba->
cid_que.cid_q_prod_idx = 0;
344 hba->
cid_que.cid_q_cons_idx = 0;
360 static void bnx2i_release_free_cid_que(
struct bnx2i_hba *hba)
392 INIT_LIST_HEAD(&bnx2i_ep->
link);
394 bnx2i_ep->ep_iscsi_cid = (
u16) -1;
419 bnx2i_ep->
hba->ofld_conns_active--;
421 if (bnx2i_ep->ep_iscsi_cid != (
u16) -1)
422 bnx2i_free_iscsi_cid(bnx2i_ep->
hba, bnx2i_ep->ep_iscsi_cid);
424 if (bnx2i_ep->
conn) {
430 spin_unlock_irqrestore(&bnx2i_resc_lock, flags);
465 static void bnx2i_destroy_cmd_pool(
struct bnx2i_hba *hba,
470 for (i = 0; i < session->
cmds_max; i++) {
490 static int bnx2i_setup_cmd_pool(
struct bnx2i_hba *hba,
495 for (i = 0; i < session->
cmds_max; i++) {
502 if (bnx2i_alloc_bdt(hba, session, cmd))
509 bnx2i_destroy_cmd_pool(hba, session);
521 static int bnx2i_setup_mp_bdt(
struct bnx2i_hba *hba)
551 mp_bdt->flags = ISCSI_BD_LAST_IN_BD_CHAIN |
552 ISCSI_BD_FIRST_IN_BD_CHAIN;
564 static void bnx2i_free_mp_bdt(
struct bnx2i_hba *hba)
602 static int bnx2i_ep_destroy_list_add(
struct bnx2i_hba *hba,
619 static int bnx2i_ep_destroy_list_del(
struct bnx2i_hba *hba,
623 list_del_init(&ep->
link);
636 static int bnx2i_ep_ofld_list_add(
struct bnx2i_hba *hba,
652 static int bnx2i_ep_ofld_list_del(
struct bnx2i_hba *hba,
656 list_del_init(&ep->
link);
680 if (ep->ep_iscsi_cid == iscsi_cid)
708 if (ep->ep_iscsi_cid == iscsi_cid)
727 static void bnx2i_ep_active_list_add(
struct bnx2i_hba *hba,
743 static void bnx2i_ep_active_list_del(
struct bnx2i_hba *hba,
747 list_del_init(&ep->
link);
761 static void bnx2i_setup_host_queue_size(
struct bnx2i_hba *hba,
811 bnx2i_setup_host_queue_size(hba, shost);
824 if (bnx2i_setup_mp_bdt(hba))
837 if (bnx2i_setup_free_cid_que(hba))
886 bnx2i_release_free_cid_que(hba);
888 bnx2i_free_mp_bdt(hba);
920 bnx2i_free_mp_bdt(hba);
921 bnx2i_release_free_cid_que(hba);
932 static void bnx2i_conn_free_login_resources(
struct bnx2i_hba *hba,
933 struct bnx2i_conn *bnx2i_conn)
935 if (bnx2i_conn->
gen_pdu.resp_bd_tbl) {
937 bnx2i_conn->
gen_pdu.resp_bd_tbl,
938 bnx2i_conn->
gen_pdu.resp_bd_dma);
942 if (bnx2i_conn->
gen_pdu.req_bd_tbl) {
944 bnx2i_conn->
gen_pdu.req_bd_tbl,
945 bnx2i_conn->
gen_pdu.req_bd_dma);
949 if (bnx2i_conn->
gen_pdu.resp_buf) {
953 bnx2i_conn->
gen_pdu.resp_dma_addr);
957 if (bnx2i_conn->
gen_pdu.req_buf) {
961 bnx2i_conn->
gen_pdu.req_dma_addr);
973 static int bnx2i_conn_alloc_login_resources(
struct bnx2i_hba *hba,
974 struct bnx2i_conn *bnx2i_conn)
980 &bnx2i_conn->
gen_pdu.req_dma_addr,
983 goto login_req_buf_failure;
985 bnx2i_conn->
gen_pdu.req_buf_size = 0;
991 &bnx2i_conn->
gen_pdu.resp_dma_addr,
994 goto login_resp_buf_failure;
999 bnx2i_conn->
gen_pdu.req_bd_tbl =
1003 goto login_req_bd_tbl_failure;
1005 bnx2i_conn->
gen_pdu.resp_bd_tbl =
1007 &bnx2i_conn->
gen_pdu.resp_bd_dma,
1010 goto login_resp_bd_tbl_failure;
1014 login_resp_bd_tbl_failure:
1016 bnx2i_conn->
gen_pdu.req_bd_tbl,
1017 bnx2i_conn->
gen_pdu.req_bd_dma);
1020 login_req_bd_tbl_failure:
1023 bnx2i_conn->
gen_pdu.resp_dma_addr);
1025 login_resp_buf_failure:
1028 bnx2i_conn->
gen_pdu.req_dma_addr);
1030 login_req_buf_failure:
1032 "login resource alloc failed!!\n");
1045 static void bnx2i_iscsi_prep_generic_pdu_bd(
struct bnx2i_conn *bnx2i_conn)
1054 bd_tbl->buffer_length = bnx2i_conn->
gen_pdu.req_wr_ptr -
1056 bd_tbl->reserved0 = 0;
1057 bd_tbl->flags = ISCSI_BD_LAST_IN_BD_CHAIN |
1058 ISCSI_BD_FIRST_IN_BD_CHAIN;
1064 bd_tbl->reserved0 = 0;
1065 bd_tbl->flags = ISCSI_BD_LAST_IN_BD_CHAIN |
1066 ISCSI_BD_FIRST_IN_BD_CHAIN;
1077 static int bnx2i_iscsi_send_generic_request(
struct iscsi_task *task)
1080 struct bnx2i_conn *bnx2i_conn = cmd->
conn;
1085 bnx2i_iscsi_prep_generic_pdu_bd(bnx2i_conn);
1091 data_len = bnx2i_conn->
gen_pdu.req_buf_size;
1092 buf = bnx2i_conn->
gen_pdu.req_buf;
1111 "send_gen: unsupported op 0x%x\n",
1141 dstp = (
u32 *) cmd->
req.cdb;
1143 memcpy(&dword, (
const void *) srcp, 4);
1149 dword = (
u32) srcp[0] | ((
u32) srcp[1] << 8);
1154 static void bnx2i_cleanup_task(
struct iscsi_task *task)
1157 struct bnx2i_conn *bnx2i_conn = conn->
dd_data;
1171 spin_unlock_bh(&conn->
session->lock);
1174 spin_lock_bh(&conn->
session->lock);
1187 struct bnx2i_conn *bnx2i_conn = conn->
dd_data;
1193 bnx2i_setup_cmd_wqe_template(cmd);
1203 bnx2i_conn->
gen_pdu.req_wr_ptr =
1208 return bnx2i_iscsi_send_generic_request(task);
1217 static int bnx2i_task_xmit(
struct iscsi_task *task)
1223 struct bnx2i_conn *bnx2i_conn = conn->
dd_data;
1236 return bnx2i_mtask_xmit(conn, task);
1238 bnx2i_setup_cmd_wqe_template(cmd);
1240 cmd->
conn = bnx2i_conn;
1242 cmd->
req.total_data_transfer_length = scsi_bufflen(sc);
1245 bnx2i_iscsi_map_sg_list(cmd);
1246 bnx2i_cpy_scsi_cdb(sc, cmd);
1250 cmd->
req.op_attr |= ISCSI_CMD_REQUEST_WRITE;
1251 cmd->
req.itt = task->
itt |
1253 bnx2i_setup_write_cmd_bd_info(task);
1255 if (scsi_bufflen(sc))
1256 cmd->
req.op_attr |= ISCSI_CMD_REQUEST_READ;
1257 cmd->
req.itt = task->
itt |
1261 cmd->
req.num_bds = cmd->
io_tbl.bd_valid;
1262 if (!cmd->
io_tbl.bd_valid) {
1265 cmd->
req.num_bds = 1;
1296 shost = bnx2i_ep->
hba->shost;
1298 if (bnx2i_adapter_ready(hba))
1316 if (bnx2i_setup_cmd_pool(hba, cls_session->
dd_data))
1317 goto session_teardown;
1339 bnx2i_destroy_cmd_pool(hba, session);
1356 struct bnx2i_conn *bnx2i_conn;
1368 bnx2i_conn->
hba = hba;
1376 if (bnx2i_conn_alloc_login_resources(hba, bnx2i_conn)) {
1378 "conn_new: login resc alloc failed!!\n");
1406 struct bnx2i_conn *bnx2i_conn = conn->
dd_data;
1420 if (bnx2i_adapter_ready(hba))
1432 if (bnx2i_ep->
hba != hba) {
1436 "conn bind, ep=0x%p (%s) does not",
1437 bnx2i_ep, bnx2i_ep->
hba->netdev->name);
1439 "belong to hba (%s)\n",
1443 bnx2i_ep->
conn = bnx2i_conn;
1444 bnx2i_conn->
ep = bnx2i_ep;
1446 bnx2i_conn->
fw_cid = bnx2i_ep->ep_cid;
1448 ret_code = bnx2i_bind_conn_to_iscsi_cid(hba, bnx2i_conn,
1449 bnx2i_ep->ep_iscsi_cid);
1472 struct bnx2i_conn *bnx2i_conn = conn->
dd_data;
1482 bnx2i_conn_free_login_resources(hba, bnx2i_conn);
1486 p = &
per_cpu(bnx2i_percpu, cpu);
1492 list_del_init(&work->
list);
1528 if (bnx2i_ep->
cm_sk)
1529 len =
sprintf(buf,
"%hu\n", bnx2i_ep->
cm_sk->dst_port);
1534 if (bnx2i_ep->
cm_sk)
1535 len =
sprintf(buf,
"%pI4\n", &bnx2i_ep->
cm_sk->dst_ip);
1551 static int bnx2i_host_get_param(
struct Scsi_Host *shost,
1575 csk = bnx2i_ep->
cm_sk;
1599 struct bnx2i_conn *bnx2i_conn = conn->
dd_data;
1608 bnx2i_conn->
ep->ofld_timer.expires = 1 *
HZ +
jiffies;
1610 bnx2i_conn->
ep->ofld_timer.data = (
unsigned long) bnx2i_conn->
ep;
1630 static void bnx2i_conn_get_stats(
struct iscsi_cls_conn *cls_conn,
1645 strcpy(stats->custom[2].desc,
"eh_abort_cnt");
1666 if (hba && hba->
cnic)
1670 "can't connect using cnic\n");
1677 if (bnx2i_adapter_ready(hba)) {
1701 static int bnx2i_tear_down_conn(
struct bnx2i_hba *hba,
1709 if (ep->
conn && ep->
conn->cls_conn &&
1710 ep->
conn->cls_conn->dd_data) {
1721 "please submit GRC Dump, NW/PCIe trace, "
1722 "driver msgs to developers for analysis\n",
1733 bnx2i_ep_destroy_list_add(hba, ep);
1746 bnx2i_ep_destroy_list_del(hba, ep);
1790 hba = bnx2i_check_route(dst_addr);
1798 if (bnx2i_adapter_ready(hba) || !hba->
cid_que.cid_free_cnt) {
1803 ep = bnx2i_alloc_ep(hba);
1811 iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
1812 if (iscsi_cid == -1) {
1814 "iscsi cid\n", hba->
netdev->name);
1824 "\n", hba->
netdev->name);
1829 bnx2i_ep->ep_iscsi_cid = (
u16)iscsi_cid;
1831 bnx2i_ep_ofld_list_add(hba, bnx2i_ep);
1842 hba->
netdev->name, bnx2i_ep->ep_iscsi_cid);
1847 "\n", hba->
netdev->name);
1848 bnx2i_ep_ofld_list_del(hba, bnx2i_ep);
1860 bnx2i_ep_ofld_list_del(hba, bnx2i_ep);
1865 hba->
netdev->name, bnx2i_ep->ep_iscsi_cid);
1873 iscsi_cid, &bnx2i_ep->
cm_sk, bnx2i_ep);
1880 bnx2i_ep->
cm_sk->rcv_buf = 256 * 1024;
1881 bnx2i_ep->
cm_sk->snd_buf = 256 * 1024;
1887 saddr.remote.v4 = *desti;
1891 saddr.remote.v6 = *desti6;
1905 bnx2i_ep_active_list_add(hba, bnx2i_ep);
1914 bnx2i_ep_active_list_del(hba, bnx2i_ep);
1916 if (bnx2i_tear_down_conn(hba, bnx2i_ep)) {
1952 ((bnx2i_ep->
state ==
1977 static int bnx2i_ep_tcp_conn_active(
struct bnx2i_endpoint *bnx2i_ep)
1980 int cnic_dev_10g = 0;
1985 switch (bnx2i_ep->
state) {
2043 if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
2046 if (bnx2i_ep->
conn) {
2047 conn = bnx2i_ep->
conn->cls_conn->dd_data;
2061 spin_lock_bh(&session->
lock);
2067 " logout response was not "
2069 bnx2i_ep->
hba->netdev->name);
2070 }
else if (bnx2i_ep->
state ==
2077 spin_unlock_bh(&session->
lock);
2089 bnx2i_ep->
hba->netdev->name, close, close_ret);
2100 bnx2i_ep_active_list_del(hba, bnx2i_ep);
2101 if (bnx2i_tear_down_conn(hba, bnx2i_ep))
2118 struct bnx2i_conn *bnx2i_conn =
NULL;
2132 if (bnx2i_ep->
conn) {
2133 bnx2i_conn = bnx2i_ep->
conn;
2134 conn = bnx2i_conn->
cls_conn->dd_data;
2137 hba = bnx2i_ep->
hba;
2149 bnx2i_ep_active_list_del(hba, bnx2i_ep);
2180 char *buf = (
char *) params;
2181 u16 len =
sizeof(*params);
2192 switch (param_type) {
2250 .name =
"Broadcom Offload iSCSI Initiator",
2251 .proc_name =
"bnx2i",
2274 .create_session = bnx2i_session_create,
2275 .destroy_session = bnx2i_session_destroy,
2276 .create_conn = bnx2i_conn_create,
2277 .bind_conn = bnx2i_conn_bind,
2278 .destroy_conn = bnx2i_conn_destroy,
2279 .attr_is_visible = bnx2i_attr_is_visible,
2283 .get_host_param = bnx2i_host_get_param,
2284 .start_conn = bnx2i_conn_start,
2287 .xmit_task = bnx2i_task_xmit,
2288 .get_stats = bnx2i_conn_get_stats,
2290 .get_ep_param = bnx2i_ep_get_param,
2291 .ep_connect = bnx2i_ep_connect,
2292 .ep_poll = bnx2i_ep_poll,
2293 .ep_disconnect = bnx2i_ep_disconnect,
2294 .set_path = bnx2i_nl_set_path,
2297 .cleanup_task = bnx2i_cleanup_task,