Commit 9ba55cf7 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target updates from Nicholas Bellinger:
 "Here are the outstanding target pending updates for v4.7-rc1.

  The highlights this round include:

   - Allow external PR/ALUA metadata path be defined at runtime via top
     level configfs attribute (Lee)
   - Fix target session shutdown bug for ib_srpt multi-channel (hch)
   - Make TFO close_session() and shutdown_session() optional (hch)
   - Drop se_sess->sess_kref + convert tcm_qla2xxx to internal kref
     (hch)
   - Add tcm_qla2xxx endpoint attribute for basic FC jammer (Laurence)
   - Refactor iscsi-target RX/TX PDU encode/decode into common code
     (Varun)
   - Extend iscsit_transport with xmit_pdu, release_cmd, get_rx_pdu,
     validate_parameters, and get_r2t_ttt for generic ISO offload
     (Varun)
   - Initial merge of cxgb iscsi-segment offload target driver (Varun)

  The bulk of the changes are Chelsio's new driver, along with a number
  of iscsi-target common code improvements made by Varun + Co along the
  way"

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (29 commits)
  iscsi-target: Fix early sk_data_ready LOGIN_FLAGS_READY race
  cxgbit: Use type ISCSI_CXGBIT + cxgbit tpg_np attribute
  iscsi-target: Convert transport drivers to signal rdma_shutdown
  iscsi-target: Make iscsi_tpg_np driver show/store use generic code
  tcm_qla2xxx Add SCSI command jammer/discard capability
  iscsi-target: graceful disconnect on invalid mapping to iovec
  target: need_to_release is always false, remove redundant check and kfree
  target: remove sess_kref and ->shutdown_session
  iscsi-target: remove usage of ->shutdown_session
  tcm_qla2xxx: introduce a private sess_kref
  target: make close_session optional
  target: make ->shutdown_session optional
  target: remove acl_stop
  target: consolidate and fix session shutdown
  cxgbit: add files for cxgbit.ko
  iscsi-target: export symbols
  iscsi-target: call complete on conn_logout_comp
  iscsi-target: clear tx_thread_active
  iscsi-target: add new offload transport type
  iscsi-target: use conn_transport->transport_type in text rsp
  ...
