Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target fixes from Nicholas Bellinger:
 "This series is larger than what I'd normally be conformable with
  sending for a -rc5 PULL request..

  However, the bulk of the series is localized to qla2xxx target
  specific fixes that address a number of real-world correctness issues,
  that have been outstanding on the list for ~6 weeks now.  They where
  submitted + verified + acked by the HW LLD vendor, contributed by a
  major production customer of the code, and are marked for v3.18.y
  stable code.

  That said, I don't see a good reason to wait another month to get
  these fixes into mainline.

  Beyond the qla2xx specific fixes, this series also includes:

   - bugfix for a long standing use-after-free in iscsi-target during
     TPG shutdown + demo-mode sessions.

   - bugfix for a >= v4.0 regression OOPs in iscsi-target during a
     iscsi_start_kthreads() failure.

   - bugfix for a >= v4.0 regression hang in iscsi-target for iser
     explicit session/connection logout.

   - bugfix for a iser-target bug where a early CMA REJECTED status
     during login triggers a NULL pointer dereference OOPs.

   - bugfixes for a handful of v4.2-rc1 specific regressions related to
     the larger set of recent backend configfs attribute changes.

  A big thanks to QLogic + Pure Storage for the qla2xxx target bugfixes"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (28 commits)
  Documentation/target: Fix tcm_mod_builder.py build breakage
  iser-target: Fix REJECT CM event use-after-free OOPs
  iscsi-target: Fix iser explicit logout TX kthread leak
  iscsi-target: Fix iscsit_start_kthreads failure OOPs
  iscsi-target: Fix use-after-free during TPG session shutdown
  qla2xxx: terminate exchange when command is aborted by LIO
  qla2xxx: drop cmds/tmrs arrived while session is being deleted
  qla2xxx: disable scsi_transport_fc registration in target mode
  qla2xxx: added sess generations to detect RSCN update races
  qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives
  qla2xxx: delay plogi/prli ack until existing sessions are deleted
  qla2xxx: cleanup cmd in qla workqueue before processing TMR
  qla2xxx: kill sessions/log out initiator on RSCN and port down events
  qla2xxx: fix command initialization in target mode.
  qla2xxx: Remove msleep in qlt_send_term_exchange
  qla2xxx: adjust debug flags
  qla2xxx: release request queue reservation.
  qla2xxx: Add flush after updating ATIOQ consumer index.
  qla2xxx: Enable target mode for ISP27XX
  qla2xxx: Fix hardware lock/unlock issue causing kernel panic.
  ...
This commit is contained in:
Linus Torvalds 2015-07-29 09:54:40 -07:00
commit 733db573a6
22 changed files with 1105 additions and 220 deletions

View file

