.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /******************************************************************************* |
---|
2 | 3 | * This file contains tcm implementation using v4 configfs fabric infrastructure |
---|
3 | 4 | * for QLogic target mode HBAs |
---|
.. | .. |
---|
11 | 12 | * |
---|
12 | 13 | * Copyright (c) 2010 Cisco Systems, Inc |
---|
13 | 14 | * |
---|
14 | | - * This program is free software; you can redistribute it and/or modify |
---|
15 | | - * it under the terms of the GNU General Public License as published by |
---|
16 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
17 | | - * (at your option) any later version. |
---|
18 | | - * |
---|
19 | | - * This program is distributed in the hope that it will be useful, |
---|
20 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
21 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
22 | | - * GNU General Public License for more details. |
---|
23 | 15 | ****************************************************************************/ |
---|
24 | 16 | |
---|
25 | 17 | |
---|
26 | 18 | #include <linux/module.h> |
---|
27 | | -#include <linux/moduleparam.h> |
---|
28 | 19 | #include <linux/utsname.h> |
---|
29 | 20 | #include <linux/vmalloc.h> |
---|
30 | | -#include <linux/init.h> |
---|
31 | 21 | #include <linux/list.h> |
---|
32 | 22 | #include <linux/slab.h> |
---|
33 | | -#include <linux/kthread.h> |
---|
34 | 23 | #include <linux/types.h> |
---|
35 | 24 | #include <linux/string.h> |
---|
36 | 25 | #include <linux/configfs.h> |
---|
37 | 26 | #include <linux/ctype.h> |
---|
38 | 27 | #include <asm/unaligned.h> |
---|
39 | | -#include <scsi/scsi.h> |
---|
40 | 28 | #include <scsi/scsi_host.h> |
---|
41 | | -#include <scsi/scsi_device.h> |
---|
42 | | -#include <scsi/scsi_cmnd.h> |
---|
43 | 29 | #include <target/target_core_base.h> |
---|
44 | 30 | #include <target/target_core_fabric.h> |
---|
45 | 31 | |
---|
.. | .. |
---|
108 | 94 | b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); |
---|
109 | 95 | } |
---|
110 | 96 | |
---|
111 | | -static char *tcm_qla2xxx_get_fabric_name(void) |
---|
112 | | -{ |
---|
113 | | - return "qla2xxx"; |
---|
114 | | -} |
---|
115 | | - |
---|
116 | 97 | /* |
---|
117 | 98 | * From drivers/scsi/scsi_transport_fc.c:fc_parse_wwn |
---|
118 | 99 | */ |
---|
.. | .. |
---|
176 | 157 | return rc; |
---|
177 | 158 | |
---|
178 | 159 | return 0; |
---|
179 | | -} |
---|
180 | | - |
---|
181 | | -static char *tcm_qla2xxx_npiv_get_fabric_name(void) |
---|
182 | | -{ |
---|
183 | | - return "qla2xxx_npiv"; |
---|
184 | 160 | } |
---|
185 | 161 | |
---|
186 | 162 | static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) |
---|
.. | .. |
---|
270 | 246 | */ |
---|
271 | 247 | static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) |
---|
272 | 248 | { |
---|
| 249 | + if (!mcmd) |
---|
| 250 | + return; |
---|
273 | 251 | INIT_WORK(&mcmd->free_work, tcm_qla2xxx_complete_mcmd); |
---|
274 | 252 | queue_work(tcm_qla2xxx_free_wq, &mcmd->free_work); |
---|
275 | 253 | } |
---|
.. | .. |
---|
282 | 260 | |
---|
283 | 261 | WARN_ON(cmd->trc_flags & TRC_CMD_FREE); |
---|
284 | 262 | |
---|
| 263 | + /* To do: protect all tgt_counters manipulations with proper locking. */ |
---|
285 | 264 | cmd->qpair->tgt_counters.qla_core_ret_sta_ctio++; |
---|
286 | 265 | cmd->trc_flags |= TRC_CMD_FREE; |
---|
| 266 | + cmd->cmd_sent_to_fw = 0; |
---|
| 267 | + |
---|
287 | 268 | transport_generic_free_cmd(&cmd->se_cmd, 0); |
---|
| 269 | +} |
---|
| 270 | + |
---|
| 271 | +static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct fc_port *sess) |
---|
| 272 | +{ |
---|
| 273 | + struct se_session *se_sess = sess->se_sess; |
---|
| 274 | + struct qla_tgt_cmd *cmd; |
---|
| 275 | + int tag, cpu; |
---|
| 276 | + |
---|
| 277 | + tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); |
---|
| 278 | + if (tag < 0) |
---|
| 279 | + return NULL; |
---|
| 280 | + |
---|
| 281 | + cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag]; |
---|
| 282 | + memset(cmd, 0, sizeof(struct qla_tgt_cmd)); |
---|
| 283 | + cmd->se_cmd.map_tag = tag; |
---|
| 284 | + cmd->se_cmd.map_cpu = cpu; |
---|
| 285 | + |
---|
| 286 | + return cmd; |
---|
| 287 | +} |
---|
| 288 | + |
---|
| 289 | +static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd) |
---|
| 290 | +{ |
---|
| 291 | + target_free_tag(cmd->sess->se_sess, &cmd->se_cmd); |
---|
288 | 292 | } |
---|
289 | 293 | |
---|
290 | 294 | /* |
---|
.. | .. |
---|
332 | 336 | qlt_free_mcmd(mcmd); |
---|
333 | 337 | return; |
---|
334 | 338 | } |
---|
335 | | - |
---|
336 | 339 | cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); |
---|
| 340 | + |
---|
| 341 | + if (WARN_ON(cmd->cmd_sent_to_fw)) |
---|
| 342 | + return; |
---|
| 343 | + |
---|
337 | 344 | qlt_free_cmd(cmd); |
---|
338 | 345 | } |
---|
339 | 346 | |
---|
.. | .. |
---|
366 | 373 | target_sess_cmd_list_set_waiting(se_sess); |
---|
367 | 374 | spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); |
---|
368 | 375 | |
---|
| 376 | + sess->explicit_logout = 1; |
---|
369 | 377 | tcm_qla2xxx_put_sess(sess); |
---|
370 | 378 | } |
---|
371 | 379 | |
---|
.. | .. |
---|
407 | 415 | se_cmd->pi_err = 0; |
---|
408 | 416 | |
---|
409 | 417 | /* |
---|
410 | | - * qla_target.c:qlt_rdy_to_xfer() will call pci_map_sg() to setup |
---|
| 418 | + * qla_target.c:qlt_rdy_to_xfer() will call dma_map_sg() to setup |
---|
411 | 419 | * the SGL mappings into PCIe memory for incoming FCP WRITE data. |
---|
412 | 420 | */ |
---|
413 | 421 | return qlt_rdy_to_xfer(cmd); |
---|
414 | | -} |
---|
415 | | - |
---|
416 | | -static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd) |
---|
417 | | -{ |
---|
418 | | - unsigned long flags; |
---|
419 | | - /* |
---|
420 | | - * Check for WRITE_PENDING status to determine if we need to wait for |
---|
421 | | - * CTIO aborts to be posted via hardware in tcm_qla2xxx_handle_data(). |
---|
422 | | - */ |
---|
423 | | - spin_lock_irqsave(&se_cmd->t_state_lock, flags); |
---|
424 | | - if (se_cmd->t_state == TRANSPORT_WRITE_PENDING || |
---|
425 | | - se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { |
---|
426 | | - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); |
---|
427 | | - wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, |
---|
428 | | - 50); |
---|
429 | | - return 0; |
---|
430 | | - } |
---|
431 | | - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); |
---|
432 | | - |
---|
433 | | - return 0; |
---|
434 | 422 | } |
---|
435 | 423 | |
---|
436 | 424 | static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl) |
---|
.. | .. |
---|
507 | 495 | * Otherwise return an exception via CHECK_CONDITION status. |
---|
508 | 496 | */ |
---|
509 | 497 | cmd->cmd_in_wq = 0; |
---|
| 498 | + cmd->cmd_sent_to_fw = 0; |
---|
| 499 | + if (cmd->aborted) { |
---|
| 500 | + transport_generic_request_failure(&cmd->se_cmd, |
---|
| 501 | + TCM_CHECK_CONDITION_ABORT_CMD); |
---|
| 502 | + return; |
---|
| 503 | + } |
---|
510 | 504 | |
---|
511 | 505 | cmd->qpair->tgt_counters.qla_core_ret_ctio++; |
---|
512 | 506 | if (!cmd->write_data_transferred) { |
---|
513 | | - /* |
---|
514 | | - * Check if se_cmd has already been aborted via LUN_RESET, and |
---|
515 | | - * waiting upon completion in tcm_qla2xxx_write_pending_status() |
---|
516 | | - */ |
---|
517 | | - if (cmd->se_cmd.transport_state & CMD_T_ABORTED) { |
---|
518 | | - complete(&cmd->se_cmd.t_transport_stop_comp); |
---|
519 | | - return; |
---|
520 | | - } |
---|
521 | | - |
---|
522 | 507 | switch (cmd->dif_err_code) { |
---|
523 | 508 | case DIF_ERR_GRD: |
---|
524 | 509 | cmd->se_cmd.pi_err = |
---|
.. | .. |
---|
861 | 846 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \ |
---|
862 | 847 | struct tcm_qla2xxx_tpg, se_tpg); \ |
---|
863 | 848 | \ |
---|
864 | | - return sprintf(page, "%u\n", tpg->tpg_attrib.name); \ |
---|
| 849 | + return sprintf(page, "%d\n", tpg->tpg_attrib.name); \ |
---|
865 | 850 | } \ |
---|
866 | 851 | \ |
---|
867 | 852 | static ssize_t tcm_qla2xxx_tpg_attrib_##name##_store( \ |
---|
.. | .. |
---|
1179 | 1164 | /* |
---|
1180 | 1165 | * Expected to be called with struct qla_hw_data->tgt.sess_lock held |
---|
1181 | 1166 | */ |
---|
1182 | | -static struct fc_port *tcm_qla2xxx_find_sess_by_s_id( |
---|
1183 | | - scsi_qla_host_t *vha, |
---|
1184 | | - const uint8_t *s_id) |
---|
| 1167 | +static struct fc_port *tcm_qla2xxx_find_sess_by_s_id(scsi_qla_host_t *vha, |
---|
| 1168 | + const be_id_t s_id) |
---|
1185 | 1169 | { |
---|
1186 | 1170 | struct tcm_qla2xxx_lport *lport; |
---|
1187 | 1171 | struct se_node_acl *se_nacl; |
---|
.. | .. |
---|
1224 | 1208 | struct tcm_qla2xxx_nacl *nacl, |
---|
1225 | 1209 | struct se_session *se_sess, |
---|
1226 | 1210 | struct fc_port *fc_port, |
---|
1227 | | - uint8_t *s_id) |
---|
| 1211 | + be_id_t s_id) |
---|
1228 | 1212 | { |
---|
1229 | 1213 | u32 key; |
---|
1230 | 1214 | void *slot; |
---|
.. | .. |
---|
1391 | 1375 | struct tcm_qla2xxx_nacl *nacl, struct fc_port *sess) |
---|
1392 | 1376 | { |
---|
1393 | 1377 | struct se_session *se_sess = sess->se_sess; |
---|
1394 | | - unsigned char be_sid[3]; |
---|
1395 | | - |
---|
1396 | | - be_sid[0] = sess->d_id.b.domain; |
---|
1397 | | - be_sid[1] = sess->d_id.b.area; |
---|
1398 | | - be_sid[2] = sess->d_id.b.al_pa; |
---|
1399 | 1378 | |
---|
1400 | 1379 | tcm_qla2xxx_set_sess_by_s_id(lport, NULL, nacl, se_sess, |
---|
1401 | | - sess, be_sid); |
---|
| 1380 | + sess, port_id_to_be_id(sess->d_id)); |
---|
1402 | 1381 | tcm_qla2xxx_set_sess_by_loop_id(lport, NULL, nacl, se_sess, |
---|
1403 | 1382 | sess, sess->loop_id); |
---|
1404 | 1383 | } |
---|
.. | .. |
---|
1444 | 1423 | struct fc_port *qlat_sess = p; |
---|
1445 | 1424 | uint16_t loop_id = qlat_sess->loop_id; |
---|
1446 | 1425 | unsigned long flags; |
---|
1447 | | - unsigned char be_sid[3]; |
---|
1448 | | - |
---|
1449 | | - be_sid[0] = qlat_sess->d_id.b.domain; |
---|
1450 | | - be_sid[1] = qlat_sess->d_id.b.area; |
---|
1451 | | - be_sid[2] = qlat_sess->d_id.b.al_pa; |
---|
1452 | 1426 | |
---|
1453 | 1427 | /* |
---|
1454 | 1428 | * And now setup se_nacl and session pointers into HW lport internal |
---|
1455 | 1429 | * mappings for fabric S_ID and LOOP_ID. |
---|
1456 | 1430 | */ |
---|
1457 | 1431 | spin_lock_irqsave(&ha->tgt.sess_lock, flags); |
---|
1458 | | - tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, |
---|
1459 | | - se_sess, qlat_sess, be_sid); |
---|
| 1432 | + tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess, qlat_sess, |
---|
| 1433 | + port_id_to_be_id(qlat_sess->d_id)); |
---|
1460 | 1434 | tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, |
---|
1461 | 1435 | se_sess, qlat_sess, loop_id); |
---|
1462 | 1436 | spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); |
---|
.. | .. |
---|
1492 | 1466 | */ |
---|
1493 | 1467 | tpg = lport->tpg_1; |
---|
1494 | 1468 | if (!tpg) { |
---|
1495 | | - pr_err("Unable to lcoate struct tcm_qla2xxx_lport->tpg_1\n"); |
---|
| 1469 | + pr_err("Unable to locate struct tcm_qla2xxx_lport->tpg_1\n"); |
---|
1496 | 1470 | return -EINVAL; |
---|
1497 | 1471 | } |
---|
1498 | 1472 | /* |
---|
.. | .. |
---|
1596 | 1570 | .handle_cmd = tcm_qla2xxx_handle_cmd, |
---|
1597 | 1571 | .handle_data = tcm_qla2xxx_handle_data, |
---|
1598 | 1572 | .handle_tmr = tcm_qla2xxx_handle_tmr, |
---|
| 1573 | + .get_cmd = tcm_qla2xxx_get_cmd, |
---|
| 1574 | + .rel_cmd = tcm_qla2xxx_rel_cmd, |
---|
1599 | 1575 | .free_cmd = tcm_qla2xxx_free_cmd, |
---|
1600 | 1576 | .free_mcmd = tcm_qla2xxx_free_mcmd, |
---|
1601 | 1577 | .free_session = tcm_qla2xxx_free_session, |
---|
.. | .. |
---|
1852 | 1828 | |
---|
1853 | 1829 | static const struct target_core_fabric_ops tcm_qla2xxx_ops = { |
---|
1854 | 1830 | .module = THIS_MODULE, |
---|
1855 | | - .name = "qla2xxx", |
---|
| 1831 | + .fabric_name = "qla2xxx", |
---|
1856 | 1832 | .node_acl_size = sizeof(struct tcm_qla2xxx_nacl), |
---|
1857 | 1833 | /* |
---|
1858 | 1834 | * XXX: Limit assumes single page per scatter-gather-list entry. |
---|
1859 | 1835 | * Current maximum is ~4.9 MB per se_cmd->t_data_sg with PAGE_SIZE=4096 |
---|
1860 | 1836 | */ |
---|
1861 | 1837 | .max_data_sg_nents = 1200, |
---|
1862 | | - .get_fabric_name = tcm_qla2xxx_get_fabric_name, |
---|
1863 | 1838 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, |
---|
1864 | 1839 | .tpg_get_tag = tcm_qla2xxx_get_tag, |
---|
1865 | 1840 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, |
---|
.. | .. |
---|
1877 | 1852 | .sess_get_index = tcm_qla2xxx_sess_get_index, |
---|
1878 | 1853 | .sess_get_initiator_sid = NULL, |
---|
1879 | 1854 | .write_pending = tcm_qla2xxx_write_pending, |
---|
1880 | | - .write_pending_status = tcm_qla2xxx_write_pending_status, |
---|
1881 | 1855 | .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, |
---|
1882 | 1856 | .get_cmd_state = tcm_qla2xxx_get_cmd_state, |
---|
1883 | 1857 | .queue_data_in = tcm_qla2xxx_queue_data_in, |
---|
.. | .. |
---|
1901 | 1875 | |
---|
1902 | 1876 | static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { |
---|
1903 | 1877 | .module = THIS_MODULE, |
---|
1904 | | - .name = "qla2xxx_npiv", |
---|
| 1878 | + .fabric_name = "qla2xxx_npiv", |
---|
1905 | 1879 | .node_acl_size = sizeof(struct tcm_qla2xxx_nacl), |
---|
1906 | | - .get_fabric_name = tcm_qla2xxx_npiv_get_fabric_name, |
---|
1907 | 1880 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, |
---|
1908 | 1881 | .tpg_get_tag = tcm_qla2xxx_get_tag, |
---|
1909 | 1882 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, |
---|
.. | .. |
---|
1919 | 1892 | .sess_get_index = tcm_qla2xxx_sess_get_index, |
---|
1920 | 1893 | .sess_get_initiator_sid = NULL, |
---|
1921 | 1894 | .write_pending = tcm_qla2xxx_write_pending, |
---|
1922 | | - .write_pending_status = tcm_qla2xxx_write_pending_status, |
---|
1923 | 1895 | .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, |
---|
1924 | 1896 | .get_cmd_state = tcm_qla2xxx_get_cmd_state, |
---|
1925 | 1897 | .queue_data_in = tcm_qla2xxx_queue_data_in, |
---|
.. | .. |
---|
1984 | 1956 | { |
---|
1985 | 1957 | int ret; |
---|
1986 | 1958 | |
---|
| 1959 | + BUILD_BUG_ON(sizeof(struct abts_recv_from_24xx) != 64); |
---|
| 1960 | + BUILD_BUG_ON(sizeof(struct abts_resp_from_24xx_fw) != 64); |
---|
| 1961 | + BUILD_BUG_ON(sizeof(struct atio7_fcp_cmnd) != 32); |
---|
| 1962 | + BUILD_BUG_ON(sizeof(struct atio_from_isp) != 64); |
---|
| 1963 | + BUILD_BUG_ON(sizeof(struct ba_acc_le) != 12); |
---|
| 1964 | + BUILD_BUG_ON(sizeof(struct ba_rjt_le) != 4); |
---|
| 1965 | + BUILD_BUG_ON(sizeof(struct ctio7_from_24xx) != 64); |
---|
| 1966 | + BUILD_BUG_ON(sizeof(struct ctio7_to_24xx) != 64); |
---|
| 1967 | + BUILD_BUG_ON(sizeof(struct ctio_crc2_to_fw) != 64); |
---|
| 1968 | + BUILD_BUG_ON(sizeof(struct ctio_crc_from_fw) != 64); |
---|
| 1969 | + BUILD_BUG_ON(sizeof(struct ctio_to_2xxx) != 64); |
---|
| 1970 | + BUILD_BUG_ON(sizeof(struct fcp_hdr) != 24); |
---|
| 1971 | + BUILD_BUG_ON(sizeof(struct fcp_hdr_le) != 24); |
---|
| 1972 | + BUILD_BUG_ON(sizeof(struct nack_to_isp) != 64); |
---|
| 1973 | + |
---|
1987 | 1974 | ret = tcm_qla2xxx_register_configfs(); |
---|
1988 | 1975 | if (ret < 0) |
---|
1989 | 1976 | return ret; |
---|