1682 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.5 */6 7#include <target/target_core_base.h>8#include <target/target_core_fabric.h>9#include "efct_driver.h"10#include "efct_lio.h"11 12/*13 * lio_wq is used to call the LIO backed during creation or deletion of14 * sessions. This brings serialization to the session management as we create15 * single threaded work queue.16 */17static struct workqueue_struct *lio_wq;18 19static int20efct_format_wwn(char *str, size_t len, const char *pre, u64 wwn)21{22 u8 a[8];23 24 put_unaligned_be64(wwn, a);25 return snprintf(str, len, "%s%8phC", pre, a);26}27 28static int29efct_lio_parse_wwn(const char *name, u64 *wwp, u8 npiv)30{31 int num;32 u8 b[8];33 34 if (npiv) {35 num = sscanf(name,36 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",37 &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], &b[6],38 &b[7]);39 } else {40 num = sscanf(name,41 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",42 &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], &b[6],43 &b[7]);44 }45 46 if (num != 8)47 return -EINVAL;48 49 *wwp = get_unaligned_be64(b);50 return 0;51}52 53static int54efct_lio_parse_npiv_wwn(const char *name, size_t size, u64 *wwpn, u64 *wwnn)55{56 unsigned int cnt = size;57 int rc;58 59 *wwpn = *wwnn = 0;60 if (name[cnt - 1] == '\n' || name[cnt - 1] == 0)61 cnt--;62 63 /* validate we have enough characters for WWPN */64 if ((cnt != (16 + 1 + 16)) || (name[16] != ':'))65 return -EINVAL;66 67 rc = efct_lio_parse_wwn(&name[0], wwpn, 1);68 if (rc)69 return rc;70 71 rc = efct_lio_parse_wwn(&name[17], wwnn, 1);72 if (rc)73 return rc;74 75 return 0;76}77 78static ssize_t79efct_lio_tpg_enable_show(struct config_item *item, char *page)80{81 struct se_portal_group *se_tpg = to_tpg(item);82 struct efct_lio_tpg *tpg =83 container_of(se_tpg, struct efct_lio_tpg, tpg);84 85 return snprintf(page, PAGE_SIZE, "%d\n", tpg->enabled);86}87 88static ssize_t89efct_lio_tpg_enable_store(struct config_item *item, const char *page,90 size_t count)91{92 struct se_portal_group *se_tpg = to_tpg(item);93 struct efct_lio_tpg *tpg =94 container_of(se_tpg, struct efct_lio_tpg, tpg);95 struct efct *efct;96 struct efc *efc;97 unsigned long op;98 99 if (!tpg->nport || !tpg->nport->efct) {100 pr_err("%s: Unable to find EFCT device\n", __func__);101 return -EINVAL;102 }103 104 efct = tpg->nport->efct;105 efc = efct->efcport;106 107 if (kstrtoul(page, 0, &op) < 0)108 return -EINVAL;109 110 if (op == 1) {111 int ret;112 113 tpg->enabled = true;114 efc_log_debug(efct, "enable portal group %d\n", tpg->tpgt);115 116 ret = efct_xport_control(efct->xport, EFCT_XPORT_PORT_ONLINE);117 if (ret) {118 efct->tgt_efct.lio_nport = NULL;119 efc_log_debug(efct, "cannot bring port online\n");120 return ret;121 }122 } else if (op == 0) {123 efc_log_debug(efct, "disable portal group %d\n", tpg->tpgt);124 125 if (efc->domain && efc->domain->nport)126 efct_scsi_tgt_del_nport(efc, efc->domain->nport);127 128 tpg->enabled = false;129 } else {130 return -EINVAL;131 }132 133 return count;134}135 136static ssize_t137efct_lio_npiv_tpg_enable_show(struct config_item *item, char *page)138{139 struct se_portal_group *se_tpg = to_tpg(item);140 struct efct_lio_tpg *tpg =141 container_of(se_tpg, struct efct_lio_tpg, tpg);142 143 return snprintf(page, PAGE_SIZE, "%d\n", tpg->enabled);144}145 146static ssize_t147efct_lio_npiv_tpg_enable_store(struct config_item *item, const char *page,148 size_t count)149{150 struct se_portal_group *se_tpg = to_tpg(item);151 struct efct_lio_tpg *tpg =152 container_of(se_tpg, struct efct_lio_tpg, tpg);153 struct efct_lio_vport *lio_vport = tpg->vport;154 struct efct *efct;155 struct efc *efc;156 unsigned long op;157 158 if (kstrtoul(page, 0, &op) < 0)159 return -EINVAL;160 161 if (!lio_vport) {162 pr_err("Unable to find vport\n");163 return -EINVAL;164 }165 166 efct = lio_vport->efct;167 efc = efct->efcport;168 169 if (op == 1) {170 tpg->enabled = true;171 efc_log_debug(efct, "enable portal group %d\n", tpg->tpgt);172 173 if (efc->domain) {174 int ret;175 176 ret = efc_nport_vport_new(efc->domain,177 lio_vport->npiv_wwpn,178 lio_vport->npiv_wwnn,179 U32_MAX, false, true,180 NULL, NULL);181 if (ret != 0) {182 efc_log_err(efct, "Failed to create Vport\n");183 return ret;184 }185 return count;186 }187 188 if (!(efc_vport_create_spec(efc, lio_vport->npiv_wwnn,189 lio_vport->npiv_wwpn, U32_MAX,190 false, true, NULL, NULL)))191 return -ENOMEM;192 193 } else if (op == 0) {194 efc_log_debug(efct, "disable portal group %d\n", tpg->tpgt);195 196 tpg->enabled = false;197 /* only physical nport should exist, free lio_nport198 * allocated in efct_lio_make_nport199 */200 if (efc->domain) {201 efc_nport_vport_del(efct->efcport, efc->domain,202 lio_vport->npiv_wwpn,203 lio_vport->npiv_wwnn);204 return count;205 }206 } else {207 return -EINVAL;208 }209 return count;210}211 212static char *efct_lio_get_fabric_wwn(struct se_portal_group *se_tpg)213{214 struct efct_lio_tpg *tpg =215 container_of(se_tpg, struct efct_lio_tpg, tpg);216 217 return tpg->nport->wwpn_str;218}219 220static char *efct_lio_get_npiv_fabric_wwn(struct se_portal_group *se_tpg)221{222 struct efct_lio_tpg *tpg =223 container_of(se_tpg, struct efct_lio_tpg, tpg);224 225 return tpg->vport->wwpn_str;226}227 228static u16 efct_lio_get_tag(struct se_portal_group *se_tpg)229{230 struct efct_lio_tpg *tpg =231 container_of(se_tpg, struct efct_lio_tpg, tpg);232 233 return tpg->tpgt;234}235 236static u16 efct_lio_get_npiv_tag(struct se_portal_group *se_tpg)237{238 struct efct_lio_tpg *tpg =239 container_of(se_tpg, struct efct_lio_tpg, tpg);240 241 return tpg->tpgt;242}243 244static int efct_lio_check_demo_mode(struct se_portal_group *se_tpg)245{246 return 1;247}248 249static int efct_lio_check_demo_mode_cache(struct se_portal_group *se_tpg)250{251 return 1;252}253 254static int efct_lio_check_demo_write_protect(struct se_portal_group *se_tpg)255{256 struct efct_lio_tpg *tpg =257 container_of(se_tpg, struct efct_lio_tpg, tpg);258 259 return tpg->tpg_attrib.demo_mode_write_protect;260}261 262static int263efct_lio_npiv_check_demo_write_protect(struct se_portal_group *se_tpg)264{265 struct efct_lio_tpg *tpg =266 container_of(se_tpg, struct efct_lio_tpg, tpg);267 268 return tpg->tpg_attrib.demo_mode_write_protect;269}270 271static int efct_lio_check_prod_write_protect(struct se_portal_group *se_tpg)272{273 struct efct_lio_tpg *tpg =274 container_of(se_tpg, struct efct_lio_tpg, tpg);275 276 return tpg->tpg_attrib.prod_mode_write_protect;277}278 279static int280efct_lio_npiv_check_prod_write_protect(struct se_portal_group *se_tpg)281{282 struct efct_lio_tpg *tpg =283 container_of(se_tpg, struct efct_lio_tpg, tpg);284 285 return tpg->tpg_attrib.prod_mode_write_protect;286}287 288static int efct_lio_check_stop_free(struct se_cmd *se_cmd)289{290 struct efct_scsi_tgt_io *ocp =291 container_of(se_cmd, struct efct_scsi_tgt_io, cmd);292 struct efct_io *io = container_of(ocp, struct efct_io, tgt_io);293 294 efct_set_lio_io_state(io, EFCT_LIO_STATE_TFO_CHK_STOP_FREE);295 return target_put_sess_cmd(se_cmd);296}297 298static int299efct_lio_abort_tgt_cb(struct efct_io *io,300 enum efct_scsi_io_status scsi_status,301 u32 flags, void *arg)302{303 efct_lio_io_printf(io, "Abort done, status:%d\n", scsi_status);304 return 0;305}306 307static void308efct_lio_aborted_task(struct se_cmd *se_cmd)309{310 struct efct_scsi_tgt_io *ocp =311 container_of(se_cmd, struct efct_scsi_tgt_io, cmd);312 struct efct_io *io = container_of(ocp, struct efct_io, tgt_io);313 314 efct_set_lio_io_state(io, EFCT_LIO_STATE_TFO_ABORTED_TASK);315 316 if (ocp->rsp_sent)317 return;318 319 /* command has been aborted, cleanup here */320 ocp->aborting = true;321 ocp->err = EFCT_SCSI_STATUS_ABORTED;322 /* terminate the exchange */323 efct_scsi_tgt_abort_io(io, efct_lio_abort_tgt_cb, NULL);324}325 326static void efct_lio_release_cmd(struct se_cmd *se_cmd)327{328 struct efct_scsi_tgt_io *ocp =329 container_of(se_cmd, struct efct_scsi_tgt_io, cmd);330 struct efct_io *io = container_of(ocp, struct efct_io, tgt_io);331 struct efct *efct = io->efct;332 333 efct_set_lio_io_state(io, EFCT_LIO_STATE_TFO_RELEASE_CMD);334 efct_set_lio_io_state(io, EFCT_LIO_STATE_SCSI_CMPL_CMD);335 efct_scsi_io_complete(io);336 atomic_sub_return(1, &efct->tgt_efct.ios_in_use);337}338 339static void efct_lio_close_session(struct se_session *se_sess)340{341 struct efc_node *node = se_sess->fabric_sess_ptr;342 343 pr_debug("se_sess=%p node=%p", se_sess, node);344 345 if (!node) {346 pr_debug("node is NULL");347 return;348 }349 350 efc_node_post_shutdown(node, NULL);351}352 353static int efct_lio_get_cmd_state(struct se_cmd *cmd)354{355 struct efct_scsi_tgt_io *ocp =356 container_of(cmd, struct efct_scsi_tgt_io, cmd);357 struct efct_io *io = container_of(ocp, struct efct_io, tgt_io);358 359 return io->tgt_io.state;360}361 362static int363efct_lio_sg_map(struct efct_io *io)364{365 struct efct_scsi_tgt_io *ocp = &io->tgt_io;366 struct se_cmd *cmd = &ocp->cmd;367 368 ocp->seg_map_cnt = dma_map_sg(&io->efct->pci->dev, cmd->t_data_sg,369 cmd->t_data_nents, cmd->data_direction);370 if (ocp->seg_map_cnt == 0)371 return -EFAULT;372 return 0;373}374 375static void376efct_lio_sg_unmap(struct efct_io *io)377{378 struct efct_scsi_tgt_io *ocp = &io->tgt_io;379 struct se_cmd *cmd = &ocp->cmd;380 381 if (WARN_ON(!ocp->seg_map_cnt || !cmd->t_data_sg))382 return;383 384 dma_unmap_sg(&io->efct->pci->dev, cmd->t_data_sg,385 ocp->seg_map_cnt, cmd->data_direction);386 ocp->seg_map_cnt = 0;387}388 389static int390efct_lio_status_done(struct efct_io *io,391 enum efct_scsi_io_status scsi_status,392 u32 flags, void *arg)393{394 struct efct_scsi_tgt_io *ocp = &io->tgt_io;395 396 efct_set_lio_io_state(io, EFCT_LIO_STATE_SCSI_RSP_DONE);397 if (scsi_status != EFCT_SCSI_STATUS_GOOD) {398 efct_lio_io_printf(io, "callback completed with error=%d\n",399 scsi_status);400 ocp->err = scsi_status;401 }402 if (ocp->seg_map_cnt)403 efct_lio_sg_unmap(io);404 405 efct_lio_io_printf(io, "status=%d, err=%d flags=0x%x, dir=%d\n",406 scsi_status, ocp->err, flags, ocp->ddir);407 408 efct_set_lio_io_state(io, EFCT_LIO_STATE_TGT_GENERIC_FREE);409 transport_generic_free_cmd(&io->tgt_io.cmd, 0);410 return 0;411}412 413static int414efct_lio_datamove_done(struct efct_io *io, enum efct_scsi_io_status scsi_status,415 u32 flags, void *arg);416 417static int418efct_lio_write_pending(struct se_cmd *cmd)419{420 struct efct_scsi_tgt_io *ocp =421 container_of(cmd, struct efct_scsi_tgt_io, cmd);422 struct efct_io *io = container_of(ocp, struct efct_io, tgt_io);423 struct efct_scsi_sgl *sgl = io->sgl;424 struct scatterlist *sg;425 u32 flags = 0, cnt, curcnt;426 u64 length = 0;427 428 efct_set_lio_io_state(io, EFCT_LIO_STATE_TFO_WRITE_PENDING);429 efct_lio_io_printf(io, "trans_state=0x%x se_cmd_flags=0x%x\n",430 cmd->transport_state, cmd->se_cmd_flags);431 432 if (ocp->seg_cnt == 0) {433 ocp->seg_cnt = cmd->t_data_nents;434 ocp->cur_seg = 0;435 if (efct_lio_sg_map(io)) {436 efct_lio_io_printf(io, "efct_lio_sg_map failed\n");437 return -EFAULT;438 }439 }440 curcnt = (ocp->seg_map_cnt - ocp->cur_seg);441 curcnt = (curcnt < io->sgl_allocated) ? curcnt : io->sgl_allocated;442 /* find current sg */443 for (cnt = 0, sg = cmd->t_data_sg; cnt < ocp->cur_seg; cnt++,444 sg = sg_next(sg))445 ;/* do nothing */446 447 for (cnt = 0; cnt < curcnt; cnt++, sg = sg_next(sg)) {448 sgl[cnt].addr = sg_dma_address(sg);449 sgl[cnt].dif_addr = 0;450 sgl[cnt].len = sg_dma_len(sg);451 length += sgl[cnt].len;452 ocp->cur_seg++;453 }454 455 if (ocp->cur_seg == ocp->seg_cnt)456 flags = EFCT_SCSI_LAST_DATAPHASE;457 458 return efct_scsi_recv_wr_data(io, flags, sgl, curcnt, length,459 efct_lio_datamove_done, NULL);460}461 462static int463efct_lio_queue_data_in(struct se_cmd *cmd)464{465 struct efct_scsi_tgt_io *ocp =466 container_of(cmd, struct efct_scsi_tgt_io, cmd);467 struct efct_io *io = container_of(ocp, struct efct_io, tgt_io);468 struct efct_scsi_sgl *sgl = io->sgl;469 struct scatterlist *sg = NULL;470 uint flags = 0, cnt = 0, curcnt = 0;471 u64 length = 0;472 473 efct_set_lio_io_state(io, EFCT_LIO_STATE_TFO_QUEUE_DATA_IN);474 475 if (ocp->seg_cnt == 0) {476 if (cmd->data_length) {477 ocp->seg_cnt = cmd->t_data_nents;478 ocp->cur_seg = 0;479 if (efct_lio_sg_map(io)) {480 efct_lio_io_printf(io,481 "efct_lio_sg_map failed\n");482 return -EAGAIN;483 }484 } else {485 /* If command length is 0, send the response status */486 struct efct_scsi_cmd_resp rsp;487 488 memset(&rsp, 0, sizeof(rsp));489 efct_lio_io_printf(io,490 "cmd : %p length 0, send status\n",491 cmd);492 return efct_scsi_send_resp(io, 0, &rsp,493 efct_lio_status_done, NULL);494 }495 }496 curcnt = min(ocp->seg_map_cnt - ocp->cur_seg, io->sgl_allocated);497 498 while (cnt < curcnt) {499 sg = &cmd->t_data_sg[ocp->cur_seg];500 sgl[cnt].addr = sg_dma_address(sg);501 sgl[cnt].dif_addr = 0;502 if (ocp->transferred_len + sg_dma_len(sg) >= cmd->data_length)503 sgl[cnt].len = cmd->data_length - ocp->transferred_len;504 else505 sgl[cnt].len = sg_dma_len(sg);506 507 ocp->transferred_len += sgl[cnt].len;508 length += sgl[cnt].len;509 ocp->cur_seg++;510 cnt++;511 if (ocp->transferred_len == cmd->data_length)512 break;513 }514 515 if (ocp->transferred_len == cmd->data_length) {516 flags = EFCT_SCSI_LAST_DATAPHASE;517 ocp->seg_cnt = ocp->cur_seg;518 }519 520 /* If there is residual, disable Auto Good Response */521 if (cmd->residual_count)522 flags |= EFCT_SCSI_NO_AUTO_RESPONSE;523 524 efct_set_lio_io_state(io, EFCT_LIO_STATE_SCSI_SEND_RD_DATA);525 526 return efct_scsi_send_rd_data(io, flags, sgl, curcnt, length,527 efct_lio_datamove_done, NULL);528}529 530static void531efct_lio_send_resp(struct efct_io *io, enum efct_scsi_io_status scsi_status,532 u32 flags)533{534 struct efct_scsi_cmd_resp rsp;535 struct efct_scsi_tgt_io *ocp = &io->tgt_io;536 struct se_cmd *cmd = &io->tgt_io.cmd;537 int rc;538 539 if (flags & EFCT_SCSI_IO_CMPL_RSP_SENT) {540 ocp->rsp_sent = true;541 efct_set_lio_io_state(io, EFCT_LIO_STATE_TGT_GENERIC_FREE);542 transport_generic_free_cmd(&io->tgt_io.cmd, 0);543 return;544 }545 546 /* send check condition if an error occurred */547 memset(&rsp, 0, sizeof(rsp));548 rsp.scsi_status = cmd->scsi_status;549 rsp.sense_data = (uint8_t *)io->tgt_io.sense_buffer;550 rsp.sense_data_length = cmd->scsi_sense_length;551 552 /* Check for residual underrun or overrun */553 if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT)554 rsp.residual = -cmd->residual_count;555 else if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT)556 rsp.residual = cmd->residual_count;557 558 rc = efct_scsi_send_resp(io, 0, &rsp, efct_lio_status_done, NULL);559 efct_set_lio_io_state(io, EFCT_LIO_STATE_SCSI_SEND_RSP);560 if (rc != 0) {561 efct_lio_io_printf(io, "Read done, send rsp failed %d\n", rc);562 efct_set_lio_io_state(io, EFCT_LIO_STATE_TGT_GENERIC_FREE);563 transport_generic_free_cmd(&io->tgt_io.cmd, 0);564 } else {565 ocp->rsp_sent = true;566 }567}568 569static int570efct_lio_datamove_done(struct efct_io *io, enum efct_scsi_io_status scsi_status,571 u32 flags, void *arg)572{573 struct efct_scsi_tgt_io *ocp = &io->tgt_io;574 575 efct_set_lio_io_state(io, EFCT_LIO_STATE_SCSI_DATA_DONE);576 if (scsi_status != EFCT_SCSI_STATUS_GOOD) {577 efct_lio_io_printf(io, "callback completed with error=%d\n",578 scsi_status);579 ocp->err = scsi_status;580 }581 efct_lio_io_printf(io, "seg_map_cnt=%d\n", ocp->seg_map_cnt);582 if (ocp->seg_map_cnt) {583 if (ocp->err == EFCT_SCSI_STATUS_GOOD &&584 ocp->cur_seg < ocp->seg_cnt) {585 int rc;586 587 efct_lio_io_printf(io, "continuing cmd at segm=%d\n",588 ocp->cur_seg);589 if (ocp->ddir == DMA_TO_DEVICE)590 rc = efct_lio_write_pending(&ocp->cmd);591 else592 rc = efct_lio_queue_data_in(&ocp->cmd);593 if (!rc)594 return 0;595 596 ocp->err = EFCT_SCSI_STATUS_ERROR;597 efct_lio_io_printf(io, "could not continue command\n");598 }599 efct_lio_sg_unmap(io);600 }601 602 if (io->tgt_io.aborting) {603 efct_lio_io_printf(io, "IO done aborted\n");604 return 0;605 }606 607 if (ocp->ddir == DMA_TO_DEVICE) {608 efct_lio_io_printf(io, "Write done, trans_state=0x%x\n",609 io->tgt_io.cmd.transport_state);610 if (scsi_status != EFCT_SCSI_STATUS_GOOD) {611 transport_generic_request_failure(&io->tgt_io.cmd,612 TCM_CHECK_CONDITION_ABORT_CMD);613 efct_set_lio_io_state(io,614 EFCT_LIO_STATE_TGT_GENERIC_REQ_FAILURE);615 } else {616 efct_set_lio_io_state(io,617 EFCT_LIO_STATE_TGT_EXECUTE_CMD);618 target_execute_cmd(&io->tgt_io.cmd);619 }620 } else {621 efct_lio_send_resp(io, scsi_status, flags);622 }623 return 0;624}625 626static int627efct_lio_tmf_done(struct efct_io *io, enum efct_scsi_io_status scsi_status,628 u32 flags, void *arg)629{630 efct_lio_tmfio_printf(io, "cmd=%p status=%d, flags=0x%x\n",631 &io->tgt_io.cmd, scsi_status, flags);632 633 efct_set_lio_io_state(io, EFCT_LIO_STATE_TGT_GENERIC_FREE);634 transport_generic_free_cmd(&io->tgt_io.cmd, 0);635 return 0;636}637 638static int639efct_lio_null_tmf_done(struct efct_io *tmfio,640 enum efct_scsi_io_status scsi_status,641 u32 flags, void *arg)642{643 efct_lio_tmfio_printf(tmfio, "cmd=%p status=%d, flags=0x%x\n",644 &tmfio->tgt_io.cmd, scsi_status, flags);645 646 /* free struct efct_io only, no active se_cmd */647 efct_scsi_io_complete(tmfio);648 return 0;649}650 651static int652efct_lio_queue_status(struct se_cmd *cmd)653{654 struct efct_scsi_cmd_resp rsp;655 struct efct_scsi_tgt_io *ocp =656 container_of(cmd, struct efct_scsi_tgt_io, cmd);657 struct efct_io *io = container_of(ocp, struct efct_io, tgt_io);658 int rc = 0;659 660 efct_set_lio_io_state(io, EFCT_LIO_STATE_TFO_QUEUE_STATUS);661 efct_lio_io_printf(io,662 "status=0x%x trans_state=0x%x se_cmd_flags=0x%x sns_len=%d\n",663 cmd->scsi_status, cmd->transport_state, cmd->se_cmd_flags,664 cmd->scsi_sense_length);665 666 memset(&rsp, 0, sizeof(rsp));667 rsp.scsi_status = cmd->scsi_status;668 rsp.sense_data = (u8 *)io->tgt_io.sense_buffer;669 rsp.sense_data_length = cmd->scsi_sense_length;670 671 /* Check for residual underrun or overrun, mark negitive value for672 * underrun to recognize in HW673 */674 if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT)675 rsp.residual = -cmd->residual_count;676 else if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT)677 rsp.residual = cmd->residual_count;678 679 rc = efct_scsi_send_resp(io, 0, &rsp, efct_lio_status_done, NULL);680 efct_set_lio_io_state(io, EFCT_LIO_STATE_SCSI_SEND_RSP);681 if (rc == 0)682 ocp->rsp_sent = true;683 return rc;684}685 686static void efct_lio_queue_tm_rsp(struct se_cmd *cmd)687{688 struct efct_scsi_tgt_io *ocp =689 container_of(cmd, struct efct_scsi_tgt_io, cmd);690 struct efct_io *tmfio = container_of(ocp, struct efct_io, tgt_io);691 struct se_tmr_req *se_tmr = cmd->se_tmr_req;692 u8 rspcode;693 694 efct_lio_tmfio_printf(tmfio, "cmd=%p function=0x%x tmr->response=%d\n",695 cmd, se_tmr->function, se_tmr->response);696 switch (se_tmr->response) {697 case TMR_FUNCTION_COMPLETE:698 rspcode = EFCT_SCSI_TMF_FUNCTION_COMPLETE;699 break;700 case TMR_TASK_DOES_NOT_EXIST:701 rspcode = EFCT_SCSI_TMF_FUNCTION_IO_NOT_FOUND;702 break;703 case TMR_LUN_DOES_NOT_EXIST:704 rspcode = EFCT_SCSI_TMF_INCORRECT_LOGICAL_UNIT_NUMBER;705 break;706 case TMR_FUNCTION_REJECTED:707 default:708 rspcode = EFCT_SCSI_TMF_FUNCTION_REJECTED;709 break;710 }711 efct_scsi_send_tmf_resp(tmfio, rspcode, NULL, efct_lio_tmf_done, NULL);712}713 714static struct efct *efct_find_wwpn(u64 wwpn)715{716 struct efct *efct;717 718 /* Search for the HBA that has this WWPN */719 list_for_each_entry(efct, &efct_devices, list_entry) {720 721 if (wwpn == efct_get_wwpn(&efct->hw))722 return efct;723 }724 725 return NULL;726}727 728static struct se_wwn *729efct_lio_make_nport(struct target_fabric_configfs *tf,730 struct config_group *group, const char *name)731{732 struct efct_lio_nport *lio_nport;733 struct efct *efct;734 int ret;735 u64 wwpn;736 737 ret = efct_lio_parse_wwn(name, &wwpn, 0);738 if (ret)739 return ERR_PTR(ret);740 741 efct = efct_find_wwpn(wwpn);742 if (!efct) {743 pr_err("cannot find EFCT for base wwpn %s\n", name);744 return ERR_PTR(-ENXIO);745 }746 747 lio_nport = kzalloc(sizeof(*lio_nport), GFP_KERNEL);748 if (!lio_nport)749 return ERR_PTR(-ENOMEM);750 751 lio_nport->efct = efct;752 lio_nport->wwpn = wwpn;753 efct_format_wwn(lio_nport->wwpn_str, sizeof(lio_nport->wwpn_str),754 "naa.", wwpn);755 efct->tgt_efct.lio_nport = lio_nport;756 757 return &lio_nport->nport_wwn;758}759 760static struct se_wwn *761efct_lio_npiv_make_nport(struct target_fabric_configfs *tf,762 struct config_group *group, const char *name)763{764 struct efct_lio_vport *lio_vport;765 struct efct *efct;766 int ret;767 u64 p_wwpn, npiv_wwpn, npiv_wwnn;768 char *p, *pbuf, tmp[128];769 struct efct_lio_vport_list_t *vport_list;770 struct fc_vport *new_fc_vport;771 struct fc_vport_identifiers vport_id;772 unsigned long flags = 0;773 774 snprintf(tmp, sizeof(tmp), "%s", name);775 pbuf = &tmp[0];776 777 p = strsep(&pbuf, "@");778 779 if (!p || !pbuf) {780 pr_err("Unable to find separator operator(@)\n");781 return ERR_PTR(-EINVAL);782 }783 784 ret = efct_lio_parse_wwn(p, &p_wwpn, 0);785 if (ret)786 return ERR_PTR(ret);787 788 ret = efct_lio_parse_npiv_wwn(pbuf, strlen(pbuf), &npiv_wwpn,789 &npiv_wwnn);790 if (ret)791 return ERR_PTR(ret);792 793 efct = efct_find_wwpn(p_wwpn);794 if (!efct) {795 pr_err("cannot find EFCT for base wwpn %s\n", name);796 return ERR_PTR(-ENXIO);797 }798 799 lio_vport = kzalloc(sizeof(*lio_vport), GFP_KERNEL);800 if (!lio_vport)801 return ERR_PTR(-ENOMEM);802 803 lio_vport->efct = efct;804 lio_vport->wwpn = p_wwpn;805 lio_vport->npiv_wwpn = npiv_wwpn;806 lio_vport->npiv_wwnn = npiv_wwnn;807 808 efct_format_wwn(lio_vport->wwpn_str, sizeof(lio_vport->wwpn_str),809 "naa.", npiv_wwpn);810 811 vport_list = kzalloc(sizeof(*vport_list), GFP_KERNEL);812 if (!vport_list) {813 kfree(lio_vport);814 return ERR_PTR(-ENOMEM);815 }816 817 vport_list->lio_vport = lio_vport;818 819 memset(&vport_id, 0, sizeof(vport_id));820 vport_id.port_name = npiv_wwpn;821 vport_id.node_name = npiv_wwnn;822 vport_id.roles = FC_PORT_ROLE_FCP_INITIATOR;823 vport_id.vport_type = FC_PORTTYPE_NPIV;824 vport_id.disable = false;825 826 new_fc_vport = fc_vport_create(efct->shost, 0, &vport_id);827 if (!new_fc_vport) {828 efc_log_err(efct, "fc_vport_create failed\n");829 kfree(lio_vport);830 kfree(vport_list);831 return ERR_PTR(-ENOMEM);832 }833 834 lio_vport->fc_vport = new_fc_vport;835 spin_lock_irqsave(&efct->tgt_efct.efct_lio_lock, flags);836 INIT_LIST_HEAD(&vport_list->list_entry);837 list_add_tail(&vport_list->list_entry, &efct->tgt_efct.vport_list);838 spin_unlock_irqrestore(&efct->tgt_efct.efct_lio_lock, flags);839 840 return &lio_vport->vport_wwn;841}842 843static void844efct_lio_drop_nport(struct se_wwn *wwn)845{846 struct efct_lio_nport *lio_nport =847 container_of(wwn, struct efct_lio_nport, nport_wwn);848 struct efct *efct = lio_nport->efct;849 850 /* only physical nport should exist, free lio_nport allocated851 * in efct_lio_make_nport.852 */853 kfree(efct->tgt_efct.lio_nport);854 efct->tgt_efct.lio_nport = NULL;855}856 857static void858efct_lio_npiv_drop_nport(struct se_wwn *wwn)859{860 struct efct_lio_vport *lio_vport =861 container_of(wwn, struct efct_lio_vport, vport_wwn);862 struct efct_lio_vport_list_t *vport, *next_vport;863 struct efct *efct = lio_vport->efct;864 unsigned long flags = 0;865 866 if (lio_vport->fc_vport)867 fc_vport_terminate(lio_vport->fc_vport);868 869 spin_lock_irqsave(&efct->tgt_efct.efct_lio_lock, flags);870 871 list_for_each_entry_safe(vport, next_vport, &efct->tgt_efct.vport_list,872 list_entry) {873 if (vport->lio_vport == lio_vport) {874 list_del(&vport->list_entry);875 kfree(vport->lio_vport);876 kfree(vport);877 break;878 }879 }880 spin_unlock_irqrestore(&efct->tgt_efct.efct_lio_lock, flags);881}882 883static struct se_portal_group *884efct_lio_make_tpg(struct se_wwn *wwn, const char *name)885{886 struct efct_lio_nport *lio_nport =887 container_of(wwn, struct efct_lio_nport, nport_wwn);888 struct efct_lio_tpg *tpg;889 struct efct *efct;890 unsigned long n;891 int ret;892 893 if (strstr(name, "tpgt_") != name)894 return ERR_PTR(-EINVAL);895 if (kstrtoul(name + 5, 10, &n) || n > USHRT_MAX)896 return ERR_PTR(-EINVAL);897 898 tpg = kzalloc(sizeof(*tpg), GFP_KERNEL);899 if (!tpg)900 return ERR_PTR(-ENOMEM);901 902 tpg->nport = lio_nport;903 tpg->tpgt = n;904 tpg->enabled = false;905 906 tpg->tpg_attrib.generate_node_acls = 1;907 tpg->tpg_attrib.demo_mode_write_protect = 1;908 tpg->tpg_attrib.cache_dynamic_acls = 1;909 tpg->tpg_attrib.demo_mode_login_only = 1;910 tpg->tpg_attrib.session_deletion_wait = 1;911 912 ret = core_tpg_register(wwn, &tpg->tpg, SCSI_PROTOCOL_FCP);913 if (ret < 0) {914 kfree(tpg);915 return NULL;916 }917 efct = lio_nport->efct;918 efct->tgt_efct.tpg = tpg;919 efc_log_debug(efct, "create portal group %d\n", tpg->tpgt);920 921 xa_init(&efct->lookup);922 return &tpg->tpg;923}924 925static void926efct_lio_drop_tpg(struct se_portal_group *se_tpg)927{928 struct efct_lio_tpg *tpg =929 container_of(se_tpg, struct efct_lio_tpg, tpg);930 931 struct efct *efct = tpg->nport->efct;932 933 efc_log_debug(efct, "drop portal group %d\n", tpg->tpgt);934 tpg->nport->efct->tgt_efct.tpg = NULL;935 core_tpg_deregister(se_tpg);936 xa_destroy(&efct->lookup);937 kfree(tpg);938}939 940static struct se_portal_group *941efct_lio_npiv_make_tpg(struct se_wwn *wwn, const char *name)942{943 struct efct_lio_vport *lio_vport =944 container_of(wwn, struct efct_lio_vport, vport_wwn);945 struct efct_lio_tpg *tpg;946 struct efct *efct;947 unsigned long n;948 int ret;949 950 efct = lio_vport->efct;951 if (strstr(name, "tpgt_") != name)952 return ERR_PTR(-EINVAL);953 if (kstrtoul(name + 5, 10, &n) || n > USHRT_MAX)954 return ERR_PTR(-EINVAL);955 956 if (n != 1) {957 efc_log_err(efct, "Invalid tpgt index: %ld provided\n", n);958 return ERR_PTR(-EINVAL);959 }960 961 tpg = kzalloc(sizeof(*tpg), GFP_KERNEL);962 if (!tpg)963 return ERR_PTR(-ENOMEM);964 965 tpg->vport = lio_vport;966 tpg->tpgt = n;967 tpg->enabled = false;968 969 tpg->tpg_attrib.generate_node_acls = 1;970 tpg->tpg_attrib.demo_mode_write_protect = 1;971 tpg->tpg_attrib.cache_dynamic_acls = 1;972 tpg->tpg_attrib.demo_mode_login_only = 1;973 tpg->tpg_attrib.session_deletion_wait = 1;974 975 ret = core_tpg_register(wwn, &tpg->tpg, SCSI_PROTOCOL_FCP);976 977 if (ret < 0) {978 kfree(tpg);979 return NULL;980 }981 lio_vport->tpg = tpg;982 efc_log_debug(efct, "create vport portal group %d\n", tpg->tpgt);983 984 return &tpg->tpg;985}986 987static void988efct_lio_npiv_drop_tpg(struct se_portal_group *se_tpg)989{990 struct efct_lio_tpg *tpg =991 container_of(se_tpg, struct efct_lio_tpg, tpg);992 993 efc_log_debug(tpg->vport->efct, "drop npiv portal group %d\n",994 tpg->tpgt);995 core_tpg_deregister(se_tpg);996 kfree(tpg);997}998 999static int1000efct_lio_init_nodeacl(struct se_node_acl *se_nacl, const char *name)1001{1002 struct efct_lio_nacl *nacl;1003 u64 wwnn;1004 1005 if (efct_lio_parse_wwn(name, &wwnn, 0) < 0)1006 return -EINVAL;1007 1008 nacl = container_of(se_nacl, struct efct_lio_nacl, se_node_acl);1009 nacl->nport_wwnn = wwnn;1010 1011 efct_format_wwn(nacl->nport_name, sizeof(nacl->nport_name), "", wwnn);1012 return 0;1013}1014 1015static int efct_lio_check_demo_mode_login_only(struct se_portal_group *stpg)1016{1017 struct efct_lio_tpg *tpg = container_of(stpg, struct efct_lio_tpg, tpg);1018 1019 return tpg->tpg_attrib.demo_mode_login_only;1020}1021 1022static int1023efct_lio_npiv_check_demo_mode_login_only(struct se_portal_group *stpg)1024{1025 struct efct_lio_tpg *tpg = container_of(stpg, struct efct_lio_tpg, tpg);1026 1027 return tpg->tpg_attrib.demo_mode_login_only;1028}1029 1030static struct efct_lio_tpg *1031efct_get_vport_tpg(struct efc_node *node)1032{1033 struct efct *efct;1034 u64 wwpn = node->nport->wwpn;1035 struct efct_lio_vport_list_t *vport, *next;1036 struct efct_lio_vport *lio_vport = NULL;1037 struct efct_lio_tpg *tpg = NULL;1038 unsigned long flags = 0;1039 1040 efct = node->efc->base;1041 spin_lock_irqsave(&efct->tgt_efct.efct_lio_lock, flags);1042 list_for_each_entry_safe(vport, next, &efct->tgt_efct.vport_list,1043 list_entry) {1044 lio_vport = vport->lio_vport;1045 if (wwpn && lio_vport && lio_vport->npiv_wwpn == wwpn) {1046 efc_log_debug(efct, "found tpg on vport\n");1047 tpg = lio_vport->tpg;1048 break;1049 }1050 }1051 spin_unlock_irqrestore(&efct->tgt_efct.efct_lio_lock, flags);1052 return tpg;1053}1054 1055static void1056_efct_tgt_node_free(struct kref *arg)1057{1058 struct efct_node *tgt_node = container_of(arg, struct efct_node, ref);1059 struct efc_node *node = tgt_node->node;1060 1061 efc_scsi_del_initiator_complete(node->efc, node);1062 kfree(tgt_node);1063}1064 1065static int efct_session_cb(struct se_portal_group *se_tpg,1066 struct se_session *se_sess, void *private)1067{1068 struct efc_node *node = private;1069 struct efct_node *tgt_node;1070 struct efct *efct = node->efc->base;1071 1072 tgt_node = kzalloc(sizeof(*tgt_node), GFP_KERNEL);1073 if (!tgt_node)1074 return -ENOMEM;1075 1076 kref_init(&tgt_node->ref);1077 tgt_node->release = _efct_tgt_node_free;1078 1079 tgt_node->session = se_sess;1080 node->tgt_node = tgt_node;1081 tgt_node->efct = efct;1082 1083 tgt_node->node = node;1084 1085 tgt_node->node_fc_id = node->rnode.fc_id;1086 tgt_node->port_fc_id = node->nport->fc_id;1087 tgt_node->vpi = node->nport->indicator;1088 tgt_node->rpi = node->rnode.indicator;1089 1090 spin_lock_init(&tgt_node->active_ios_lock);1091 INIT_LIST_HEAD(&tgt_node->active_ios);1092 1093 return 0;1094}1095 1096int efct_scsi_tgt_new_device(struct efct *efct)1097{1098 u32 total_ios;1099 1100 /* Get the max settings */1101 efct->tgt_efct.max_sge = sli_get_max_sge(&efct->hw.sli);1102 efct->tgt_efct.max_sgl = sli_get_max_sgl(&efct->hw.sli);1103 1104 /* initialize IO watermark fields */1105 atomic_set(&efct->tgt_efct.ios_in_use, 0);1106 total_ios = efct->hw.config.n_io;1107 efc_log_debug(efct, "total_ios=%d\n", total_ios);1108 efct->tgt_efct.watermark_min =1109 (total_ios * EFCT_WATERMARK_LOW_PCT) / 100;1110 efct->tgt_efct.watermark_max =1111 (total_ios * EFCT_WATERMARK_HIGH_PCT) / 100;1112 atomic_set(&efct->tgt_efct.io_high_watermark,1113 efct->tgt_efct.watermark_max);1114 atomic_set(&efct->tgt_efct.watermark_hit, 0);1115 atomic_set(&efct->tgt_efct.initiator_count, 0);1116 1117 lio_wq = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM,1118 "efct_lio_worker");1119 if (!lio_wq) {1120 efc_log_err(efct, "workqueue create failed\n");1121 return -EIO;1122 }1123 1124 spin_lock_init(&efct->tgt_efct.efct_lio_lock);1125 INIT_LIST_HEAD(&efct->tgt_efct.vport_list);1126 1127 return 0;1128}1129 1130int efct_scsi_tgt_del_device(struct efct *efct)1131{1132 flush_workqueue(lio_wq);1133 1134 return 0;1135}1136 1137int1138efct_scsi_tgt_new_nport(struct efc *efc, struct efc_nport *nport)1139{1140 struct efct *efct = nport->efc->base;1141 1142 efc_log_debug(efct, "New SPORT: %s bound to %s\n", nport->display_name,1143 efct->tgt_efct.lio_nport->wwpn_str);1144 1145 return 0;1146}1147 1148void1149efct_scsi_tgt_del_nport(struct efc *efc, struct efc_nport *nport)1150{1151 efc_log_debug(efc, "Del SPORT: %s\n", nport->display_name);1152}1153 1154static void efct_lio_setup_session(struct work_struct *work)1155{1156 struct efct_lio_wq_data *wq_data =1157 container_of(work, struct efct_lio_wq_data, work);1158 struct efct *efct = wq_data->efct;1159 struct efc_node *node = wq_data->ptr;1160 char wwpn[WWN_NAME_LEN];1161 struct efct_lio_tpg *tpg;1162 struct efct_node *tgt_node;1163 struct se_portal_group *se_tpg;1164 struct se_session *se_sess;1165 int watermark;1166 int ini_count;1167 u64 id;1168 1169 /* Check to see if it's belongs to vport,1170 * if not get physical port1171 */1172 tpg = efct_get_vport_tpg(node);1173 if (tpg) {1174 se_tpg = &tpg->tpg;1175 } else if (efct->tgt_efct.tpg) {1176 tpg = efct->tgt_efct.tpg;1177 se_tpg = &tpg->tpg;1178 } else {1179 efc_log_err(efct, "failed to init session\n");1180 return;1181 }1182 1183 /*1184 * Format the FCP Initiator port_name into colon1185 * separated values to match the format by our explicit1186 * ConfigFS NodeACLs.1187 */1188 efct_format_wwn(wwpn, sizeof(wwpn), "", efc_node_get_wwpn(node));1189 1190 se_sess = target_setup_session(se_tpg, 0, 0, TARGET_PROT_NORMAL, wwpn,1191 node, efct_session_cb);1192 if (IS_ERR(se_sess)) {1193 efc_log_err(efct, "failed to setup session\n");1194 kfree(wq_data);1195 efc_scsi_sess_reg_complete(node, -EIO);1196 return;1197 }1198 1199 tgt_node = node->tgt_node;1200 id = (u64) tgt_node->port_fc_id << 32 | tgt_node->node_fc_id;1201 1202 efc_log_debug(efct, "new initiator sess=%p node=%p id: %llx\n",1203 se_sess, node, id);1204 1205 if (xa_err(xa_store(&efct->lookup, id, tgt_node, GFP_KERNEL)))1206 efc_log_err(efct, "Node lookup store failed\n");1207 1208 efc_scsi_sess_reg_complete(node, 0);1209 1210 /* update IO watermark: increment initiator count */1211 ini_count = atomic_add_return(1, &efct->tgt_efct.initiator_count);1212 watermark = efct->tgt_efct.watermark_max -1213 ini_count * EFCT_IO_WATERMARK_PER_INITIATOR;1214 watermark = (efct->tgt_efct.watermark_min > watermark) ?1215 efct->tgt_efct.watermark_min : watermark;1216 atomic_set(&efct->tgt_efct.io_high_watermark, watermark);1217 1218 kfree(wq_data);1219}1220 1221int efct_scsi_new_initiator(struct efc *efc, struct efc_node *node)1222{1223 struct efct *efct = node->efc->base;1224 struct efct_lio_wq_data *wq_data;1225 1226 /*1227 * Since LIO only supports initiator validation at thread level,1228 * we are open minded and accept all callers.1229 */1230 wq_data = kzalloc(sizeof(*wq_data), GFP_ATOMIC);1231 if (!wq_data)1232 return -ENOMEM;1233 1234 wq_data->ptr = node;1235 wq_data->efct = efct;1236 INIT_WORK(&wq_data->work, efct_lio_setup_session);1237 queue_work(lio_wq, &wq_data->work);1238 return EFC_SCSI_CALL_ASYNC;1239}1240 1241static void efct_lio_remove_session(struct work_struct *work)1242{1243 struct efct_lio_wq_data *wq_data =1244 container_of(work, struct efct_lio_wq_data, work);1245 struct efct *efct = wq_data->efct;1246 struct efc_node *node = wq_data->ptr;1247 struct efct_node *tgt_node;1248 struct se_session *se_sess;1249 1250 tgt_node = node->tgt_node;1251 if (!tgt_node) {1252 /* base driver has sent back-to-back requests1253 * to unreg session with no intervening1254 * register1255 */1256 efc_log_err(efct, "unreg session for NULL session\n");1257 efc_scsi_del_initiator_complete(node->efc, node);1258 return;1259 }1260 1261 se_sess = tgt_node->session;1262 efc_log_debug(efct, "unreg session se_sess=%p node=%p\n",1263 se_sess, node);1264 1265 /* first flag all session commands to complete */1266 target_stop_session(se_sess);1267 1268 /* now wait for session commands to complete */1269 target_wait_for_sess_cmds(se_sess);1270 target_remove_session(se_sess);1271 tgt_node->session = NULL;1272 node->tgt_node = NULL;1273 kref_put(&tgt_node->ref, tgt_node->release);1274 1275 kfree(wq_data);1276}1277 1278int efct_scsi_del_initiator(struct efc *efc, struct efc_node *node, int reason)1279{1280 struct efct *efct = node->efc->base;1281 struct efct_node *tgt_node = node->tgt_node;1282 struct efct_lio_wq_data *wq_data;1283 int watermark;1284 int ini_count;1285 u64 id;1286 1287 if (reason == EFCT_SCSI_INITIATOR_MISSING)1288 return EFC_SCSI_CALL_COMPLETE;1289 1290 if (!tgt_node) {1291 efc_log_err(efct, "tgt_node is NULL\n");1292 return -EIO;1293 }1294 1295 wq_data = kzalloc(sizeof(*wq_data), GFP_ATOMIC);1296 if (!wq_data)1297 return -ENOMEM;1298 1299 id = (u64) tgt_node->port_fc_id << 32 | tgt_node->node_fc_id;1300 xa_erase(&efct->lookup, id);1301 1302 wq_data->ptr = node;1303 wq_data->efct = efct;1304 INIT_WORK(&wq_data->work, efct_lio_remove_session);1305 queue_work(lio_wq, &wq_data->work);1306 1307 /*1308 * update IO watermark: decrement initiator count1309 */1310 ini_count = atomic_sub_return(1, &efct->tgt_efct.initiator_count);1311 1312 watermark = efct->tgt_efct.watermark_max -1313 ini_count * EFCT_IO_WATERMARK_PER_INITIATOR;1314 watermark = (efct->tgt_efct.watermark_min > watermark) ?1315 efct->tgt_efct.watermark_min : watermark;1316 atomic_set(&efct->tgt_efct.io_high_watermark, watermark);1317 1318 return EFC_SCSI_CALL_ASYNC;1319}1320 1321void efct_scsi_recv_cmd(struct efct_io *io, uint64_t lun, u8 *cdb,1322 u32 cdb_len, u32 flags)1323{1324 struct efct_scsi_tgt_io *ocp = &io->tgt_io;1325 struct se_cmd *se_cmd = &io->tgt_io.cmd;1326 struct efct *efct = io->efct;1327 char *ddir;1328 struct efct_node *tgt_node;1329 struct se_session *se_sess;1330 int rc = 0;1331 1332 memset(ocp, 0, sizeof(struct efct_scsi_tgt_io));1333 efct_set_lio_io_state(io, EFCT_LIO_STATE_SCSI_RECV_CMD);1334 atomic_add_return(1, &efct->tgt_efct.ios_in_use);1335 1336 /* set target timeout */1337 io->timeout = efct->target_io_timer_sec;1338 1339 if (flags & EFCT_SCSI_CMD_SIMPLE)1340 ocp->task_attr = TCM_SIMPLE_TAG;1341 else if (flags & EFCT_SCSI_CMD_HEAD_OF_QUEUE)1342 ocp->task_attr = TCM_HEAD_TAG;1343 else if (flags & EFCT_SCSI_CMD_ORDERED)1344 ocp->task_attr = TCM_ORDERED_TAG;1345 else if (flags & EFCT_SCSI_CMD_ACA)1346 ocp->task_attr = TCM_ACA_TAG;1347 1348 switch (flags & (EFCT_SCSI_CMD_DIR_IN | EFCT_SCSI_CMD_DIR_OUT)) {1349 case EFCT_SCSI_CMD_DIR_IN:1350 ddir = "FROM_INITIATOR";1351 ocp->ddir = DMA_TO_DEVICE;1352 break;1353 case EFCT_SCSI_CMD_DIR_OUT:1354 ddir = "TO_INITIATOR";1355 ocp->ddir = DMA_FROM_DEVICE;1356 break;1357 case EFCT_SCSI_CMD_DIR_IN | EFCT_SCSI_CMD_DIR_OUT:1358 ddir = "BIDIR";1359 ocp->ddir = DMA_BIDIRECTIONAL;1360 break;1361 default:1362 ddir = "NONE";1363 ocp->ddir = DMA_NONE;1364 break;1365 }1366 1367 ocp->lun = lun;1368 efct_lio_io_printf(io, "new cmd=0x%x ddir=%s dl=%u\n",1369 cdb[0], ddir, io->exp_xfer_len);1370 1371 tgt_node = io->node;1372 se_sess = tgt_node->session;1373 if (!se_sess) {1374 efc_log_err(efct, "No session found to submit IO se_cmd: %p\n",1375 &ocp->cmd);1376 efct_scsi_io_free(io);1377 return;1378 }1379 1380 efct_set_lio_io_state(io, EFCT_LIO_STATE_TGT_SUBMIT_CMD);1381 rc = target_init_cmd(se_cmd, se_sess, &io->tgt_io.sense_buffer[0],1382 ocp->lun, io->exp_xfer_len, ocp->task_attr,1383 ocp->ddir, TARGET_SCF_ACK_KREF);1384 if (rc) {1385 efc_log_err(efct, "failed to init cmd se_cmd: %p\n", se_cmd);1386 efct_scsi_io_free(io);1387 return;1388 }1389 1390 if (target_submit_prep(se_cmd, cdb, NULL, 0, NULL, 0,1391 NULL, 0, GFP_ATOMIC))1392 return;1393 1394 target_submit(se_cmd);1395}1396 1397int1398efct_scsi_recv_tmf(struct efct_io *tmfio, u32 lun, enum efct_scsi_tmf_cmd cmd,1399 struct efct_io *io_to_abort, u32 flags)1400{1401 unsigned char tmr_func;1402 struct efct *efct = tmfio->efct;1403 struct efct_scsi_tgt_io *ocp = &tmfio->tgt_io;1404 struct efct_node *tgt_node;1405 struct se_session *se_sess;1406 int rc;1407 1408 memset(ocp, 0, sizeof(struct efct_scsi_tgt_io));1409 efct_set_lio_io_state(tmfio, EFCT_LIO_STATE_SCSI_RECV_TMF);1410 atomic_add_return(1, &efct->tgt_efct.ios_in_use);1411 efct_lio_tmfio_printf(tmfio, "%s: new tmf %x lun=%u\n",1412 tmfio->display_name, cmd, lun);1413 1414 switch (cmd) {1415 case EFCT_SCSI_TMF_ABORT_TASK:1416 tmr_func = TMR_ABORT_TASK;1417 break;1418 case EFCT_SCSI_TMF_ABORT_TASK_SET:1419 tmr_func = TMR_ABORT_TASK_SET;1420 break;1421 case EFCT_SCSI_TMF_CLEAR_TASK_SET:1422 tmr_func = TMR_CLEAR_TASK_SET;1423 break;1424 case EFCT_SCSI_TMF_LOGICAL_UNIT_RESET:1425 tmr_func = TMR_LUN_RESET;1426 break;1427 case EFCT_SCSI_TMF_CLEAR_ACA:1428 tmr_func = TMR_CLEAR_ACA;1429 break;1430 case EFCT_SCSI_TMF_TARGET_RESET:1431 tmr_func = TMR_TARGET_WARM_RESET;1432 break;1433 case EFCT_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT:1434 case EFCT_SCSI_TMF_QUERY_TASK_SET:1435 default:1436 goto tmf_fail;1437 }1438 1439 tmfio->tgt_io.tmf = tmr_func;1440 tmfio->tgt_io.lun = lun;1441 tmfio->tgt_io.io_to_abort = io_to_abort;1442 1443 tgt_node = tmfio->node;1444 1445 se_sess = tgt_node->session;1446 if (!se_sess)1447 return 0;1448 1449 rc = target_submit_tmr(&ocp->cmd, se_sess, NULL, lun, ocp, tmr_func,1450 GFP_ATOMIC, tmfio->init_task_tag, TARGET_SCF_ACK_KREF);1451 1452 efct_set_lio_io_state(tmfio, EFCT_LIO_STATE_TGT_SUBMIT_TMR);1453 if (rc)1454 goto tmf_fail;1455 1456 return 0;1457 1458tmf_fail:1459 efct_scsi_send_tmf_resp(tmfio, EFCT_SCSI_TMF_FUNCTION_REJECTED,1460 NULL, efct_lio_null_tmf_done, NULL);1461 return 0;1462}1463 1464/* Start items for efct_lio_tpg_attrib_cit */1465 1466#define DEF_EFCT_TPG_ATTRIB(name) \1467 \1468static ssize_t efct_lio_tpg_attrib_##name##_show( \1469 struct config_item *item, char *page) \1470{ \1471 struct se_portal_group *se_tpg = to_tpg(item); \1472 struct efct_lio_tpg *tpg = container_of(se_tpg, \1473 struct efct_lio_tpg, tpg); \1474 \1475 return sprintf(page, "%u\n", tpg->tpg_attrib.name); \1476} \1477 \1478static ssize_t efct_lio_tpg_attrib_##name##_store( \1479 struct config_item *item, const char *page, size_t count) \1480{ \1481 struct se_portal_group *se_tpg = to_tpg(item); \1482 struct efct_lio_tpg *tpg = container_of(se_tpg, \1483 struct efct_lio_tpg, tpg); \1484 struct efct_lio_tpg_attrib *a = &tpg->tpg_attrib; \1485 unsigned long val; \1486 int ret; \1487 \1488 ret = kstrtoul(page, 0, &val); \1489 if (ret < 0) { \1490 pr_err("kstrtoul() failed with ret: %d\n", ret); \1491 return ret; \1492 } \1493 \1494 if (val != 0 && val != 1) { \1495 pr_err("Illegal boolean value %lu\n", val); \1496 return -EINVAL; \1497 } \1498 \1499 a->name = val; \1500 \1501 return count; \1502} \1503CONFIGFS_ATTR(efct_lio_tpg_attrib_, name)1504 1505DEF_EFCT_TPG_ATTRIB(generate_node_acls);1506DEF_EFCT_TPG_ATTRIB(cache_dynamic_acls);1507DEF_EFCT_TPG_ATTRIB(demo_mode_write_protect);1508DEF_EFCT_TPG_ATTRIB(prod_mode_write_protect);1509DEF_EFCT_TPG_ATTRIB(demo_mode_login_only);1510DEF_EFCT_TPG_ATTRIB(session_deletion_wait);1511 1512static struct configfs_attribute *efct_lio_tpg_attrib_attrs[] = {1513 &efct_lio_tpg_attrib_attr_generate_node_acls,1514 &efct_lio_tpg_attrib_attr_cache_dynamic_acls,1515 &efct_lio_tpg_attrib_attr_demo_mode_write_protect,1516 &efct_lio_tpg_attrib_attr_prod_mode_write_protect,1517 &efct_lio_tpg_attrib_attr_demo_mode_login_only,1518 &efct_lio_tpg_attrib_attr_session_deletion_wait,1519 NULL,1520};1521 1522#define DEF_EFCT_NPIV_TPG_ATTRIB(name) \1523 \1524static ssize_t efct_lio_npiv_tpg_attrib_##name##_show( \1525 struct config_item *item, char *page) \1526{ \1527 struct se_portal_group *se_tpg = to_tpg(item); \1528 struct efct_lio_tpg *tpg = container_of(se_tpg, \1529 struct efct_lio_tpg, tpg); \1530 \1531 return sprintf(page, "%u\n", tpg->tpg_attrib.name); \1532} \1533 \1534static ssize_t efct_lio_npiv_tpg_attrib_##name##_store( \1535 struct config_item *item, const char *page, size_t count) \1536{ \1537 struct se_portal_group *se_tpg = to_tpg(item); \1538 struct efct_lio_tpg *tpg = container_of(se_tpg, \1539 struct efct_lio_tpg, tpg); \1540 struct efct_lio_tpg_attrib *a = &tpg->tpg_attrib; \1541 unsigned long val; \1542 int ret; \1543 \1544 ret = kstrtoul(page, 0, &val); \1545 if (ret < 0) { \1546 pr_err("kstrtoul() failed with ret: %d\n", ret); \1547 return ret; \1548 } \1549 \1550 if (val != 0 && val != 1) { \1551 pr_err("Illegal boolean value %lu\n", val); \1552 return -EINVAL; \1553 } \1554 \1555 a->name = val; \1556 \1557 return count; \1558} \1559CONFIGFS_ATTR(efct_lio_npiv_tpg_attrib_, name)1560 1561DEF_EFCT_NPIV_TPG_ATTRIB(generate_node_acls);1562DEF_EFCT_NPIV_TPG_ATTRIB(cache_dynamic_acls);1563DEF_EFCT_NPIV_TPG_ATTRIB(demo_mode_write_protect);1564DEF_EFCT_NPIV_TPG_ATTRIB(prod_mode_write_protect);1565DEF_EFCT_NPIV_TPG_ATTRIB(demo_mode_login_only);1566DEF_EFCT_NPIV_TPG_ATTRIB(session_deletion_wait);1567 1568static struct configfs_attribute *efct_lio_npiv_tpg_attrib_attrs[] = {1569 &efct_lio_npiv_tpg_attrib_attr_generate_node_acls,1570 &efct_lio_npiv_tpg_attrib_attr_cache_dynamic_acls,1571 &efct_lio_npiv_tpg_attrib_attr_demo_mode_write_protect,1572 &efct_lio_npiv_tpg_attrib_attr_prod_mode_write_protect,1573 &efct_lio_npiv_tpg_attrib_attr_demo_mode_login_only,1574 &efct_lio_npiv_tpg_attrib_attr_session_deletion_wait,1575 NULL,1576};1577 1578CONFIGFS_ATTR(efct_lio_tpg_, enable);1579static struct configfs_attribute *efct_lio_tpg_attrs[] = {1580 &efct_lio_tpg_attr_enable, NULL };1581CONFIGFS_ATTR(efct_lio_npiv_tpg_, enable);1582static struct configfs_attribute *efct_lio_npiv_tpg_attrs[] = {1583 &efct_lio_npiv_tpg_attr_enable, NULL };1584 1585static const struct target_core_fabric_ops efct_lio_ops = {1586 .module = THIS_MODULE,1587 .fabric_name = "efct",1588 .node_acl_size = sizeof(struct efct_lio_nacl),1589 .max_data_sg_nents = 65535,1590 .tpg_get_wwn = efct_lio_get_fabric_wwn,1591 .tpg_get_tag = efct_lio_get_tag,1592 .fabric_init_nodeacl = efct_lio_init_nodeacl,1593 .tpg_check_demo_mode = efct_lio_check_demo_mode,1594 .tpg_check_demo_mode_cache = efct_lio_check_demo_mode_cache,1595 .tpg_check_demo_mode_write_protect = efct_lio_check_demo_write_protect,1596 .tpg_check_prod_mode_write_protect = efct_lio_check_prod_write_protect,1597 .check_stop_free = efct_lio_check_stop_free,1598 .aborted_task = efct_lio_aborted_task,1599 .release_cmd = efct_lio_release_cmd,1600 .close_session = efct_lio_close_session,1601 .write_pending = efct_lio_write_pending,1602 .get_cmd_state = efct_lio_get_cmd_state,1603 .queue_data_in = efct_lio_queue_data_in,1604 .queue_status = efct_lio_queue_status,1605 .queue_tm_rsp = efct_lio_queue_tm_rsp,1606 .fabric_make_wwn = efct_lio_make_nport,1607 .fabric_drop_wwn = efct_lio_drop_nport,1608 .fabric_make_tpg = efct_lio_make_tpg,1609 .fabric_drop_tpg = efct_lio_drop_tpg,1610 .tpg_check_demo_mode_login_only = efct_lio_check_demo_mode_login_only,1611 .tpg_check_prot_fabric_only = NULL,1612 .sess_get_initiator_sid = NULL,1613 .tfc_tpg_base_attrs = efct_lio_tpg_attrs,1614 .tfc_tpg_attrib_attrs = efct_lio_tpg_attrib_attrs,1615 .default_submit_type = TARGET_DIRECT_SUBMIT,1616 .direct_submit_supp = 1,1617};1618 1619static const struct target_core_fabric_ops efct_lio_npiv_ops = {1620 .module = THIS_MODULE,1621 .fabric_name = "efct_npiv",1622 .node_acl_size = sizeof(struct efct_lio_nacl),1623 .max_data_sg_nents = 65535,1624 .tpg_get_wwn = efct_lio_get_npiv_fabric_wwn,1625 .tpg_get_tag = efct_lio_get_npiv_tag,1626 .fabric_init_nodeacl = efct_lio_init_nodeacl,1627 .tpg_check_demo_mode = efct_lio_check_demo_mode,1628 .tpg_check_demo_mode_cache = efct_lio_check_demo_mode_cache,1629 .tpg_check_demo_mode_write_protect =1630 efct_lio_npiv_check_demo_write_protect,1631 .tpg_check_prod_mode_write_protect =1632 efct_lio_npiv_check_prod_write_protect,1633 .check_stop_free = efct_lio_check_stop_free,1634 .aborted_task = efct_lio_aborted_task,1635 .release_cmd = efct_lio_release_cmd,1636 .close_session = efct_lio_close_session,1637 .write_pending = efct_lio_write_pending,1638 .get_cmd_state = efct_lio_get_cmd_state,1639 .queue_data_in = efct_lio_queue_data_in,1640 .queue_status = efct_lio_queue_status,1641 .queue_tm_rsp = efct_lio_queue_tm_rsp,1642 .fabric_make_wwn = efct_lio_npiv_make_nport,1643 .fabric_drop_wwn = efct_lio_npiv_drop_nport,1644 .fabric_make_tpg = efct_lio_npiv_make_tpg,1645 .fabric_drop_tpg = efct_lio_npiv_drop_tpg,1646 .tpg_check_demo_mode_login_only =1647 efct_lio_npiv_check_demo_mode_login_only,1648 .tpg_check_prot_fabric_only = NULL,1649 .sess_get_initiator_sid = NULL,1650 .tfc_tpg_base_attrs = efct_lio_npiv_tpg_attrs,1651 .tfc_tpg_attrib_attrs = efct_lio_npiv_tpg_attrib_attrs,1652 1653 .default_submit_type = TARGET_DIRECT_SUBMIT,1654 .direct_submit_supp = 1,1655};1656 1657int efct_scsi_tgt_driver_init(void)1658{1659 int rc;1660 1661 /* Register the top level struct config_item_type with TCM core */1662 rc = target_register_template(&efct_lio_ops);1663 if (rc < 0) {1664 pr_err("target_fabric_configfs_register failed with %d\n", rc);1665 return rc;1666 }1667 rc = target_register_template(&efct_lio_npiv_ops);1668 if (rc < 0) {1669 pr_err("target_fabric_configfs_register failed with %d\n", rc);1670 target_unregister_template(&efct_lio_ops);1671 return rc;1672 }1673 return 0;1674}1675 1676int efct_scsi_tgt_driver_exit(void)1677{1678 target_unregister_template(&efct_lio_ops);1679 target_unregister_template(&efct_lio_npiv_ops);1680 return 0;1681}1682