@ -738,7 +738,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
ql_log(ql_log_info, vha, 0x706f,
"Issuing MPI reset.\n");
if (IS_QLA83XX(ha)) {
if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
uint32_t idc_control;
qla83xx_idc_lock(vha, 0);

View file

@ -67,10 +67,10 @@
* | | | 0xd031-0xd0ff |
* | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe |
* | Target Mode | 0xe079 | |
* | Target Mode Management | 0xf072 | 0xf002 |
* | Target Mode | 0xe080 | |
* | Target Mode Management | 0xf096 | 0xf002 |
* | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000b | |
* | Target Mode Task Management | 0x1000d | |
* ----------------------------------------------------------------------
*/

View file

@ -274,6 +274,7 @@
#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
struct req_que;
struct qla_tgt_sess;
/*
* (sd.h is not exported, hence local inclusion)
@ -2026,6 +2027,7 @@ typedef struct fc_port {
uint16_t port_id;
unsigned long retry_delay_timestamp;
struct qla_tgt_sess *tgt_session;
} fc_port_t;
#include "qla_mr.h"
@ -3154,13 +3156,13 @@ struct qla_hw_data {
/* Bit 21 of fw_attributes decides the MCTP capabilities */
#define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \
((ha)->fw_attributes_ext[0] & BIT_0))
#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha))
#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha))
#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_PI_DIFB_DIX0_CAPABLE(ha) (0)
#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha))
#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \
(((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22))
#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha))
#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length)
#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha))
#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
@ -3579,6 +3581,16 @@ typedef struct scsi_qla_host {
uint16_t fcoe_fcf_idx;
uint8_t fcoe_vn_port_mac[6];
/* list of commands waiting on workqueue */
struct list_head qla_cmd_list;
struct list_head qla_sess_op_cmd_list;
spinlock_t cmd_list_lock;
/* Counter to detect races between ELS and RSCN events */
atomic_t generation_tick;
/* Time when global fcport update has been scheduled */
int total_fcport_update_gen;
uint32_t vp_abort_cnt;
struct fc_vport *fc_vport; /* holds fc_vport * for each vport */

View file

@ -115,6 +115,8 @@ qla2x00_async_iocb_timeout(void *data)
QLA_LOGIO_LOGIN_RETRIED : 0;
qla2x00_post_async_login_done_work(fcport->vha, fcport,
lio->u.logio.data);
} else if (sp->type == SRB_LOGOUT_CMD) {
qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
}
}
@ -497,7 +499,10 @@ void
qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
uint16_t *data)
{
qla2x00_mark_device_lost(vha, fcport, 1, 0);
/* Don't re-login in target mode */
if (!fcport->tgt_session)
qla2x00_mark_device_lost(vha, fcport, 1, 0);
qlt_logo_completion_handler(fcport, data[0]);
return;
}
@ -1538,7 +1543,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
mem_size = (ha->fw_memory_size - 0x11000 + 1) *
sizeof(uint16_t);
} else if (IS_FWI2_CAPABLE(ha)) {
if (IS_QLA83XX(ha))
if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
else if (IS_QLA81XX(ha))
fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
@ -1550,7 +1555,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
mem_size = (ha->fw_memory_size - 0x100000 + 1) *
sizeof(uint32_t);
if (ha->mqenable) {
if (!IS_QLA83XX(ha))
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
mq_size = sizeof(struct qla2xxx_mq_chain);
/*
* Allocate maximum buffer size for all queues.
@ -2922,21 +2927,14 @@ qla2x00_rport_del(void *data)
{
fc_port_t *fcport = data;
struct fc_rport *rport;
scsi_qla_host_t *vha = fcport->vha;
unsigned long flags;
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
rport = fcport->drport ? fcport->drport: fcport->rport;
fcport->drport = NULL;
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
if (rport) {
if (rport)
fc_remote_port_delete(rport);
/*
* Release the target mode FC NEXUS in qla_target.c code
* if target mod is enabled.
*/
qlt_fc_port_deleted(vha, fcport);
}
}
/**
@ -3303,6 +3301,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
* Create target mode FC NEXUS in qla_target.c if target mode is
* enabled..
*/
qlt_fc_port_added(vha, fcport);
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
@ -3341,8 +3340,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
if (IS_QLAFX00(vha->hw)) {
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
qla2x00_reg_remote_port(vha, fcport);
return;
goto reg_port;
}
fcport->login_retry = 0;
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
@ -3350,7 +3348,16 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
qla2x00_iidma_fcport(vha, fcport);
qla24xx_update_fcport_fcp_prio(vha, fcport);
qla2x00_reg_remote_port(vha, fcport);
reg_port:
if (qla_ini_mode_enabled(vha))
qla2x00_reg_remote_port(vha, fcport);
else {
/*
* Create target mode FC NEXUS in qla_target.c
*/
qlt_fc_port_added(vha, fcport);
}
}
/*
@ -3375,6 +3382,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
LIST_HEAD(new_fcports);
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
int discovery_gen;
/* If FL port exists, then SNS is present */
if (IS_FWI2_CAPABLE(ha))
@ -3445,6 +3453,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
fcport->scan_state = QLA_FCPORT_SCAN;
}
/* Mark the time right before querying FW for connected ports.
* This process is long, asynchronous and by the time it's done,
* collected information might not be accurate anymore. E.g.
* disconnected port might have re-connected and a brand new
* session has been created. In this case session's generation
* will be newer than discovery_gen. */
qlt_do_generation_tick(vha, &discovery_gen);
rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
if (rval != QLA_SUCCESS)
break;
@ -3460,20 +3476,44 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
continue;
if (fcport->scan_state == QLA_FCPORT_SCAN &&
atomic_read(&fcport->state) == FCS_ONLINE) {
qla2x00_mark_device_lost(vha, fcport,
ql2xplogiabsentdevice, 0);
if (fcport->loop_id != FC_NO_LOOP_ID &&
(fcport->flags & FCF_FCP2_DEVICE) == 0 &&
fcport->port_type != FCT_INITIATOR &&
fcport->port_type != FCT_BROADCAST) {
ha->isp_ops->fabric_logout(vha,
fcport->loop_id,
fcport->d_id.b.domain,
fcport->d_id.b.area,
fcport->d_id.b.al_pa);
qla2x00_clear_loop_id(fcport);
if (fcport->scan_state == QLA_FCPORT_SCAN) {
if (qla_ini_mode_enabled(base_vha) &&
atomic_read(&fcport->state) == FCS_ONLINE) {
qla2x00_mark_device_lost(vha, fcport,
ql2xplogiabsentdevice, 0);
if (fcport->loop_id != FC_NO_LOOP_ID &&
(fcport->flags & FCF_FCP2_DEVICE) == 0 &&
fcport->port_type != FCT_INITIATOR &&
fcport->port_type != FCT_BROADCAST) {
ha->isp_ops->fabric_logout(vha,
fcport->loop_id,
fcport->d_id.b.domain,
fcport->d_id.b.area,
fcport->d_id.b.al_pa);
qla2x00_clear_loop_id(fcport);
}
} else if (!qla_ini_mode_enabled(base_vha)) {
/*
* In target mode, explicitly kill
* sessions and log out of devices
* that are gone, so that we don't
* end up with an initiator using the
* wrong ACL (if the fabric recycles
* an FC address and we have a stale
* session around) and so that we don't
* report initiators that are no longer
* on the fabric.
*/
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077,
"port gone, logging out/killing session: "
"%8phC state 0x%x flags 0x%x fc4_type 0x%x "
"scan_state %d\n",
fcport->port_name,
atomic_read(&fcport->state),
fcport->flags, fcport->fc4_type,
fcport->scan_state);
qlt_fc_port_deleted(vha, fcport,
discovery_gen);
}
}
}
@ -3494,6 +3534,28 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
(fcport->flags & FCF_LOGIN_NEEDED) == 0)
continue;
/*
* If we're not an initiator, skip looking for devices
* and logging in. There's no reason for us to do it,
* and it seems to actively cause problems in target
* mode if we race with the initiator logging into us
* (we might get the "port ID used" status back from
* our login command and log out the initiator, which
* seems to cause havoc).
*/
if (!qla_ini_mode_enabled(base_vha)) {
if (fcport->scan_state == QLA_FCPORT_FOUND) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078,
"port %8phC state 0x%x flags 0x%x fc4_type 0x%x "
"scan_state %d (initiator mode disabled; skipping "
"login)\n", fcport->port_name,
atomic_read(&fcport->state),
fcport->flags, fcport->fc4_type,
fcport->scan_state);
}
continue;
}
if (fcport->loop_id == FC_NO_LOOP_ID) {
fcport->loop_id = next_loopid;
rval = qla2x00_find_new_loop_id(
@ -3520,16 +3582,38 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
break;
/* Find a new loop ID to use. */
fcport->loop_id = next_loopid;
rval = qla2x00_find_new_loop_id(base_vha, fcport);
if (rval != QLA_SUCCESS) {
/* Ran out of IDs to use */
break;
}
/*
* If we're not an initiator, skip looking for devices
* and logging in. There's no reason for us to do it,
* and it seems to actively cause problems in target
* mode if we race with the initiator logging into us
* (we might get the "port ID used" status back from
* our login command and log out the initiator, which
* seems to cause havoc).
*/
if (qla_ini_mode_enabled(base_vha)) {
/* Find a new loop ID to use. */
fcport->loop_id = next_loopid;
rval = qla2x00_find_new_loop_id(base_vha,
fcport);
if (rval != QLA_SUCCESS) {
/* Ran out of IDs to use */
break;
}
/* Login and update database */
qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
/* Login and update database */
qla2x00_fabric_dev_login(vha, fcport,
&next_loopid);
} else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079,
"new port %8phC state 0x%x flags 0x%x fc4_type "
"0x%x scan_state %d (initiator mode disabled; "
"skipping login)\n",
fcport->port_name,
atomic_read(&fcport->state),
fcport->flags, fcport->fc4_type,
fcport->scan_state);
}
list_move_tail(&fcport->list, &vha->vp_fcports);
}
@ -3725,11 +3809,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
fcport->fp_speed = new_fcport->fp_speed;
/*
* If address the same and state FCS_ONLINE, nothing
* changed.
* If address the same and state FCS_ONLINE
* (or in target mode), nothing changed.
*/
if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
atomic_read(&fcport->state) == FCS_ONLINE) {
(atomic_read(&fcport->state) == FCS_ONLINE ||
!qla_ini_mode_enabled(base_vha))) {
break;
}
@ -3749,6 +3834,22 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
* Log it out if still logged in and mark it for
* relogin later.
*/
if (!qla_ini_mode_enabled(base_vha)) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
"port changed FC ID, %8phC"
" old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
fcport->port_name,
fcport->d_id.b.domain,
fcport->d_id.b.area,
fcport->d_id.b.al_pa,
fcport->loop_id,
new_fcport->d_id.b.domain,
new_fcport->d_id.b.area,
new_fcport->d_id.b.al_pa);
fcport->d_id.b24 = new_fcport->d_id.b24;
break;
}
fcport->d_id.b24 = new_fcport->d_id.b24;
fcport->flags |= FCF_LOGIN_NEEDED;
if (fcport->loop_id != FC_NO_LOOP_ID &&
@ -3768,6 +3869,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
if (found)
continue;
/* If device was not in our fcports list, then add it. */
new_fcport->scan_state = QLA_FCPORT_FOUND;
list_add_tail(&new_fcport->list, new_fcports);
/* Allocate a new replacement fcport. */
@ -4188,6 +4290,14 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
spin_unlock_irqrestore(&ha->vport_slock, flags);
qla2x00_rport_del(fcport);
/*
* Release the target mode FC NEXUS in
* qla_target.c, if target mod is enabled.
*/
qlt_fc_port_deleted(vha, fcport,
base_vha->total_fcport_update_gen);
spin_lock_irqsave(&ha->vport_slock, flags);
}
}

