summaryrefslogtreecommitdiffstats
path: root/drivers/target/tcm_fc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target/tcm_fc')
-rw-r--r--drivers/target/tcm_fc/tcm_fc.h9
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c164
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c17
-rw-r--r--drivers/target/tcm_fc/tfc_io.c12
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c33
5 files changed, 71 insertions, 164 deletions
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h
index e05c55100ec..c5eb3c33c3d 100644
--- a/drivers/target/tcm_fc/tcm_fc.h
+++ b/drivers/target/tcm_fc/tcm_fc.h
@@ -17,7 +17,7 @@
#ifndef __TCM_FC_H__
#define __TCM_FC_H__
-#define FT_VERSION "0.3"
+#define FT_VERSION "0.4"
#define FT_NAMELEN 32 /* length of ASCII WWPNs including pad */
#define FT_TPG_NAMELEN 32 /* max length of TPG name */
@@ -113,17 +113,16 @@ struct ft_lport_acl {
* Commands
*/
struct ft_cmd {
- u32 lun; /* LUN from request */
struct ft_sess *sess; /* session held for cmd */
struct fc_seq *seq; /* sequence in exchange mgr */
struct se_cmd se_cmd; /* Local TCM I/O descriptor */
struct fc_frame *req_frame;
- unsigned char *cdb; /* pointer to CDB inside frame */
u32 write_data_len; /* data received on writes */
struct work_struct work;
/* Local sense buffer */
unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER];
u32 was_ddp_setup:1; /* Set only if ddp is setup */
+ u32 aborted:1; /* Set if aborted by reset or timeout */
struct scatterlist *sg; /* Set only if DDP is setup */
u32 sg_cnt; /* No. of item in scatterlist */
};
@@ -143,11 +142,8 @@ extern struct target_fabric_configfs *ft_configfs;
void ft_sess_put(struct ft_sess *);
int ft_sess_shutdown(struct se_session *);
void ft_sess_close(struct se_session *);
-void ft_sess_stop(struct se_session *, int, int);
-int ft_sess_logged_in(struct se_session *);
u32 ft_sess_get_index(struct se_session *);
u32 ft_sess_get_port_name(struct se_session *, unsigned char *, u32);
-void ft_sess_set_erl0(struct se_session *);
void ft_lport_add(struct fc_lport *, void *);
void ft_lport_del(struct fc_lport *, void *);
@@ -165,7 +161,6 @@ int ft_write_pending_status(struct se_cmd *);
u32 ft_get_task_tag(struct se_cmd *);
int ft_get_cmd_state(struct se_cmd *);
int ft_queue_tm_resp(struct se_cmd *);
-int ft_is_state_remove(struct se_cmd *);
/*
* other internal functions.
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index addc18f727e..a375f257aab 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -59,9 +59,6 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
se_cmd = &cmd->se_cmd;
pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n",
caller, cmd, cmd->sess, cmd->seq, se_cmd);
- pr_debug("%s: cmd %p cdb %p\n",
- caller, cmd, cmd->cdb);
- pr_debug("%s: cmd %p lun %d\n", caller, cmd, cmd->lun);
pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n",
caller, cmd, se_cmd->t_data_nents,
@@ -81,8 +78,6 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid,
sp->id, ep->esb_stat);
}
- print_hex_dump(KERN_INFO, "ft_dump_cmd ", DUMP_PREFIX_NONE,
- 16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0);
}
static void ft_free_cmd(struct ft_cmd *cmd)
@@ -126,6 +121,8 @@ int ft_queue_status(struct se_cmd *se_cmd)
struct fc_exch *ep;
size_t len;
+ if (cmd->aborted)
+ return 0;
ft_dump_cmd(cmd, __func__);
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
@@ -192,6 +189,8 @@ int ft_write_pending(struct se_cmd *se_cmd)
ft_dump_cmd(cmd, __func__);
+ if (cmd->aborted)
+ return 0;
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
fp = fc_frame_alloc(lport, sizeof(*txrdy));
@@ -249,11 +248,6 @@ int ft_get_cmd_state(struct se_cmd *se_cmd)
return 0;
}
-int ft_is_state_remove(struct se_cmd *se_cmd)
-{
- return 0; /* XXX TBD */
-}
-
/*
* FC sequence response handler for follow-on sequences (data) and aborts.
*/
@@ -262,10 +256,10 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
struct ft_cmd *cmd = arg;
struct fc_frame_header *fh;
- if (IS_ERR(fp)) {
+ if (unlikely(IS_ERR(fp))) {
/* XXX need to find cmd if queued */
cmd->seq = NULL;
- transport_generic_free_cmd(&cmd->se_cmd, 0);
+ cmd->aborted = true;
return;
}
@@ -325,10 +319,12 @@ static void ft_send_resp_status(struct fc_lport *lport,
fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0);
sp = fr_seq(fp);
- if (sp)
+ if (sp) {
lport->tt.seq_send(lport, sp, fp);
- else
+ lport->tt.exch_done(sp);
+ } else {
lport->tt.frame_send(lport, fp);
+ }
}
/*
@@ -358,16 +354,10 @@ static void ft_send_resp_code_and_free(struct ft_cmd *cmd,
*/
static void ft_send_tm(struct ft_cmd *cmd)
{
- struct se_tmr_req *tmr;
struct fcp_cmnd *fcp;
- struct ft_sess *sess;
+ int rc;
u8 tm_func;
- transport_init_se_cmd(&cmd->se_cmd, &ft_configfs->tf_ops,
- cmd->sess->se_sess, 0, DMA_NONE, 0,
- &cmd->ft_sense_buffer[0]);
- target_get_sess_cmd(cmd->sess->se_sess, &cmd->se_cmd, false);
-
fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
switch (fcp->fc_tm_flags) {
@@ -396,44 +386,12 @@ static void ft_send_tm(struct ft_cmd *cmd)
return;
}
- pr_debug("alloc tm cmd fn %d\n", tm_func);
- tmr = core_tmr_alloc_req(&cmd->se_cmd, cmd, tm_func, GFP_KERNEL);
- if (!tmr) {
- pr_debug("alloc failed\n");
+ /* FIXME: Add referenced task tag for ABORT_TASK */
+ rc = target_submit_tmr(&cmd->se_cmd, cmd->sess->se_sess,
+ &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
+ cmd, tm_func, GFP_KERNEL, 0, 0);
+ if (rc < 0)
ft_send_resp_code_and_free(cmd, FCP_TMF_FAILED);
- return;
- }
- cmd->se_cmd.se_tmr_req = tmr;
-
- switch (fcp->fc_tm_flags) {
- case FCP_TMF_LUN_RESET:
- cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
- if (transport_lookup_tmr_lun(&cmd->se_cmd, cmd->lun) < 0) {
- /*
- * Make sure to clean up newly allocated TMR request
- * since "unable to handle TMR request because failed
- * to get to LUN"
- */
- pr_debug("Failed to get LUN for TMR func %d, "
- "se_cmd %p, unpacked_lun %d\n",
- tm_func, &cmd->se_cmd, cmd->lun);
- ft_dump_cmd(cmd, __func__);
- sess = cmd->sess;
- transport_send_check_condition_and_sense(&cmd->se_cmd,
- cmd->se_cmd.scsi_sense_reason, 0);
- ft_sess_put(sess);
- return;
- }
- break;
- case FCP_TMF_TGT_RESET:
- case FCP_TMF_CLR_TASK_SET:
- case FCP_TMF_ABT_TASK_SET:
- case FCP_TMF_CLR_ACA:
- break;
- default:
- return;
- }
- transport_generic_handle_tmr(&cmd->se_cmd);
}
/*
@@ -445,6 +403,8 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd)
struct se_tmr_req *tmr = se_cmd->se_tmr_req;
enum fcp_resp_rsp_codes code;
+ if (cmd->aborted)
+ return 0;
switch (tmr->response) {
case TMR_FUNCTION_COMPLETE:
code = FCP_TMF_CMPL;
@@ -538,9 +498,7 @@ static void ft_send_work(struct work_struct *work)
struct fc_frame_header *fh = fc_frame_header_get(cmd->req_frame);
struct fcp_cmnd *fcp;
int data_dir = 0;
- u32 data_len;
int task_attr;
- int ret;
fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
if (!fcp)
@@ -549,47 +507,6 @@ static void ft_send_work(struct work_struct *work)
if (fcp->fc_flags & FCP_CFL_LEN_MASK)
goto err; /* not handling longer CDBs yet */
- if (fcp->fc_tm_flags) {
- task_attr = FCP_PTA_SIMPLE;
- data_dir = DMA_NONE;
- data_len = 0;
- } else {
- switch (fcp->fc_flags & (FCP_CFL_RDDATA | FCP_CFL_WRDATA)) {
- case 0:
- data_dir = DMA_NONE;
- break;
- case FCP_CFL_RDDATA:
- data_dir = DMA_FROM_DEVICE;
- break;
- case FCP_CFL_WRDATA:
- data_dir = DMA_TO_DEVICE;
- break;
- case FCP_CFL_WRDATA | FCP_CFL_RDDATA:
- goto err; /* TBD not supported by tcm_fc yet */
- }
- /*
- * Locate the SAM Task Attr from fc_pri_ta
- */
- switch (fcp->fc_pri_ta & FCP_PTA_MASK) {
- case FCP_PTA_HEADQ:
- task_attr = MSG_HEAD_TAG;
- break;
- case FCP_PTA_ORDERED:
- task_attr = MSG_ORDERED_TAG;
- break;
- case FCP_PTA_ACA:
- task_attr = MSG_ACA_TAG;
- break;
- case FCP_PTA_SIMPLE: /* Fallthrough */
- default:
- task_attr = MSG_SIMPLE_TAG;
- }
-
-
- task_attr = fcp->fc_pri_ta & FCP_PTA_MASK;
- data_len = ntohl(fcp->fc_dl);
- cmd->cdb = fcp->fc_cdb;
- }
/*
* Check for FCP task management flags
*/
@@ -597,20 +514,47 @@ static void ft_send_work(struct work_struct *work)
ft_send_tm(cmd);
return;
}
+
+ switch (fcp->fc_flags & (FCP_CFL_RDDATA | FCP_CFL_WRDATA)) {
+ case 0:
+ data_dir = DMA_NONE;
+ break;
+ case FCP_CFL_RDDATA:
+ data_dir = DMA_FROM_DEVICE;
+ break;
+ case FCP_CFL_WRDATA:
+ data_dir = DMA_TO_DEVICE;
+ break;
+ case FCP_CFL_WRDATA | FCP_CFL_RDDATA:
+ goto err; /* TBD not supported by tcm_fc yet */
+ }
+ /*
+ * Locate the SAM Task Attr from fc_pri_ta
+ */
+ switch (fcp->fc_pri_ta & FCP_PTA_MASK) {
+ case FCP_PTA_HEADQ:
+ task_attr = MSG_HEAD_TAG;
+ break;
+ case FCP_PTA_ORDERED:
+ task_attr = MSG_ORDERED_TAG;
+ break;
+ case FCP_PTA_ACA:
+ task_attr = MSG_ACA_TAG;
+ break;
+ case FCP_PTA_SIMPLE: /* Fallthrough */
+ default:
+ task_attr = MSG_SIMPLE_TAG;
+ }
+
fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
- cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
/*
* Use a single se_cmd->cmd_kref as we expect to release se_cmd
* directly from ft_check_stop_free callback in response path.
*/
- ret = target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
- &cmd->ft_sense_buffer[0], cmd->lun, data_len,
- task_attr, data_dir, 0);
- pr_debug("r_ctl %x alloc target_submit_cmd %d\n", fh->fh_r_ctl, ret);
- if (ret < 0) {
- ft_dump_cmd(cmd, __func__);
- return;
- }
+ target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
+ &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
+ ntohl(fcp->fc_dl), task_attr, data_dir, 0);
+ pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
return;
err:
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 73852fbc857..2948dc94461 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -300,6 +300,7 @@ static struct se_portal_group *ft_add_tpg(
{
struct ft_lport_acl *lacl;
struct ft_tpg *tpg;
+ struct workqueue_struct *wq;
unsigned long index;
int ret;
@@ -321,18 +322,20 @@ static struct se_portal_group *ft_add_tpg(
tpg->lport_acl = lacl;
INIT_LIST_HEAD(&tpg->lun_list);
- ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
- tpg, TRANSPORT_TPG_TYPE_NORMAL);
- if (ret < 0) {
+ wq = alloc_workqueue("tcm_fc", 0, 1);
+ if (!wq) {
kfree(tpg);
return NULL;
}
- tpg->workqueue = alloc_workqueue("tcm_fc", 0, 1);
- if (!tpg->workqueue) {
+ ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
+ tpg, TRANSPORT_TPG_TYPE_NORMAL);
+ if (ret < 0) {
+ destroy_workqueue(wq);
kfree(tpg);
return NULL;
}
+ tpg->workqueue = wq;
mutex_lock(&ft_lport_lock);
list_add_tail(&tpg->list, &lacl->tpg_list);
@@ -529,9 +532,6 @@ static struct target_core_fabric_ops ft_fabric_ops = {
.release_cmd = ft_release_cmd,
.shutdown_session = ft_sess_shutdown,
.close_session = ft_sess_close,
- .stop_session = ft_sess_stop,
- .fall_back_to_erl0 = ft_sess_set_erl0,
- .sess_logged_in = ft_sess_logged_in,
.sess_get_index = ft_sess_get_index,
.sess_get_initiator_sid = NULL,
.write_pending = ft_write_pending,
@@ -544,7 +544,6 @@ static struct target_core_fabric_ops ft_fabric_ops = {
.queue_tm_rsp = ft_queue_tm_resp,
.get_fabric_sense_len = ft_get_fabric_sense_len,
.set_fabric_sense_len = ft_set_fabric_sense_len,
- .is_state_remove = ft_is_state_remove,
/*
* Setup function pointers for generic logic in
* target_core_fabric_configfs.c
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index d8cabc21036..dc7c0db26e2 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -81,6 +81,8 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
void *from;
void *to = NULL;
+ if (cmd->aborted)
+ return 0;
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
cmd->seq = lport->tt.seq_start_next(cmd->seq);
@@ -146,14 +148,13 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
PAGE_SIZE << compound_order(page);
} else {
BUG_ON(!page);
- from = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
- KM_SOFTIRQ0);
+ from = kmap_atomic(page + (mem_off >> PAGE_SHIFT));
page_addr = from;
from += mem_off & ~PAGE_MASK;
tlen = min(tlen, (size_t)(PAGE_SIZE -
(mem_off & ~PAGE_MASK)));
memcpy(to, from, tlen);
- kunmap_atomic(page_addr, KM_SOFTIRQ0);
+ kunmap_atomic(page_addr);
to += tlen;
}
@@ -291,14 +292,13 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
tlen = min(mem_len, frame_len);
- to = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
- KM_SOFTIRQ0);
+ to = kmap_atomic(page + (mem_off >> PAGE_SHIFT));
page_addr = to;
to += mem_off & ~PAGE_MASK;
tlen = min(tlen, (size_t)(PAGE_SIZE -
(mem_off & ~PAGE_MASK)));
memcpy(to, from, tlen);
- kunmap_atomic(page_addr, KM_SOFTIRQ0);
+ kunmap_atomic(page_addr);
from += tlen;
frame_len -= tlen;
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 4c0507cf808..cb99da92006 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -86,16 +86,6 @@ static struct ft_tport *ft_tport_create(struct fc_lport *lport)
}
/*
- * Free tport via RCU.
- */
-static void ft_tport_rcu_free(struct rcu_head *rcu)
-{
- struct ft_tport *tport = container_of(rcu, struct ft_tport, rcu);
-
- kfree(tport);
-}
-
-/*
* Delete a target local port.
* Caller holds ft_lport_lock.
*/
@@ -114,7 +104,7 @@ static void ft_tport_delete(struct ft_tport *tport)
tpg->tport = NULL;
tport->tpg = NULL;
}
- call_rcu(&tport->rcu, ft_tport_rcu_free);
+ kfree_rcu(tport, rcu);
}
/*
@@ -319,11 +309,9 @@ int ft_sess_shutdown(struct se_session *se_sess)
void ft_sess_close(struct se_session *se_sess)
{
struct ft_sess *sess = se_sess->fabric_sess_ptr;
- struct fc_lport *lport;
u32 port_id;
mutex_lock(&ft_lport_lock);
- lport = sess->tport->lport;
port_id = sess->port_id;
if (port_id == -1) {
mutex_unlock(&ft_lport_lock);
@@ -338,20 +326,6 @@ void ft_sess_close(struct se_session *se_sess)
synchronize_rcu(); /* let transport deregister happen */
}
-void ft_sess_stop(struct se_session *se_sess, int sess_sleep, int conn_sleep)
-{
- struct ft_sess *sess = se_sess->fabric_sess_ptr;
-
- pr_debug("port_id %x\n", sess->port_id);
-}
-
-int ft_sess_logged_in(struct se_session *se_sess)
-{
- struct ft_sess *sess = se_sess->fabric_sess_ptr;
-
- return sess->port_id != -1;
-}
-
u32 ft_sess_get_index(struct se_session *se_sess)
{
struct ft_sess *sess = se_sess->fabric_sess_ptr;
@@ -367,11 +341,6 @@ u32 ft_sess_get_port_name(struct se_session *se_sess,
return ft_format_wwn(buf, len, sess->port_name);
}
-void ft_sess_set_erl0(struct se_session *se_sess)
-{
- /* XXX TBD called when out of memory */
-}
-
/*
* libfc ops involving sessions.
*/