parents 1cbe06c3 8f0dfb3d
tcm_qla2xxx jam_host attribute
------------------------------
There is now a new module endpoint atribute called jam_host
attribute: jam_host: boolean=0/1
This attribute and accompanying code is only included if the
Kconfig parameter TCM_QLA2XXX_DEBUG is set to Y
By default this jammer code and functionality is disabled
Use this attribute to control the discarding of SCSI commands to a
selected host.
This may be useful for testing error handling and simulating slow drain
and other fabric issues.
Setting a boolean of 1 for the jam_host attribute for a particular host
will discard the commands for that host.
Reset back to 0 to stop the jamming.
Enable host 4 to be jammed
echo 1 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host
Disable jamming on host 4
echo 0 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host
......@@ -294,8 +294,6 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += " .tpg_check_prod_mode_write_protect = " + fabric_mod_name + "_check_false,\n"
buf += " .tpg_get_inst_index = " + fabric_mod_name + "_tpg_get_inst_index,\n"
buf += " .release_cmd = " + fabric_mod_name + "_release_cmd,\n"
buf += " .shutdown_session = " + fabric_mod_name + "_shutdown_session,\n"
buf += " .close_session = " + fabric_mod_name + "_close_session,\n"
buf += " .sess_get_index = " + fabric_mod_name + "_sess_get_index,\n"
buf += " .sess_get_initiator_sid = NULL,\n"
buf += " .write_pending = " + fabric_mod_name + "_write_pending,\n"
......@@ -467,20 +465,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += "}\n\n"
bufi += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *);\n"
if re.search('shutdown_session\)\(', fo):
buf += "int " + fabric_mod_name + "_shutdown_session(struct se_session *se_sess)\n"
buf += "{\n"
buf += " return 0;\n"
buf += "}\n\n"
bufi += "int " + fabric_mod_name + "_shutdown_session(struct se_session *);\n"
if re.search('close_session\)\(', fo):
buf += "void " + fabric_mod_name + "_close_session(struct se_session *se_sess)\n"
buf += "{\n"
buf += " return;\n"
buf += "}\n\n"
bufi += "void " + fabric_mod_name + "_close_session(struct se_session *);\n"
if re.search('sess_get_index\)\(', fo):
buf += "u32 " + fabric_mod_name + "_sess_get_index(struct se_session *se_sess)\n"
buf += "{\n"
......
......@@ -2596,9 +2596,19 @@ static void isert_free_conn(struct iscsi_conn *conn)
isert_put_conn(isert_conn);
}
static void isert_get_rx_pdu(struct iscsi_conn *conn)
{
struct completion comp;
init_completion(&comp);
wait_for_completion_interruptible(&comp);
}
static struct iscsit_transport iser_target_transport = {
.name = "IB/iSER",
.transport_type = ISCSI_INFINIBAND,
.rdma_shutdown = true,
.priv_size = sizeof(struct isert_cmd),
.owner = THIS_MODULE,
.iscsit_setup_np = isert_setup_np,
......@@ -2614,6 +2624,7 @@ static struct iscsit_transport iser_target_transport = {
.iscsit_queue_data_in = isert_put_datain,
.iscsit_queue_status = isert_put_response,
.iscsit_aborted_task = isert_aborted_task,
.iscsit_get_rx_pdu = isert_get_rx_pdu,
.iscsit_get_sup_prot_ops = isert_get_sup_prot_ops,
};
......
......@@ -1767,14 +1767,6 @@ static void __srpt_close_all_ch(struct srpt_device *sdev)
}
}
/**
* srpt_shutdown_session() - Whether or not a session may be shut down.
*/
static int srpt_shutdown_session(struct se_session *se_sess)
{
return 1;
}
static void srpt_free_ch(struct kref *kref)
{
struct srpt_rdma_ch *ch = container_of(kref, struct srpt_rdma_ch, kref);
......@@ -3064,7 +3056,6 @@ static const struct target_core_fabric_ops srpt_template = {
.tpg_get_inst_index = srpt_tpg_get_inst_index,
.release_cmd = srpt_release_cmd,
.check_stop_free = srpt_check_stop_free,
.shutdown_session = srpt_shutdown_session,
.close_session = srpt_close_session,
.sess_get_index = srpt_sess_get_index,
.sess_get_initiator_sid = NULL,
......
......@@ -36,3 +36,12 @@ config TCM_QLA2XXX
default n
---help---
Say Y here to enable the TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs
if TCM_QLA2XXX
config TCM_QLA2XXX_DEBUG
bool "TCM_QLA2XXX fabric module DEBUG mode for QLogic 24xx+ series target mode HBAs"
default n
---help---
Say Y here to enable the TCM_QLA2XXX fabric module DEBUG for QLogic 24xx+ series target mode HBAs
This will include code to enable the SCSI command jammer
endif
......@@ -637,8 +637,10 @@ static void qlt_free_session_done(struct work_struct *work)
}
/* ha->tgt.sess_lock supposed to be held on entry */
void qlt_unreg_sess(struct qla_tgt_sess *sess)
static void qlt_release_session(struct kref *kref)
{
struct qla_tgt_sess *sess =
container_of(kref, struct qla_tgt_sess, sess_kref);
struct scsi_qla_host *vha = sess->vha;
if (sess->se_sess)
......@@ -651,8 +653,16 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess)
INIT_WORK(&sess->free_work, qlt_free_session_done);
schedule_work(&sess->free_work);
}
EXPORT_SYMBOL(qlt_unreg_sess);
void qlt_put_sess(struct qla_tgt_sess *sess)
{
if (!sess)
return;
assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
kref_put(&sess->sess_kref, qlt_release_session);
}
EXPORT_SYMBOL(qlt_put_sess);
static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
{
......@@ -857,12 +867,9 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
"Timeout: sess %p about to be deleted\n",
sess);
if (sess->se_sess) {
if (sess->se_sess)
ha->tgt.tgt_ops->shutdown_sess(sess);
ha->tgt.tgt_ops->put_sess(sess);
} else {
qlt_unreg_sess(sess);
}
qlt_put_sess(sess);
} else {
schedule_delayed_work(&tgt->sess_del_work,
sess->expires - elapsed);
......@@ -917,7 +924,7 @@ static struct qla_tgt_sess *qlt_create_sess(
}
}
kref_get(&sess->se_sess->sess_kref);
kref_get(&sess->sess_kref);
ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
(fcport->flags & FCF_CONF_COMP_SUPPORTED));
......@@ -947,6 +954,7 @@ static struct qla_tgt_sess *qlt_create_sess(
sess->s_id = fcport->d_id;
sess->loop_id = fcport->loop_id;
sess->local = local;
kref_init(&sess->sess_kref);
INIT_LIST_HEAD(&sess->del_list_entry);
/* Under normal circumstances we want to logout from firmware when
......@@ -991,7 +999,7 @@ static struct qla_tgt_sess *qlt_create_sess(
* Take an extra reference to ->sess_kref here to handle qla_tgt_sess
* access across ->tgt.sess_lock reaquire.
*/
kref_get(&sess->se_sess->sess_kref);
kref_get(&sess->sess_kref);
}
return sess;
......@@ -1035,7 +1043,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return;
} else {
kref_get(&sess->se_sess->sess_kref);
kref_get(&sess->sess_kref);
if (sess->deleted) {
qlt_undelete_sess(sess);
......@@ -1060,7 +1068,7 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
fcport->port_name, sess->loop_id);
sess->local = 0;
}
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
......@@ -3817,7 +3825,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
* Drop extra session reference from qla_tgt_handle_cmd_for_atio*(
*/
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return;
......@@ -3836,7 +3844,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
......@@ -3936,13 +3944,13 @@ static void qlt_create_sess_from_atio(struct work_struct *work)
if (!cmd) {
spin_lock_irqsave(&ha->hardware_lock, flags);
qlt_send_busy(vha, &op->atio, SAM_STAT_BUSY);
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
kfree(op);
return;
}
/*
* __qlt_do_work() will call ha->tgt.tgt_ops->put_sess() to release
* __qlt_do_work() will call qlt_put_sess() to release
* the extra reference taken above by qlt_make_local_sess()
*/
__qlt_do_work(cmd);
......@@ -4003,13 +4011,13 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
/*
* Do kref_get() before returning + dropping qla_hw_data->hardware_lock.
*/
kref_get(&sess->se_sess->sess_kref);
kref_get(&sess->sess_kref);
cmd = qlt_get_tag(vha, sess, atio);
if (!cmd) {
ql_dbg(ql_dbg_io, vha, 0x3062,
"qla_target(%d): Allocation of cmd failed\n", vha->vp_idx);
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
return -ENOMEM;
}
......@@ -5911,7 +5919,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
goto out_term2;
}
kref_get(&sess->se_sess->sess_kref);
kref_get(&sess->sess_kref);
}
spin_lock_irqsave(&ha->hardware_lock, flags);
......@@ -5924,7 +5932,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
goto out_term;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
return;
......@@ -5935,8 +5943,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (sess)
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
}
......@@ -5976,7 +5983,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
goto out_term;
}
kref_get(&sess->se_sess->sess_kref);
kref_get(&sess->sess_kref);
}
iocb = a;
......@@ -5988,14 +5995,13 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
if (rc != 0)
goto out_term;
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return;
out_term:
qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0);
if (sess)
ha->tgt.tgt_ops->put_sess(sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
......
......@@ -738,7 +738,6 @@ struct qla_tgt_func_tmpl {
struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
const uint8_t *);
void (*clear_nacl_from_fcport_map)(struct qla_tgt_sess *);
void (*put_sess)(struct qla_tgt_sess *);
void (*shutdown_sess)(struct qla_tgt_sess *);
};
......@@ -930,6 +929,7 @@ struct qla_tgt_sess {
int generation;
struct se_session *se_sess;
struct kref sess_kref;
struct scsi_qla_host *vha;
struct qla_tgt *tgt;
......@@ -1101,7 +1101,7 @@ extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *);
extern int qlt_lport_register(void *, u64, u64, u64,
int (*callback)(struct scsi_qla_host *, void *, u64, u64));
extern void qlt_lport_deregister(struct scsi_qla_host *);
extern void qlt_unreg_sess(struct qla_tgt_sess *);
void qlt_put_sess(struct qla_tgt_sess *sess);
extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int);
extern int __init qlt_init(void);
......
......@@ -339,22 +339,6 @@ static void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd)
qlt_free_cmd(cmd);
}
static int tcm_qla2xxx_shutdown_session(struct se_session *se_sess)
{
struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr;
struct scsi_qla_host *vha;
unsigned long flags;
BUG_ON(!sess);
vha = sess->vha;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
target_sess_cmd_list_set_waiting(se_sess);
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
return 1;
}
static void tcm_qla2xxx_close_session(struct se_session *se_sess)
{
struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr;
......@@ -365,7 +349,8 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess)
vha = sess->vha;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
qlt_unreg_sess(sess);
target_sess_cmd_list_set_waiting(se_sess);
qlt_put_sess(sess);
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
}
......@@ -457,6 +442,10 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
struct se_cmd *se_cmd = &cmd->se_cmd;
struct se_session *se_sess;
struct qla_tgt_sess *sess;
#ifdef CONFIG_TCM_QLA2XXX_DEBUG
struct se_portal_group *se_tpg;
struct tcm_qla2xxx_tpg *tpg;
#endif
int flags = TARGET_SCF_ACK_KREF;
if (bidi)
......@@ -477,6 +466,15 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
return -EINVAL;
}
#ifdef CONFIG_TCM_QLA2XXX_DEBUG
se_tpg = se_sess->se_tpg;
tpg = container_of(se_tpg, struct tcm_qla2xxx_tpg, se_tpg);
if (unlikely(tpg->tpg_attrib.jam_host)) {
/* return, and dont run target_submit_cmd,discarding command */
return 0;
}
#endif
cmd->vha->tgt_counters.qla_core_sbt_cmd++;
return target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0],
cmd->unpacked_lun, data_length, fcp_task_attr,
......@@ -758,23 +756,6 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess)
tcm_qla2xxx_clear_sess_lookup(lport, nacl, sess);
}
static void tcm_qla2xxx_release_session(struct kref *kref)
{
struct se_session *se_sess = container_of(kref,
struct se_session, sess_kref);
qlt_unreg_sess(se_sess->fabric_sess_ptr);
}
static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess)
{
if (!sess)
return;
assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session);
}
static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess)
{
assert_spin_locked(&sess->vha->hw->tgt.sess_lock);
......@@ -844,6 +825,9 @@ DEF_QLA_TPG_ATTRIB(cache_dynamic_acls);
DEF_QLA_TPG_ATTRIB(demo_mode_write_protect);
DEF_QLA_TPG_ATTRIB(prod_mode_write_protect);
DEF_QLA_TPG_ATTRIB(demo_mode_login_only);
#ifdef CONFIG_TCM_QLA2XXX_DEBUG
DEF_QLA_TPG_ATTRIB(jam_host);
#endif
static struct configfs_attribute *tcm_qla2xxx_tpg_attrib_attrs[] = {
&tcm_qla2xxx_tpg_attrib_attr_generate_node_acls,
......@@ -851,6 +835,9 @@ static struct configfs_attribute *tcm_qla2xxx_tpg_attrib_attrs[] = {
&tcm_qla2xxx_tpg_attrib_attr_demo_mode_write_protect,
&tcm_qla2xxx_tpg_attrib_attr_prod_mode_write_protect,
&tcm_qla2xxx_tpg_attrib_attr_demo_mode_login_only,
#ifdef CONFIG_TCM_QLA2XXX_DEBUG
&tcm_qla2xxx_tpg_attrib_attr_jam_host,
#endif
NULL,
};
......@@ -1023,6 +1010,7 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg(
tpg->tpg_attrib.demo_mode_write_protect = 1;
tpg->tpg_attrib.cache_dynamic_acls = 1;
tpg->tpg_attrib.demo_mode_login_only = 1;
tpg->tpg_attrib.jam_host = 0;
ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);
if (ret < 0) {
......@@ -1579,7 +1567,6 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
.find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id,
.find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id,
.clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map,
.put_sess = tcm_qla2xxx_put_sess,
.shutdown_sess = tcm_qla2xxx_shutdown_sess,
};
......@@ -1847,7 +1834,6 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
.tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index,
.check_stop_free = tcm_qla2xxx_check_stop_free,
.release_cmd = tcm_qla2xxx_release_cmd,
.shutdown_session = tcm_qla2xxx_shutdown_session,
.close_session = tcm_qla2xxx_close_session,
.sess_get_index = tcm_qla2xxx_sess_get_index,
.sess_get_initiator_sid = NULL,
......@@ -1890,7 +1876,6 @@ static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
.tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index,
.check_stop_free = tcm_qla2xxx_check_stop_free,
.release_cmd = tcm_qla2xxx_release_cmd,
.shutdown_session = tcm_qla2xxx_shutdown_session,
.close_session = tcm_qla2xxx_close_session,
.sess_get_index = tcm_qla2xxx_sess_get_index,
.sess_get_initiator_sid = NULL,
......
......@@ -34,6 +34,7 @@ struct tcm_qla2xxx_tpg_attrib {
int prod_mode_write_protect;
int demo_mode_login_only;
int fabric_prot_type;
int jam_host;
};
struct tcm_qla2xxx_tpg {
......
......@@ -7,3 +7,5 @@ config ISCSI_TARGET
help
Say M here to enable the ConfigFS enabled Linux-iSCSI.org iSCSI
Target Mode Stack.
source "drivers/target/iscsi/cxgbit/Kconfig"
......@@ -18,3 +18,4 @@ iscsi_target_mod-y += iscsi_target_parameters.o \
iscsi_target_transport.o
obj-$(CONFIG_ISCSI_TARGET) += iscsi_target_mod.o
obj-$(CONFIG_ISCSI_TARGET_CXGB4) += cxgbit/
config ISCSI_TARGET_CXGB4
tristate "Chelsio iSCSI target offload driver"
depends on ISCSI_TARGET && CHELSIO_T4 && INET
select CHELSIO_T4_UWIRE
---help---
To compile this driver as module, choose M here: the module
will be called cxgbit.
ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
ccflags-y += -Idrivers/target/iscsi
obj-$(CONFIG_ISCSI_TARGET_CXGB4) += cxgbit.o
cxgbit-y := cxgbit_main.o cxgbit_cm.o cxgbit_target.o cxgbit_ddp.o
/*
* Copyright (c) 2016 Chelsio Communications, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __CXGBIT_H__
#define __CXGBIT_H__
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
#include <linux/completion.h>
#include <linux/netdevice.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/inet.h>
#include <linux/wait.h>
#include <linux/kref.h>
#include <linux/timer.h>
#include <linux/io.h>
#include <asm/byteorder.h>
#include <net/net_namespace.h>
#include <target/iscsi/iscsi_transport.h>
#include <iscsi_target_parameters.h>
#include <iscsi_target_login.h>
#include "t4_regs.h"
#include "t4_msg.h"
#include "cxgb4.h"
#include "cxgb4_uld.h"
#include "l2t.h"
#include "cxgb4_ppm.h"
#include "cxgbit_lro.h"
extern struct mutex cdev_list_lock;
extern struct list_head cdev_list_head;
struct cxgbit_np;
struct cxgbit_sock;
struct cxgbit_cmd {
struct scatterlist sg;
struct cxgbi_task_tag_info ttinfo;
bool setup_ddp;
bool release;
};
#define CXGBIT_MAX_ISO_PAYLOAD \
min_t(u32, MAX_SKB_FRAGS * PAGE_SIZE, 65535)
struct cxgbit_iso_info {
u8 flags;
u32 mpdu;
u32 len;
u32 burst_len;
};
enum cxgbit_skcb_flags {
SKCBF_TX_NEED_HDR = (1 << 0), /* packet needs a header */
SKCBF_TX_FLAG_COMPL = (1 << 1), /* wr completion flag */
SKCBF_TX_ISO = (1 << 2), /* iso cpl in tx skb */
SKCBF_RX_LRO = (1 << 3), /* lro skb */
};
struct cxgbit_skb_rx_cb {
u8 opcode;
void *pdu_cb;
void (*backlog_fn)(struct cxgbit_sock *, struct sk_buff *);
};
struct cxgbit_skb_tx_cb {
u8 submode;
u32 extra_len;
};
union cxgbit_skb_cb {
struct {
u8 flags;
union {
struct cxgbit_skb_tx_cb tx;
struct cxgbit_skb_rx_cb rx;
};
};
struct {
/* This member must be first. */
struct l2t_skb_cb l2t;
struct sk_buff *wr_next;
};
};
#define CXGBIT_SKB_CB(skb) ((union cxgbit_skb_cb *)&((skb)->cb[0]))
#define cxgbit_skcb_flags(skb) (CXGBIT_SKB_CB(skb)->flags)
#define cxgbit_skcb_submode(skb) (CXGBIT_SKB_CB(skb)->tx.submode)
#define cxgbit_skcb_tx_wr_next(skb) (CXGBIT_SKB_CB(skb)->wr_next)
#define cxgbit_skcb_tx_extralen(skb) (CXGBIT_SKB_CB(skb)->tx.extra_len)
#define cxgbit_skcb_rx_opcode(skb) (CXGBIT_SKB_CB(skb)->rx.opcode)
#define cxgbit_skcb_rx_backlog_fn(skb) (CXGBIT_SKB_CB(skb)->rx.backlog_fn)
#define cxgbit_rx_pdu_cb(skb) (CXGBIT_SKB_CB(skb)->rx.pdu_cb)
static inline void *cplhdr(struct sk_buff *skb)
{
return skb->data;
}
enum cxgbit_cdev_flags {
CDEV_STATE_UP = 0,
CDEV_ISO_ENABLE,
CDEV_DDP_ENABLE,
};
#define NP_INFO_HASH_SIZE 32
struct np_info {
struct np_info *next;
struct cxgbit_np *cnp;
unsigned int stid;
};
struct cxgbit_list_head {
struct list_head list;
/* device lock */
spinlock_t lock;
};
struct cxgbit_device {
struct list_head list;
struct cxgb4_lld_info lldi;
struct np_info *np_hash_tab[NP_INFO_HASH_SIZE];
/* np lock */
spinlock_t np_lock;
u8 selectq[MAX_NPORTS][2];
struct cxgbit_list_head cskq;
u32 mdsl;
struct kref kref;
unsigned long flags;
};
struct cxgbit_wr_wait {
struct completion completion;
int ret;
};
enum cxgbit_csk_state {
CSK_STATE_IDLE = 0,
CSK_STATE_LISTEN,
CSK_STATE_CONNECTING,
CSK_STATE_ESTABLISHED,
CSK_STATE_ABORTING,
CSK_STATE_CLOSING,
CSK_STATE_MORIBUND,
CSK_STATE_DEAD,
};
enum cxgbit_csk_flags {
CSK_TX_DATA_SENT = 0,
CSK_LOGIN_PDU_DONE,
CSK_LOGIN_DONE,
CSK_DDP_ENABLE,
};
struct cxgbit_sock_common {
struct cxgbit_device *cdev;
struct sockaddr_storage local_addr;
struct sockaddr_storage remote_addr;
struct cxgbit_wr_wait wr_wait;
enum cxgbit_csk_state state;
unsigned long flags;
};
struct cxgbit_np {
struct cxgbit_sock_common com;
wait_queue_head_t accept_wait;
struct iscsi_np *np;
struct completion accept_comp;
struct list_head np_accept_list;
/* np accept lock */
spinlock_t np_accept_lock;
struct kref kref;
unsigned int stid;
};
struct cxgbit_sock {
struct cxgbit_sock_common com;
struct cxgbit_np *cnp;
struct iscsi_conn *conn;
struct l2t_entry *l2t;
struct dst_entry *dst;
struct list_head list;
struct sk_buff_head rxq;
struct sk_buff_head txq;
struct sk_buff_head ppodq;
struct sk_buff_head backlogq;
struct sk_buff_head skbq;
struct sk_buff *wr_pending_head;
struct sk_buff *wr_pending_tail;
struct sk_buff *skb;
struct sk_buff *lro_skb;
struct sk_buff *lro_hskb;
struct list_head accept_node;
/* socket lock */
spinlock_t lock;
wait_queue_head_t waitq;
wait_queue_head_t ack_waitq;
bool lock_owner;
struct kref kref;
u32 max_iso_npdu;
u32 wr_cred;
u32 wr_una_cred;
u32 wr_max_cred;