View file

@ -1943,6 +1943,9 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags =
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
if (!sp->fcport->tgt_session ||
!sp->fcport->tgt_session->keep_nport_handle)
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
logio->port_id[1] = sp->fcport->d_id.b.area;

View file

@ -2415,7 +2415,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt,
*orig_iocb_cnt = mcp->mb[10];
if (vha->hw->flags.npiv_supported && max_npiv_vports)
*max_npiv_vports = mcp->mb[11];
if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw)) && max_fcfs)
if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) ||
IS_QLA27XX(vha->hw)) && max_fcfs)
*max_fcfs = mcp->mb[12];
}
@ -3898,7 +3899,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!(rsp->options & BIT_0)) {
WRT_REG_DWORD(rsp->rsp_q_out, 0);
if (!IS_QLA83XX(ha))
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
WRT_REG_DWORD(rsp->rsp_q_in, 0);
}
@ -5345,7 +5346,7 @@ qla83xx_restart_nic_firmware(scsi_qla_host_t *vha)
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
if (!IS_QLA83XX(ha))
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__);

View file

@ -2504,6 +2504,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->mbx_count = MAILBOX_REGISTER_COUNT;
req_length = REQUEST_ENTRY_CNT_24XX;
rsp_length = RESPONSE_ENTRY_CNT_2300;
ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
ha->gid_list_info_size = 8;
@ -3229,11 +3230,15 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
spin_lock_irqsave(vha->host->host_lock, flags);
fcport->drport = rport;
spin_unlock_irqrestore(vha->host->host_lock, flags);
qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen);
set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
qla2xxx_wake_dpc(base_vha);
} else {
fc_remote_port_delete(rport);
qlt_fc_port_deleted(vha, fcport);
int now;
if (rport)
fc_remote_port_delete(rport);
qlt_do_generation_tick(vha, &now);
qlt_fc_port_deleted(vha, fcport, now);
}
}
@ -3763,8 +3768,11 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
INIT_LIST_HEAD(&vha->vp_fcports);
INIT_LIST_HEAD(&vha->work_list);
INIT_LIST_HEAD(&vha->list);
INIT_LIST_HEAD(&vha->qla_cmd_list);
INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list);
spin_lock_init(&vha->work_lock);
spin_lock_init(&vha->cmd_list_lock);
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041,

View file

@ -1697,7 +1697,7 @@ qla83xx_select_led_port(struct qla_hw_data *ha)
{
uint32_t led_select_value = 0;
if (!IS_QLA83XX(ha))
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
goto out;
if (ha->port_no == 0)

File diff suppressed because it is too large Load diff

View file

@ -167,7 +167,24 @@ struct imm_ntfy_from_isp {
uint32_t srr_rel_offs;
uint16_t srr_ui;
uint16_t srr_ox_id;
uint8_t reserved_4[19];
union {
struct {
uint8_t node_name[8];
} plogi; /* PLOGI/ADISC/PDISC */
struct {
/* PRLI word 3 bit 0-15 */
uint16_t wd3_lo;
uint8_t resv0[6];
} prli;
struct {
uint8_t port_id[3];
uint8_t resv1;
uint16_t nport_handle;
uint16_t resv2;
} req_els;
} u;
uint8_t port_name[8];
uint8_t resv3[3];
uint8_t vp_index;
uint32_t reserved_5;
uint8_t port_id[3];
@ -234,6 +251,7 @@ struct nack_to_isp {
uint8_t reserved[2];
uint16_t ox_id;
} __packed;
#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3
#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
#define NOTIFY_ACK_SRR_FLAGS_REJECT 1
@ -790,13 +808,6 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
#define FC_TM_REJECT 4
#define FC_TM_FAILED 5
/*
* Error code of qlt_pre_xmit_response() meaning that cmd's exchange was
* terminated, so no more actions is needed and success should be returned
* to target.
*/
#define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717
#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
#define pci_dma_lo32(a) (a & 0xffffffff)
#define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff)
@ -874,6 +885,15 @@ struct qla_tgt_sess_op {
struct scsi_qla_host *vha;
struct atio_from_isp atio;
struct work_struct work;
struct list_head cmd_list;
bool aborted;
};
enum qla_sess_deletion {
QLA_SESS_DELETION_NONE = 0,
QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
* this one */
QLA_SESS_DELETION_IN_PROGRESS = 2,
};
/*
@ -884,8 +904,15 @@ struct qla_tgt_sess {
port_id_t s_id;
unsigned int conf_compl_supported:1;
unsigned int deleted:1;
unsigned int deleted:2;
unsigned int local:1;
unsigned int logout_on_delete:1;
unsigned int plogi_ack_needed:1;
unsigned int keep_nport_handle:1;
unsigned char logout_completed;
int generation;
struct se_session *se_sess;
struct scsi_qla_host *vha;
@ -897,6 +924,10 @@ struct qla_tgt_sess {
uint8_t port_name[WWN_SIZE];
struct work_struct free_work;
union {
struct imm_ntfy_from_isp tm_iocb;
};
};
struct qla_tgt_cmd {
@ -912,7 +943,6 @@ struct qla_tgt_cmd {
unsigned int conf_compl_supported:1;
unsigned int sg_mapped:1;
unsigned int free_sg:1;
unsigned int aborted:1; /* Needed in case of SRR */
unsigned int write_data_transferred:1;
unsigned int ctx_dsd_alloced:1;
unsigned int q_full:1;
@ -961,6 +991,9 @@ struct qla_tgt_cmd {
* BIT_14 - Back end data received/sent.
* BIT_15 - SRR prepare ctio
* BIT_16 - complete free
* BIT_17 - flush - qlt_abort_cmd_on_host_reset
* BIT_18 - completion w/abort status
* BIT_19 - completion w/unknown status
*/
uint32_t cmd_flags;
};
@ -1026,6 +1059,10 @@ struct qla_tgt_srr_ctio {
struct qla_tgt_cmd *cmd;
};
/* Check for Switch reserved address */
#define IS_SW_RESV_ADDR(_s_id) \
((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
#define QLA_TGT_XMIT_DATA 1
#define QLA_TGT_XMIT_STATUS 2
#define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA)
@ -1043,7 +1080,7 @@ extern int qlt_lport_register(void *, u64, u64, u64,
extern void qlt_lport_deregister(struct scsi_qla_host *);
extern void qlt_unreg_sess(struct qla_tgt_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 *);
extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int);
extern int __init qlt_init(void);
extern void qlt_exit(void);
extern void qlt_update_vp_map(struct scsi_qla_host *, int);
@ -1073,12 +1110,23 @@ static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
ha->host->active_mode |= MODE_INITIATOR;
}
static inline uint32_t sid_to_key(const uint8_t *s_id)
{
uint32_t key;
key = (((unsigned long)s_id[0] << 16) |
((unsigned long)s_id[1] << 8) |
(unsigned long)s_id[2]);
return key;
}
/*
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
*/
extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
extern void qlt_abort_cmd(struct qla_tgt_cmd *);
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
@ -1109,5 +1157,7 @@ extern void qlt_stop_phase2(struct qla_tgt *);
extern irqreturn_t qla83xx_msix_atio_q(int, void *);
extern void qlt_83xx_iospace_config(struct qla_hw_data *);
extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
extern void qlt_logo_completion_handler(fc_port_t *, int);
extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
#endif /* __QLA_TARGET_H */

View file

@ -374,7 +374,7 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
{
struct qla_tgt_cmd *cmd = container_of(se_cmd,
struct qla_tgt_cmd, se_cmd);
cmd->cmd_flags |= BIT_3;
cmd->bufflen = se_cmd->data_length;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
@ -405,7 +405,7 @@ static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd)
se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) {
spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
wait_for_completion_timeout(&se_cmd->t_transport_stop_comp,
3000);
3 * HZ);
return 0;
}
spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
@ -541,12 +541,10 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
cmd->cmd_flags |= BIT_4;
cmd->bufflen = se_cmd->data_length;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
cmd->sg_cnt = se_cmd->t_data_nents;
cmd->sg = se_cmd->t_data_sg;
cmd->offset = 0;
cmd->cmd_flags |= BIT_3;
cmd->prot_sg_cnt = se_cmd->t_prot_nents;
cmd->prot_sg = se_cmd->t_prot_sg;
@ -571,7 +569,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
cmd->sg_cnt = 0;
cmd->offset = 0;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
if (cmd->cmd_flags & BIT_5) {
pr_crit("Bit_5 already set for cmd = %p.\n", cmd);
dump_stack();
@ -636,14 +633,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
{
struct qla_tgt_cmd *cmd = container_of(se_cmd,
struct qla_tgt_cmd, se_cmd);
struct scsi_qla_host *vha = cmd->vha;
struct qla_hw_data *ha = vha->hw;
if (!cmd->sg_mapped)
return;
pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
cmd->sg_mapped = 0;
qlt_abort_cmd(cmd);
}
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
@ -1149,9 +1139,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
return NULL;
}
key = (((unsigned long)s_id[0] << 16) |
((unsigned long)s_id[1] << 8) |
(unsigned long)s_id[2]);
key = sid_to_key(s_id);
pr_debug("find_sess_by_s_id: 0x%06x\n", key);
se_nacl = btree_lookup32(&lport->lport_fcport_map, key);
@ -1186,9 +1174,7 @@ static void tcm_qla2xxx_set_sess_by_s_id(
void *slot;
int rc;
key = (((unsigned long)s_id[0] << 16) |
((unsigned long)s_id[1] << 8) |
(unsigned long)s_id[2]);
key = sid_to_key(s_id);
pr_debug("set_sess_by_s_id: %06x\n", key);
slot = btree_lookup32(&lport->lport_fcport_map, key);
@ -1544,6 +1530,10 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
}
sess->conf_compl_supported = conf_compl_supported;
/* Reset logout parameters to default */
sess->logout_on_delete = 1;
sess->keep_nport_handle = 0;
}
/*