forked from Minki/linux
Merge branch 'fixes' into misc
Somewhat nasty merge due to conflicts between "33b28357dd00 scsi: qla2xxx: Fix Async GPN_FT for FCP and FC-NVMe scan" and "2b5b96473efc scsi: qla2xxx: Fix FC-NVMe LUN discovery" Merge is non-trivial and has been verified by Qlogic (Cavium) Signed-off-by: James E.J. Bottomley <jejb@linux.vnet.ibm.com>
This commit is contained in:
commit
2e1f44f6ad
@ -2687,6 +2687,8 @@ mptctl_hp_targetinfo(unsigned long arg)
|
||||
__FILE__, __LINE__, iocnum);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
|
||||
return -EINVAL;
|
||||
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
|
||||
ioc->name));
|
||||
|
||||
|
@ -180,7 +180,6 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
|
||||
CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
|
||||
zalon7xx-objs := zalon.o ncr53c8xx.o
|
||||
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
|
||||
oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o
|
||||
|
||||
# Files generated that shall be removed upon make clean
|
||||
clean-files := 53c700_d.h 53c700_u.h
|
||||
|
@ -1693,8 +1693,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
* Map in the registers from the adapter.
|
||||
*/
|
||||
aac->base_size = AAC_MIN_FOOTPRINT_SIZE;
|
||||
if ((*aac_drivers[index].init)(aac))
|
||||
if ((*aac_drivers[index].init)(aac)) {
|
||||
error = -ENODEV;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
if (aac->sync_mode) {
|
||||
if (aac_sync_mode)
|
||||
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Implementation of Utility functions for all SCSI device types.
|
||||
*
|
||||
* Copyright (c) 1997, 1998, 1999 Justin T. Gibbs.
|
||||
* Copyright (c) 1997, 1998 Kenneth D. Merry.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.38 2002/09/23 04:56:35 mjacob Exp $
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "aiclib.h"
|
||||
|
@ -1889,6 +1889,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
|
||||
/* we will not receive ABTS response for this IO */
|
||||
BNX2FC_IO_DBG(io_req, "Timer context finished processing "
|
||||
"this scsi cmd\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cancel the timeout_work, as we received IO completion */
|
||||
|
@ -114,7 +114,7 @@ static enum csio_ln_ev fwevt_to_lnevt[] = {
|
||||
static struct csio_lnode *
|
||||
csio_ln_lookup_by_portid(struct csio_hw *hw, uint8_t portid)
|
||||
{
|
||||
struct csio_lnode *ln = hw->rln;
|
||||
struct csio_lnode *ln;
|
||||
struct list_head *tmp;
|
||||
|
||||
/* Match siblings lnode with portid */
|
||||
|
@ -876,6 +876,11 @@ static void alua_rtpg_work(struct work_struct *work)
|
||||
|
||||
/**
|
||||
* alua_rtpg_queue() - cause RTPG to be submitted asynchronously
|
||||
* @pg: ALUA port group associated with @sdev.
|
||||
* @sdev: SCSI device for which to submit an RTPG.
|
||||
* @qdata: Information about the callback to invoke after the RTPG.
|
||||
* @force: Whether or not to submit an RTPG if a work item that will submit an
|
||||
* RTPG already has been scheduled.
|
||||
*
|
||||
* Returns true if and only if alua_rtpg_work() will be called asynchronously.
|
||||
* That function is responsible for calling @qdata->fn().
|
||||
|
@ -333,8 +333,6 @@ static void scsi_host_dev_release(struct device *dev)
|
||||
if (shost->work_q)
|
||||
destroy_workqueue(shost->work_q);
|
||||
|
||||
destroy_rcu_head(&shost->rcu);
|
||||
|
||||
if (shost->shost_state == SHOST_CREATED) {
|
||||
/*
|
||||
* Free the shost_dev device name here if scsi_host_alloc()
|
||||
@ -403,7 +401,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
|
||||
INIT_LIST_HEAD(&shost->starved_list);
|
||||
init_waitqueue_head(&shost->host_wait);
|
||||
mutex_init(&shost->scan_mutex);
|
||||
init_rcu_head(&shost->rcu);
|
||||
|
||||
index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL);
|
||||
if (index < 0)
|
||||
@ -476,6 +473,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
|
||||
shost->dma_boundary = 0xffffffff;
|
||||
|
||||
shost->use_blk_mq = scsi_use_blk_mq;
|
||||
shost->use_blk_mq = scsi_use_blk_mq || shost->hostt->force_blk_mq;
|
||||
|
||||
device_initialize(&shost->shost_gendev);
|
||||
dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
|
||||
|
@ -1045,11 +1045,7 @@ static void set_performant_mode(struct ctlr_info *h, struct CommandList *c,
|
||||
c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
|
||||
if (unlikely(!h->msix_vectors))
|
||||
return;
|
||||
if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
|
||||
c->Header.ReplyQueue =
|
||||
raw_smp_processor_id() % h->nreply_queues;
|
||||
else
|
||||
c->Header.ReplyQueue = reply_queue % h->nreply_queues;
|
||||
c->Header.ReplyQueue = reply_queue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1063,10 +1059,7 @@ static void set_ioaccel1_performant_mode(struct ctlr_info *h,
|
||||
* Tell the controller to post the reply to the queue for this
|
||||
* processor. This seems to give the best I/O throughput.
|
||||
*/
|
||||
if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
|
||||
cp->ReplyQueue = smp_processor_id() % h->nreply_queues;
|
||||
else
|
||||
cp->ReplyQueue = reply_queue % h->nreply_queues;
|
||||
cp->ReplyQueue = reply_queue;
|
||||
/*
|
||||
* Set the bits in the address sent down to include:
|
||||
* - performant mode bit (bit 0)
|
||||
@ -1087,10 +1080,7 @@ static void set_ioaccel2_tmf_performant_mode(struct ctlr_info *h,
|
||||
/* Tell the controller to post the reply to the queue for this
|
||||
* processor. This seems to give the best I/O throughput.
|
||||
*/
|
||||
if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
|
||||
cp->reply_queue = smp_processor_id() % h->nreply_queues;
|
||||
else
|
||||
cp->reply_queue = reply_queue % h->nreply_queues;
|
||||
cp->reply_queue = reply_queue;
|
||||
/* Set the bits in the address sent down to include:
|
||||
* - performant mode bit not used in ioaccel mode 2
|
||||
* - pull count (bits 0-3)
|
||||
@ -1109,10 +1099,7 @@ static void set_ioaccel2_performant_mode(struct ctlr_info *h,
|
||||
* Tell the controller to post the reply to the queue for this
|
||||
* processor. This seems to give the best I/O throughput.
|
||||
*/
|
||||
if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
|
||||
cp->reply_queue = smp_processor_id() % h->nreply_queues;
|
||||
else
|
||||
cp->reply_queue = reply_queue % h->nreply_queues;
|
||||
cp->reply_queue = reply_queue;
|
||||
/*
|
||||
* Set the bits in the address sent down to include:
|
||||
* - performant mode bit not used in ioaccel mode 2
|
||||
@ -1157,6 +1144,8 @@ static void __enqueue_cmd_and_start_io(struct ctlr_info *h,
|
||||
{
|
||||
dial_down_lockup_detection_during_fw_flash(h, c);
|
||||
atomic_inc(&h->commands_outstanding);
|
||||
|
||||
reply_queue = h->reply_map[raw_smp_processor_id()];
|
||||
switch (c->cmd_type) {
|
||||
case CMD_IOACCEL1:
|
||||
set_ioaccel1_performant_mode(h, c, reply_queue);
|
||||
@ -7376,6 +7365,26 @@ static void hpsa_disable_interrupt_mode(struct ctlr_info *h)
|
||||
h->msix_vectors = 0;
|
||||
}
|
||||
|
||||
static void hpsa_setup_reply_map(struct ctlr_info *h)
|
||||
{
|
||||
const struct cpumask *mask;
|
||||
unsigned int queue, cpu;
|
||||
|
||||
for (queue = 0; queue < h->msix_vectors; queue++) {
|
||||
mask = pci_irq_get_affinity(h->pdev, queue);
|
||||
if (!mask)
|
||||
goto fallback;
|
||||
|
||||
for_each_cpu(cpu, mask)
|
||||
h->reply_map[cpu] = queue;
|
||||
}
|
||||
return;
|
||||
|
||||
fallback:
|
||||
for_each_possible_cpu(cpu)
|
||||
h->reply_map[cpu] = 0;
|
||||
}
|
||||
|
||||
/* If MSI/MSI-X is supported by the kernel we will try to enable it on
|
||||
* controllers that are capable. If not, we use legacy INTx mode.
|
||||
*/
|
||||
@ -7771,6 +7780,10 @@ static int hpsa_pci_init(struct ctlr_info *h)
|
||||
err = hpsa_interrupt_mode(h);
|
||||
if (err)
|
||||
goto clean1;
|
||||
|
||||
/* setup mapping between CPU and reply queue */
|
||||
hpsa_setup_reply_map(h);
|
||||
|
||||
err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr);
|
||||
if (err)
|
||||
goto clean2; /* intmode+region, pci */
|
||||
@ -8480,6 +8493,28 @@ static struct workqueue_struct *hpsa_create_controller_wq(struct ctlr_info *h,
|
||||
return wq;
|
||||
}
|
||||
|
||||
static void hpda_free_ctlr_info(struct ctlr_info *h)
|
||||
{
|
||||
kfree(h->reply_map);
|
||||
kfree(h);
|
||||
}
|
||||
|
||||
static struct ctlr_info *hpda_alloc_ctlr_info(void)
|
||||
{
|
||||
struct ctlr_info *h;
|
||||
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
if (!h)
|
||||
return NULL;
|
||||
|
||||
h->reply_map = kzalloc(sizeof(*h->reply_map) * nr_cpu_ids, GFP_KERNEL);
|
||||
if (!h->reply_map) {
|
||||
kfree(h);
|
||||
return NULL;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
int dac, rc;
|
||||
@ -8517,7 +8552,7 @@ reinit_after_soft_reset:
|
||||
* the driver. See comments in hpsa.h for more info.
|
||||
*/
|
||||
BUILD_BUG_ON(sizeof(struct CommandList) % COMMANDLIST_ALIGNMENT);
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
h = hpda_alloc_ctlr_info();
|
||||
if (!h) {
|
||||
dev_err(&pdev->dev, "Failed to allocate controller head\n");
|
||||
return -ENOMEM;
|
||||
@ -8916,7 +8951,7 @@ static void hpsa_remove_one(struct pci_dev *pdev)
|
||||
h->lockup_detected = NULL; /* init_one 2 */
|
||||
/* (void) pci_disable_pcie_error_reporting(pdev); */ /* init_one 1 */
|
||||
|
||||
kfree(h); /* init_one 1 */
|
||||
hpda_free_ctlr_info(h); /* init_one 1 */
|
||||
}
|
||||
|
||||
static int hpsa_suspend(__attribute__((unused)) struct pci_dev *pdev,
|
||||
|
@ -158,6 +158,7 @@ struct bmic_controller_parameters {
|
||||
#pragma pack()
|
||||
|
||||
struct ctlr_info {
|
||||
unsigned int *reply_map;
|
||||
int ctlr;
|
||||
char devname[8];
|
||||
char *product_name;
|
||||
|
@ -3579,11 +3579,9 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
|
||||
static int ibmvfc_adisc_needs_plogi(struct ibmvfc_passthru_mad *mad,
|
||||
struct ibmvfc_target *tgt)
|
||||
{
|
||||
if (memcmp(&mad->fc_iu.response[2], &tgt->ids.port_name,
|
||||
sizeof(tgt->ids.port_name)))
|
||||
if (wwn_to_u64((u8 *)&mad->fc_iu.response[2]) != tgt->ids.port_name)
|
||||
return 1;
|
||||
if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name,
|
||||
sizeof(tgt->ids.node_name)))
|
||||
if (wwn_to_u64((u8 *)&mad->fc_iu.response[4]) != tgt->ids.node_name)
|
||||
return 1;
|
||||
if (be32_to_cpu(mad->fc_iu.response[6]) != tgt->scsi_id)
|
||||
return 1;
|
||||
|
@ -367,7 +367,7 @@ enum ibmvfc_fcp_rsp_info_codes {
|
||||
};
|
||||
|
||||
struct ibmvfc_fcp_rsp_info {
|
||||
__be16 reserved;
|
||||
u8 reserved[3];
|
||||
u8 rsp_code;
|
||||
u8 reserved2[4];
|
||||
}__attribute__((packed, aligned (2)));
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <net/tcp.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_device.h>
|
||||
@ -954,6 +955,13 @@ static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
|
||||
|
||||
static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
|
||||
{
|
||||
struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(sdev->host);
|
||||
struct iscsi_session *session = tcp_sw_host->session;
|
||||
struct iscsi_conn *conn = session->leadconn;
|
||||
|
||||
if (conn->datadgst_en)
|
||||
sdev->request_queue->backing_dev_info->capabilities
|
||||
|= BDI_CAP_STABLE_WRITES;
|
||||
blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
|
||||
blk_queue_dma_alignment(sdev->request_queue, 0);
|
||||
return 0;
|
||||
|
@ -223,6 +223,7 @@ out_done:
|
||||
static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
|
||||
struct domain_device *dev = cmd_to_domain_dev(cmd);
|
||||
struct sas_task *task = TO_SAS_TASK(cmd);
|
||||
|
||||
/* At this point, we only get called following an actual abort
|
||||
@ -231,6 +232,14 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
||||
*/
|
||||
sas_end_task(cmd, task);
|
||||
|
||||
if (dev_is_sata(dev)) {
|
||||
/* defer commands to libata so that libata EH can
|
||||
* handle ata qcs correctly
|
||||
*/
|
||||
list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q);
|
||||
return;
|
||||
}
|
||||
|
||||
/* now finish the command and move it on to the error
|
||||
* handler done list, this also takes it off the
|
||||
* error handler pending list.
|
||||
@ -238,22 +247,6 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
||||
scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
|
||||
}
|
||||
|
||||
static void sas_eh_defer_cmd(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct domain_device *dev = cmd_to_domain_dev(cmd);
|
||||
struct sas_ha_struct *ha = dev->port->ha;
|
||||
struct sas_task *task = TO_SAS_TASK(cmd);
|
||||
|
||||
if (!dev_is_sata(dev)) {
|
||||
sas_eh_finish_cmd(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* report the timeout to libata */
|
||||
sas_end_task(cmd, task);
|
||||
list_move_tail(&cmd->eh_entry, &ha->eh_ata_q);
|
||||
}
|
||||
|
||||
static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd)
|
||||
{
|
||||
struct scsi_cmnd *cmd, *n;
|
||||
@ -261,7 +254,7 @@ static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd
|
||||
list_for_each_entry_safe(cmd, n, error_q, eh_entry) {
|
||||
if (cmd->device->sdev_target == my_cmd->device->sdev_target &&
|
||||
cmd->device->lun == my_cmd->device->lun)
|
||||
sas_eh_defer_cmd(cmd);
|
||||
sas_eh_finish_cmd(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -631,12 +624,12 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
|
||||
case TASK_IS_DONE:
|
||||
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
|
||||
task);
|
||||
sas_eh_defer_cmd(cmd);
|
||||
sas_eh_finish_cmd(cmd);
|
||||
continue;
|
||||
case TASK_IS_ABORTED:
|
||||
SAS_DPRINTK("%s: task 0x%p is aborted\n",
|
||||
__func__, task);
|
||||
sas_eh_defer_cmd(cmd);
|
||||
sas_eh_finish_cmd(cmd);
|
||||
continue;
|
||||
case TASK_IS_AT_LU:
|
||||
SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
|
||||
@ -647,7 +640,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
|
||||
"recovered\n",
|
||||
SAS_ADDR(task->dev),
|
||||
cmd->device->lun);
|
||||
sas_eh_defer_cmd(cmd);
|
||||
sas_eh_finish_cmd(cmd);
|
||||
sas_scsi_clear_queue_lu(work_q, cmd);
|
||||
goto Again;
|
||||
}
|
||||
|
@ -2128,6 +2128,7 @@ enum MR_PD_TYPE {
|
||||
|
||||
struct megasas_instance {
|
||||
|
||||
unsigned int *reply_map;
|
||||
__le32 *producer;
|
||||
dma_addr_t producer_h;
|
||||
__le32 *consumer;
|
||||
|
@ -5164,6 +5164,26 @@ skip_alloc:
|
||||
instance->use_seqnum_jbod_fp = false;
|
||||
}
|
||||
|
||||
static void megasas_setup_reply_map(struct megasas_instance *instance)
|
||||
{
|
||||
const struct cpumask *mask;
|
||||
unsigned int queue, cpu;
|
||||
|
||||
for (queue = 0; queue < instance->msix_vectors; queue++) {
|
||||
mask = pci_irq_get_affinity(instance->pdev, queue);
|
||||
if (!mask)
|
||||
goto fallback;
|
||||
|
||||
for_each_cpu(cpu, mask)
|
||||
instance->reply_map[cpu] = queue;
|
||||
}
|
||||
return;
|
||||
|
||||
fallback:
|
||||
for_each_possible_cpu(cpu)
|
||||
instance->reply_map[cpu] = cpu % instance->msix_vectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* megasas_init_fw - Initializes the FW
|
||||
* @instance: Adapter soft state
|
||||
@ -5342,6 +5362,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
||||
goto fail_setup_irqs;
|
||||
}
|
||||
|
||||
megasas_setup_reply_map(instance);
|
||||
|
||||
dev_info(&instance->pdev->dev,
|
||||
"firmware supports msix\t: (%d)", fw_msix_count);
|
||||
dev_info(&instance->pdev->dev,
|
||||
@ -6122,20 +6144,29 @@ static inline int megasas_alloc_mfi_ctrl_mem(struct megasas_instance *instance)
|
||||
*/
|
||||
static int megasas_alloc_ctrl_mem(struct megasas_instance *instance)
|
||||
{
|
||||
instance->reply_map = kzalloc(sizeof(unsigned int) * nr_cpu_ids,
|
||||
GFP_KERNEL);
|
||||
if (!instance->reply_map)
|
||||
return -ENOMEM;
|
||||
|
||||
switch (instance->adapter_type) {
|
||||
case MFI_SERIES:
|
||||
if (megasas_alloc_mfi_ctrl_mem(instance))
|
||||
return -ENOMEM;
|
||||
goto fail;
|
||||
break;
|
||||
case VENTURA_SERIES:
|
||||
case THUNDERBOLT_SERIES:
|
||||
case INVADER_SERIES:
|
||||
if (megasas_alloc_fusion_context(instance))
|
||||
return -ENOMEM;
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
kfree(instance->reply_map);
|
||||
instance->reply_map = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -6147,6 +6178,7 @@ static int megasas_alloc_ctrl_mem(struct megasas_instance *instance)
|
||||
*/
|
||||
static inline void megasas_free_ctrl_mem(struct megasas_instance *instance)
|
||||
{
|
||||
kfree(instance->reply_map);
|
||||
if (instance->adapter_type == MFI_SERIES) {
|
||||
if (instance->producer)
|
||||
pci_free_consistent(instance->pdev, sizeof(u32),
|
||||
@ -6539,7 +6571,6 @@ fail_io_attach:
|
||||
pci_free_irq_vectors(instance->pdev);
|
||||
fail_init_mfi:
|
||||
scsi_host_put(host);
|
||||
|
||||
fail_alloc_instance:
|
||||
pci_disable_device(pdev);
|
||||
|
||||
@ -6745,6 +6776,8 @@ megasas_resume(struct pci_dev *pdev)
|
||||
if (rval < 0)
|
||||
goto fail_reenable_msix;
|
||||
|
||||
megasas_setup_reply_map(instance);
|
||||
|
||||
if (instance->adapter_type != MFI_SERIES) {
|
||||
megasas_reset_reply_desc(instance);
|
||||
if (megasas_ioc_init_fusion(instance)) {
|
||||
|
@ -216,36 +216,30 @@ inline void megasas_return_cmd_fusion(struct megasas_instance *instance,
|
||||
/**
|
||||
* megasas_fire_cmd_fusion - Sends command to the FW
|
||||
* @instance: Adapter soft state
|
||||
* @req_desc: 32bit or 64bit Request descriptor
|
||||
* @req_desc: 64bit Request descriptor
|
||||
*
|
||||
* Perform PCI Write. Ventura supports 32 bit Descriptor.
|
||||
* Prior to Ventura (12G) MR controller supports 64 bit Descriptor.
|
||||
* Perform PCI Write.
|
||||
*/
|
||||
|
||||
static void
|
||||
megasas_fire_cmd_fusion(struct megasas_instance *instance,
|
||||
union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc)
|
||||
{
|
||||
if (instance->adapter_type == VENTURA_SERIES)
|
||||
writel(le32_to_cpu(req_desc->u.low),
|
||||
&instance->reg_set->inbound_single_queue_port);
|
||||
else {
|
||||
#if defined(writeq) && defined(CONFIG_64BIT)
|
||||
u64 req_data = (((u64)le32_to_cpu(req_desc->u.high) << 32) |
|
||||
le32_to_cpu(req_desc->u.low));
|
||||
u64 req_data = (((u64)le32_to_cpu(req_desc->u.high) << 32) |
|
||||
le32_to_cpu(req_desc->u.low));
|
||||
|
||||
writeq(req_data, &instance->reg_set->inbound_low_queue_port);
|
||||
writeq(req_data, &instance->reg_set->inbound_low_queue_port);
|
||||
#else
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&instance->hba_lock, flags);
|
||||
writel(le32_to_cpu(req_desc->u.low),
|
||||
&instance->reg_set->inbound_low_queue_port);
|
||||
writel(le32_to_cpu(req_desc->u.high),
|
||||
&instance->reg_set->inbound_high_queue_port);
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&instance->hba_lock, flags);
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&instance->hba_lock, flags);
|
||||
writel(le32_to_cpu(req_desc->u.low),
|
||||
&instance->reg_set->inbound_low_queue_port);
|
||||
writel(le32_to_cpu(req_desc->u.high),
|
||||
&instance->reg_set->inbound_high_queue_port);
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&instance->hba_lock, flags);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -982,7 +976,6 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
|
||||
const char *sys_info;
|
||||
MFI_CAPABILITIES *drv_ops;
|
||||
u32 scratch_pad_2;
|
||||
unsigned long flags;
|
||||
ktime_t time;
|
||||
bool cur_fw_64bit_dma_capable;
|
||||
|
||||
@ -1121,14 +1114,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
|
||||
break;
|
||||
}
|
||||
|
||||
/* For Ventura also IOC INIT required 64 bit Descriptor write. */
|
||||
spin_lock_irqsave(&instance->hba_lock, flags);
|
||||
writel(le32_to_cpu(req_desc.u.low),
|
||||
&instance->reg_set->inbound_low_queue_port);
|
||||
writel(le32_to_cpu(req_desc.u.high),
|
||||
&instance->reg_set->inbound_high_queue_port);
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&instance->hba_lock, flags);
|
||||
megasas_fire_cmd_fusion(instance, &req_desc);
|
||||
|
||||
wait_and_poll(instance, cmd, MFI_POLL_TIMEOUT_SECS);
|
||||
|
||||
@ -2655,11 +2641,8 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
|
||||
fp_possible = (io_info.fpOkForIo > 0) ? true : false;
|
||||
}
|
||||
|
||||
/* Use raw_smp_processor_id() for now until cmd->request->cpu is CPU
|
||||
id by default, not CPU group id, otherwise all MSI-X queues won't
|
||||
be utilized */
|
||||
cmd->request_desc->SCSIIO.MSIxIndex = instance->msix_vectors ?
|
||||
raw_smp_processor_id() % instance->msix_vectors : 0;
|
||||
cmd->request_desc->SCSIIO.MSIxIndex =
|
||||
instance->reply_map[raw_smp_processor_id()];
|
||||
|
||||
praid_context = &io_request->RaidContext;
|
||||
|
||||
@ -2985,10 +2968,9 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
|
||||
}
|
||||
|
||||
cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
|
||||
cmd->request_desc->SCSIIO.MSIxIndex =
|
||||
instance->msix_vectors ?
|
||||
(raw_smp_processor_id() % instance->msix_vectors) : 0;
|
||||
|
||||
cmd->request_desc->SCSIIO.MSIxIndex =
|
||||
instance->reply_map[raw_smp_processor_id()];
|
||||
|
||||
if (!fp_possible) {
|
||||
/* system pd firmware path */
|
||||
|
@ -2774,8 +2774,11 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
|
||||
continue;
|
||||
}
|
||||
|
||||
for_each_cpu(cpu, mask)
|
||||
for_each_cpu_and(cpu, mask, cpu_online_mask) {
|
||||
if (cpu >= ioc->cpu_msix_table_sz)
|
||||
break;
|
||||
ioc->cpu_msix_table[cpu] = reply_q->msix_index;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -6637,14 +6640,14 @@ _base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
|
||||
}
|
||||
|
||||
/**
|
||||
* _wait_for_commands_to_complete - reset controller
|
||||
* mpt3sas_wait_for_commands_to_complete - reset controller
|
||||
* @ioc: Pointer to MPT_ADAPTER structure
|
||||
*
|
||||
* This function is waiting 10s for all pending commands to complete
|
||||
* prior to putting controller in reset.
|
||||
*/
|
||||
static void
|
||||
_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc)
|
||||
void
|
||||
mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc)
|
||||
{
|
||||
u32 ioc_state;
|
||||
|
||||
@ -6717,7 +6720,7 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
|
||||
is_fault = 1;
|
||||
}
|
||||
_base_reset_handler(ioc, MPT3_IOC_PRE_RESET);
|
||||
_wait_for_commands_to_complete(ioc);
|
||||
mpt3sas_wait_for_commands_to_complete(ioc);
|
||||
_base_mask_interrupts(ioc);
|
||||
r = _base_make_ioc_ready(ioc, type);
|
||||
if (r)
|
||||
|
@ -1440,6 +1440,9 @@ void mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
||||
int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc);
|
||||
|
||||
void
|
||||
mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc);
|
||||
|
||||
|
||||
/* scsih shared API */
|
||||
struct scsi_cmnd *mpt3sas_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc,
|
||||
|
@ -2835,7 +2835,8 @@ scsih_abort(struct scsi_cmnd *scmd)
|
||||
_scsih_tm_display_info(ioc, scmd);
|
||||
|
||||
sas_device_priv_data = scmd->device->hostdata;
|
||||
if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
|
||||
if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
|
||||
ioc->remove_host) {
|
||||
sdev_printk(KERN_INFO, scmd->device,
|
||||
"device been deleted! scmd(%p)\n", scmd);
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
@ -2898,7 +2899,8 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
|
||||
_scsih_tm_display_info(ioc, scmd);
|
||||
|
||||
sas_device_priv_data = scmd->device->hostdata;
|
||||
if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
|
||||
if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
|
||||
ioc->remove_host) {
|
||||
sdev_printk(KERN_INFO, scmd->device,
|
||||
"device been deleted! scmd(%p)\n", scmd);
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
@ -2961,7 +2963,8 @@ scsih_target_reset(struct scsi_cmnd *scmd)
|
||||
_scsih_tm_display_info(ioc, scmd);
|
||||
|
||||
sas_device_priv_data = scmd->device->hostdata;
|
||||
if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
|
||||
if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
|
||||
ioc->remove_host) {
|
||||
starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n",
|
||||
scmd);
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
@ -3019,7 +3022,7 @@ scsih_host_reset(struct scsi_cmnd *scmd)
|
||||
ioc->name, scmd);
|
||||
scsi_print_command(scmd);
|
||||
|
||||
if (ioc->is_driver_loading) {
|
||||
if (ioc->is_driver_loading || ioc->remove_host) {
|
||||
pr_info(MPT3SAS_FMT "Blocking the host reset\n",
|
||||
ioc->name);
|
||||
r = FAILED;
|
||||
@ -4453,7 +4456,7 @@ _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
|
||||
st = scsi_cmd_priv(scmd);
|
||||
mpt3sas_base_clear_st(ioc, st);
|
||||
scsi_dma_unmap(scmd);
|
||||
if (ioc->pci_error_recovery)
|
||||
if (ioc->pci_error_recovery || ioc->remove_host)
|
||||
scmd->result = DID_NO_CONNECT << 16;
|
||||
else
|
||||
scmd->result = DID_RESET << 16;
|
||||
@ -9739,6 +9742,10 @@ static void scsih_remove(struct pci_dev *pdev)
|
||||
unsigned long flags;
|
||||
|
||||
ioc->remove_host = 1;
|
||||
|
||||
mpt3sas_wait_for_commands_to_complete(ioc);
|
||||
_scsih_flush_running_cmds(ioc);
|
||||
|
||||
_scsih_fw_event_cleanup_queue(ioc);
|
||||
|
||||
spin_lock_irqsave(&ioc->fw_event_lock, flags);
|
||||
@ -9815,6 +9822,10 @@ scsih_shutdown(struct pci_dev *pdev)
|
||||
unsigned long flags;
|
||||
|
||||
ioc->remove_host = 1;
|
||||
|
||||
mpt3sas_wait_for_commands_to_complete(ioc);
|
||||
_scsih_flush_running_cmds(ioc);
|
||||
|
||||
_scsih_fw_event_cleanup_queue(ioc);
|
||||
|
||||
spin_lock_irqsave(&ioc->fw_event_lock, flags);
|
||||
@ -10563,7 +10574,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
|
||||
"fw_event_%s%d", ioc->driver_name, ioc->id);
|
||||
ioc->firmware_event_thread = alloc_ordered_workqueue(
|
||||
ioc->firmware_event_name, WQ_MEM_RECLAIM);
|
||||
ioc->firmware_event_name, 0);
|
||||
if (!ioc->firmware_event_thread) {
|
||||
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
|
@ -762,6 +762,11 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi,
|
||||
|
||||
iscsi_cid = cqe->conn_id;
|
||||
qedi_conn = qedi->cid_que.conn_cid_tbl[iscsi_cid];
|
||||
if (!qedi_conn) {
|
||||
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
|
||||
"icid not found 0x%x\n", cqe->conn_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Based on this itt get the corresponding qedi_cmd */
|
||||
spin_lock_bh(&qedi_conn->tmf_work_lock);
|
||||
|
@ -1724,7 +1724,6 @@ static ssize_t qedi_show_boot_eth_info(void *data, int type, char *buf)
|
||||
{
|
||||
struct qedi_ctx *qedi = data;
|
||||
struct nvm_iscsi_initiator *initiator;
|
||||
char *str = buf;
|
||||
int rc = 1;
|
||||
u32 ipv6_en, dhcp_en, ip_len;
|
||||
struct nvm_iscsi_block *block;
|
||||
@ -1758,32 +1757,32 @@ static ssize_t qedi_show_boot_eth_info(void *data, int type, char *buf)
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_ETH_IP_ADDR:
|
||||
rc = snprintf(str, ip_len, fmt, ip);
|
||||
rc = snprintf(buf, ip_len, fmt, ip);
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_SUBNET_MASK:
|
||||
rc = snprintf(str, ip_len, fmt, sub);
|
||||
rc = snprintf(buf, ip_len, fmt, sub);
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_GATEWAY:
|
||||
rc = snprintf(str, ip_len, fmt, gw);
|
||||
rc = snprintf(buf, ip_len, fmt, gw);
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_FLAGS:
|
||||
rc = snprintf(str, 3, "%hhd\n",
|
||||
rc = snprintf(buf, 3, "%hhd\n",
|
||||
SYSFS_FLAG_FW_SEL_BOOT);
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_INDEX:
|
||||
rc = snprintf(str, 3, "0\n");
|
||||
rc = snprintf(buf, 3, "0\n");
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_MAC:
|
||||
rc = sysfs_format_mac(str, qedi->mac, ETH_ALEN);
|
||||
rc = sysfs_format_mac(buf, qedi->mac, ETH_ALEN);
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_VLAN:
|
||||
rc = snprintf(str, 12, "%d\n",
|
||||
rc = snprintf(buf, 12, "%d\n",
|
||||
GET_FIELD2(initiator->generic_cont0,
|
||||
NVM_ISCSI_CFG_INITIATOR_VLAN));
|
||||
break;
|
||||
case ISCSI_BOOT_ETH_ORIGIN:
|
||||
if (dhcp_en)
|
||||
rc = snprintf(str, 3, "3\n");
|
||||
rc = snprintf(buf, 3, "3\n");
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
@ -1819,7 +1818,6 @@ static ssize_t qedi_show_boot_ini_info(void *data, int type, char *buf)
|
||||
{
|
||||
struct qedi_ctx *qedi = data;
|
||||
struct nvm_iscsi_initiator *initiator;
|
||||
char *str = buf;
|
||||
int rc;
|
||||
struct nvm_iscsi_block *block;
|
||||
|
||||
@ -1831,8 +1829,8 @@ static ssize_t qedi_show_boot_ini_info(void *data, int type, char *buf)
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_INI_INITIATOR_NAME:
|
||||
rc = snprintf(str, NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN, "%s\n",
|
||||
initiator->initiator_name.byte);
|
||||
rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN,
|
||||
initiator->initiator_name.byte);
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
@ -1860,7 +1858,6 @@ static ssize_t
|
||||
qedi_show_boot_tgt_info(struct qedi_ctx *qedi, int type,
|
||||
char *buf, enum qedi_nvm_tgts idx)
|
||||
{
|
||||
char *str = buf;
|
||||
int rc = 1;
|
||||
u32 ctrl_flags, ipv6_en, chap_en, mchap_en, ip_len;
|
||||
struct nvm_iscsi_block *block;
|
||||
@ -1899,48 +1896,48 @@ qedi_show_boot_tgt_info(struct qedi_ctx *qedi, int type,
|
||||
|
||||
switch (type) {
|
||||
case ISCSI_BOOT_TGT_NAME:
|
||||
rc = snprintf(str, NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN, "%s\n",
|
||||
block->target[idx].target_name.byte);
|
||||
rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN,
|
||||
block->target[idx].target_name.byte);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_IP_ADDR:
|
||||
if (ipv6_en)
|
||||
rc = snprintf(str, ip_len, "%pI6\n",
|
||||
rc = snprintf(buf, ip_len, "%pI6\n",
|
||||
block->target[idx].ipv6_addr.byte);
|
||||
else
|
||||
rc = snprintf(str, ip_len, "%pI4\n",
|
||||
rc = snprintf(buf, ip_len, "%pI4\n",
|
||||
block->target[idx].ipv4_addr.byte);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_PORT:
|
||||
rc = snprintf(str, 12, "%d\n",
|
||||
rc = snprintf(buf, 12, "%d\n",
|
||||
GET_FIELD2(block->target[idx].generic_cont0,
|
||||
NVM_ISCSI_CFG_TARGET_TCP_PORT));
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_LUN:
|
||||
rc = snprintf(str, 22, "%.*d\n",
|
||||
rc = snprintf(buf, 22, "%.*d\n",
|
||||
block->target[idx].lun.value[1],
|
||||
block->target[idx].lun.value[0]);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_CHAP_NAME:
|
||||
rc = snprintf(str, NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN, "%s\n",
|
||||
chap_name);
|
||||
rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
|
||||
chap_name);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_CHAP_SECRET:
|
||||
rc = snprintf(str, NVM_ISCSI_CFG_CHAP_PWD_MAX_LEN, "%s\n",
|
||||
chap_secret);
|
||||
rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
|
||||
chap_secret);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_REV_CHAP_NAME:
|
||||
rc = snprintf(str, NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN, "%s\n",
|
||||
mchap_name);
|
||||
rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
|
||||
mchap_name);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
|
||||
rc = snprintf(str, NVM_ISCSI_CFG_CHAP_PWD_MAX_LEN, "%s\n",
|
||||
mchap_secret);
|
||||
rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
|
||||
mchap_secret);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_FLAGS:
|
||||
rc = snprintf(str, 3, "%hhd\n", SYSFS_FLAG_FW_SEL_BOOT);
|
||||
rc = snprintf(buf, 3, "%hhd\n", SYSFS_FLAG_FW_SEL_BOOT);
|
||||
break;
|
||||
case ISCSI_BOOT_TGT_NIC_ASSOC:
|
||||
rc = snprintf(str, 3, "0\n");
|
||||
rc = snprintf(buf, 3, "0\n");
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* | Module Init and Probe | 0x0193 | 0x0146 |
|
||||
* | | | 0x015b-0x0160 |
|
||||
* | | | 0x016e |
|
||||
* | Mailbox commands | 0x1205 | 0x11a2-0x11ff |
|
||||
* | Mailbox commands | 0x1206 | 0x11a2-0x11ff |
|
||||
* | Device Discovery | 0x2134 | 0x210e-0x2116 |
|
||||
* | | | 0x211a |
|
||||
* | | | 0x211c-0x2128 |
|
||||
|
@ -261,9 +261,9 @@
|
||||
struct name_list_extended {
|
||||
struct get_name_list_extended *l;
|
||||
dma_addr_t ldma;
|
||||
struct list_head fcports; /* protect by sess_list */
|
||||
struct list_head fcports;
|
||||
spinlock_t fcports_lock;
|
||||
u32 size;
|
||||
u8 sent;
|
||||
};
|
||||
/*
|
||||
* Timeout timer counts in seconds
|
||||
|
@ -3177,6 +3177,7 @@ done_free_sp:
|
||||
sp->free(sp);
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_ACTIVE;
|
||||
return rval;
|
||||
}
|
||||
|
||||
@ -3368,6 +3369,7 @@ done_free_sp:
|
||||
sp->free(sp);
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_ACTIVE;
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,6 @@ qla2x00_sp_timeout(struct timer_list *t)
|
||||
req->outstanding_cmds[sp->handle] = NULL;
|
||||
iocb = &sp->u.iocb_cmd;
|
||||
iocb->timeout(sp);
|
||||
if (sp->type != SRB_ELS_DCMD)
|
||||
sp->free(sp);
|
||||
spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
|
||||
}
|
||||
|
||||
@ -102,7 +100,6 @@ qla2x00_async_iocb_timeout(void *data)
|
||||
srb_t *sp = data;
|
||||
fc_port_t *fcport = sp->fcport;
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
struct event_arg ea;
|
||||
|
||||
if (fcport) {
|
||||
ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
|
||||
@ -117,25 +114,13 @@ qla2x00_async_iocb_timeout(void *data)
|
||||
|
||||
switch (sp->type) {
|
||||
case SRB_LOGIN_CMD:
|
||||
if (!fcport)
|
||||
break;
|
||||
/* Retry as needed. */
|
||||
lio->u.logio.data[0] = MBS_COMMAND_ERROR;
|
||||
lio->u.logio.data[1] = lio->u.logio.flags & SRB_LOGIN_RETRIED ?
|
||||
QLA_LOGIO_LOGIN_RETRIED : 0;
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.event = FCME_PLOGI_DONE;
|
||||
ea.fcport = sp->fcport;
|
||||
ea.data[0] = lio->u.logio.data[0];
|
||||
ea.data[1] = lio->u.logio.data[1];
|
||||
ea.sp = sp;
|
||||
qla24xx_handle_plogi_done_event(fcport->vha, &ea);
|
||||
sp->done(sp, QLA_FUNCTION_TIMEOUT);
|
||||
break;
|
||||
case SRB_LOGOUT_CMD:
|
||||
if (!fcport)
|
||||
break;
|
||||
qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
|
||||
break;
|
||||
case SRB_CT_PTHRU_CMD:
|
||||
case SRB_MB_IOCB:
|
||||
case SRB_NACK_PLOGI:
|
||||
@ -228,6 +213,7 @@ done_free_sp:
|
||||
sp->free(sp);
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_ACTIVE;
|
||||
return rval;
|
||||
}
|
||||
|
||||
@ -235,12 +221,10 @@ static void
|
||||
qla2x00_async_logout_sp_done(void *ptr, int res)
|
||||
{
|
||||
srb_t *sp = ptr;
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
|
||||
sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
|
||||
if (!test_bit(UNLOADING, &sp->vha->dpc_flags))
|
||||
qla2x00_post_async_logout_done_work(sp->vha, sp->fcport,
|
||||
lio->u.logio.data);
|
||||
sp->fcport->login_gen++;
|
||||
qlt_logo_completion_handler(sp->fcport, res);
|
||||
sp->free(sp);
|
||||
}
|
||||
|
||||
@ -280,7 +264,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
done_free_sp:
|
||||
sp->free(sp);
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
|
||||
return rval;
|
||||
}
|
||||
|
||||
@ -288,6 +272,7 @@ void
|
||||
qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
|
||||
uint16_t *data)
|
||||
{
|
||||
fcport->flags &= ~FCF_ASYNC_ACTIVE;
|
||||
/* Don't re-login in target mode */
|
||||
if (!fcport->tgt_session)
|
||||
qla2x00_mark_device_lost(vha, fcport, 1, 0);
|
||||
@ -301,6 +286,7 @@ qla2x00_async_prlo_sp_done(void *s, int res)
|
||||
struct srb_iocb *lio = &sp->u.iocb_cmd;
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
|
||||
sp->fcport->flags &= ~FCF_ASYNC_ACTIVE;
|
||||
if (!test_bit(UNLOADING, &vha->dpc_flags))
|
||||
qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
|
||||
lio->u.logio.data);
|
||||
@ -339,6 +325,7 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
done_free_sp:
|
||||
sp->free(sp);
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_ACTIVE;
|
||||
return rval;
|
||||
}
|
||||
|
||||
@ -392,6 +379,8 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
|
||||
"Async done-%s res %x %8phC\n",
|
||||
sp->name, res, sp->fcport->port_name);
|
||||
|
||||
sp->fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.event = FCME_ADISC_DONE;
|
||||
ea.rc = res;
|
||||
@ -442,7 +431,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
|
||||
done_free_sp:
|
||||
sp->free(sp);
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
|
||||
qla2x00_post_async_adisc_work(vha, fcport, data);
|
||||
return rval;
|
||||
}
|
||||
@ -660,8 +649,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
|
||||
(loop_id & 0x7fff));
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
||||
vha->gnl.sent = 0;
|
||||
spin_lock_irqsave(&vha->gnl.fcports_lock, flags);
|
||||
|
||||
INIT_LIST_HEAD(&h);
|
||||
fcport = tf = NULL;
|
||||
@ -670,12 +658,16 @@ qla24xx_async_gnl_sp_done(void *s, int res)
|
||||
|
||||
list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
|
||||
list_del_init(&fcport->gnl_entry);
|
||||
spin_lock(&vha->hw->tgt.sess_lock);
|
||||
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
|
||||
spin_unlock(&vha->hw->tgt.sess_lock);
|
||||
ea.fcport = fcport;
|
||||
|
||||
qla2x00_fcport_event_handler(vha, &ea);
|
||||
}
|
||||
spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
||||
/* create new fcport if fw has knowledge of new sessions */
|
||||
for (i = 0; i < n; i++) {
|
||||
port_id_t id;
|
||||
@ -727,18 +719,21 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
ql_dbg(ql_dbg_disc, vha, 0x20d9,
|
||||
"Async-gnlist WWPN %8phC \n", fcport->port_name);
|
||||
|
||||
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
||||
spin_lock_irqsave(&vha->gnl.fcports_lock, flags);
|
||||
if (!list_empty(&fcport->gnl_entry)) {
|
||||
spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
|
||||
rval = QLA_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
spin_lock(&vha->hw->tgt.sess_lock);
|
||||
fcport->disc_state = DSC_GNL;
|
||||
fcport->last_rscn_gen = fcport->rscn_gen;
|
||||
fcport->last_login_gen = fcport->login_gen;
|
||||
spin_unlock(&vha->hw->tgt.sess_lock);
|
||||
|
||||
list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports);
|
||||
if (vha->gnl.sent) {
|
||||
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
|
||||
return QLA_SUCCESS;
|
||||
}
|
||||
vha->gnl.sent = 1;
|
||||
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
|
||||
spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
|
||||
|
||||
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
|
||||
if (!sp)
|
||||
@ -1065,6 +1060,7 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
|
||||
fc_port_t *fcport = ea->fcport;
|
||||
struct port_database_24xx *pd;
|
||||
struct srb *sp = ea->sp;
|
||||
uint8_t ls;
|
||||
|
||||
pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
|
||||
|
||||
@ -1077,7 +1073,12 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
|
||||
if (fcport->disc_state == DSC_DELETE_PEND)
|
||||
return;
|
||||
|
||||
switch (pd->current_login_state) {
|
||||
if (fcport->fc4f_nvme)
|
||||
ls = pd->current_login_state >> 4;
|
||||
else
|
||||
ls = pd->current_login_state & 0xf;
|
||||
|
||||
switch (ls) {
|
||||
case PDS_PRLI_COMPLETE:
|
||||
__qla24xx_parse_gpdb(vha, fcport, pd);
|
||||
break;
|
||||
@ -1167,8 +1168,9 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
|
||||
if (fcport->scan_state != QLA_FCPORT_FOUND)
|
||||
return 0;
|
||||
|
||||
if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
|
||||
(fcport->fw_login_state == DSC_LS_PRLI_PEND))
|
||||
if ((fcport->loop_id != FC_NO_LOOP_ID) &&
|
||||
((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
|
||||
(fcport->fw_login_state == DSC_LS_PRLI_PEND)))
|
||||
return 0;
|
||||
|
||||
if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
|
||||
@ -1548,6 +1550,7 @@ qla24xx_abort_sp_done(void *ptr, int res)
|
||||
srb_t *sp = ptr;
|
||||
struct srb_iocb *abt = &sp->u.iocb_cmd;
|
||||
|
||||
del_timer(&sp->u.iocb_cmd.timer);
|
||||
complete(&abt->u.abt.comp);
|
||||
}
|
||||
|
||||
@ -1727,7 +1730,6 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
|
||||
|
||||
set_bit(ea->fcport->loop_id, vha->hw->loop_id_map);
|
||||
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
||||
ea->fcport->loop_id = FC_NO_LOOP_ID;
|
||||
ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
|
||||
ea->fcport->logout_on_delete = 1;
|
||||
ea->fcport->send_els_logo = 0;
|
||||
@ -1819,6 +1821,7 @@ qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
|
||||
qla2x00_mark_device_lost(vha, fcport, 1, 0);
|
||||
qlt_logo_completion_handler(fcport, data[0]);
|
||||
fcport->login_gen++;
|
||||
fcport->flags &= ~FCF_ASYNC_ACTIVE;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1826,6 +1829,7 @@ void
|
||||
qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
|
||||
uint16_t *data)
|
||||
{
|
||||
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
|
||||
if (data[0] == MBS_COMMAND_COMPLETE) {
|
||||
qla2x00_update_fcport(vha, fcport);
|
||||
|
||||
@ -1833,7 +1837,6 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
|
||||
}
|
||||
|
||||
/* Retry login. */
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
|
||||
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
|
||||
else
|
||||
|
@ -3276,12 +3276,11 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
|
||||
memset(abt_iocb, 0, sizeof(struct abort_entry_24xx));
|
||||
abt_iocb->entry_type = ABORT_IOCB_TYPE;
|
||||
abt_iocb->entry_count = 1;
|
||||
abt_iocb->handle =
|
||||
cpu_to_le32(MAKE_HANDLE(aio->u.abt.req_que_no,
|
||||
aio->u.abt.cmd_hndl));
|
||||
abt_iocb->handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle));
|
||||
abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
|
||||
abt_iocb->handle_to_abort =
|
||||
cpu_to_le32(MAKE_HANDLE(req->id, aio->u.abt.cmd_hndl));
|
||||
cpu_to_le32(MAKE_HANDLE(aio->u.abt.req_que_no,
|
||||
aio->u.abt.cmd_hndl));
|
||||
abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
|
||||
abt_iocb->port_id[1] = sp->fcport->d_id.b.area;
|
||||
abt_iocb->port_id[2] = sp->fcport->d_id.b.domain;
|
||||
|
@ -272,7 +272,8 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
/* Read all mbox registers? */
|
||||
mboxes = (1 << ha->mbx_count) - 1;
|
||||
WARN_ON_ONCE(ha->mbx_count > 32);
|
||||
mboxes = (1ULL << ha->mbx_count) - 1;
|
||||
if (!ha->mcp)
|
||||
ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n");
|
||||
else
|
||||
@ -2862,7 +2863,8 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
|
||||
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||
|
||||
/* Read all mbox registers? */
|
||||
mboxes = (1 << ha->mbx_count) - 1;
|
||||
WARN_ON_ONCE(ha->mbx_count > 32);
|
||||
mboxes = (1ULL << ha->mbx_count) - 1;
|
||||
if (!ha->mcp)
|
||||
ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERROR.\n");
|
||||
else
|
||||
|
@ -503,11 +503,19 @@ mbx_done:
|
||||
}
|
||||
pr_warn(" cmd=%x ****\n", command);
|
||||
}
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x1198,
|
||||
"host_status=%#x intr_ctrl=%#x intr_status=%#x\n",
|
||||
RD_REG_DWORD(®->isp24.host_status),
|
||||
RD_REG_DWORD(®->isp24.ictrl),
|
||||
RD_REG_DWORD(®->isp24.istatus));
|
||||
if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha))) {
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x1198,
|
||||
"host_status=%#x intr_ctrl=%#x intr_status=%#x\n",
|
||||
RD_REG_DWORD(®->isp24.host_status),
|
||||
RD_REG_DWORD(®->isp24.ictrl),
|
||||
RD_REG_DWORD(®->isp24.istatus));
|
||||
} else {
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x1206,
|
||||
"ctrl_status=%#x ictrl=%#x istatus=%#x\n",
|
||||
RD_REG_WORD(®->isp.ctrl_status),
|
||||
RD_REG_WORD(®->isp.ictrl),
|
||||
RD_REG_WORD(®->isp.istatus));
|
||||
}
|
||||
} else {
|
||||
ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
|
||||
}
|
||||
|
@ -453,7 +453,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
|
||||
ha->req_q_map[0] = req;
|
||||
set_bit(0, ha->rsp_qid_map);
|
||||
set_bit(0, ha->req_qid_map);
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
fail_qpair_map:
|
||||
kfree(ha->base_qpair);
|
||||
@ -470,6 +470,9 @@ fail_req_map:
|
||||
|
||||
static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
|
||||
{
|
||||
if (!ha->req_q_map)
|
||||
return;
|
||||
|
||||
if (IS_QLAFX00(ha)) {
|
||||
if (req && req->ring_fx00)
|
||||
dma_free_coherent(&ha->pdev->dev,
|
||||
@ -480,16 +483,19 @@ static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
|
||||
(req->length + 1) * sizeof(request_t),
|
||||
req->ring, req->dma);
|
||||
|
||||
if (req)
|
||||
if (req) {
|
||||
kfree(req->outstanding_cmds);
|
||||
|
||||
kfree(req);
|
||||
kfree(req);
|
||||
}
|
||||
}
|
||||
|
||||
static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
|
||||
{
|
||||
if (!ha->rsp_q_map)
|
||||
return;
|
||||
|
||||
if (IS_QLAFX00(ha)) {
|
||||
if (rsp && rsp->ring)
|
||||
if (rsp && rsp->ring_fx00)
|
||||
dma_free_coherent(&ha->pdev->dev,
|
||||
(rsp->length_fx00 + 1) * sizeof(request_t),
|
||||
rsp->ring_fx00, rsp->dma_fx00);
|
||||
@ -498,7 +504,8 @@ static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
|
||||
(rsp->length + 1) * sizeof(response_t),
|
||||
rsp->ring, rsp->dma);
|
||||
}
|
||||
kfree(rsp);
|
||||
if (rsp)
|
||||
kfree(rsp);
|
||||
}
|
||||
|
||||
static void qla2x00_free_queues(struct qla_hw_data *ha)
|
||||
@ -1722,6 +1729,8 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
|
||||
struct qla_tgt_cmd *cmd;
|
||||
uint8_t trace = 0;
|
||||
|
||||
if (!ha->req_q_map)
|
||||
return;
|
||||
spin_lock_irqsave(qp->qp_lock_ptr, flags);
|
||||
req = qp->req;
|
||||
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
|
||||
@ -3094,14 +3103,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
/* Set up the irqs */
|
||||
ret = qla2x00_request_irqs(ha, rsp);
|
||||
if (ret)
|
||||
goto probe_hw_failed;
|
||||
goto probe_failed;
|
||||
|
||||
/* Alloc arrays of request and response ring ptrs */
|
||||
if (!qla2x00_alloc_queues(ha, req, rsp)) {
|
||||
if (qla2x00_alloc_queues(ha, req, rsp)) {
|
||||
ql_log(ql_log_fatal, base_vha, 0x003d,
|
||||
"Failed to allocate memory for queue pointers..."
|
||||
"aborting.\n");
|
||||
goto probe_init_failed;
|
||||
goto probe_failed;
|
||||
}
|
||||
|
||||
if (ha->mqenable && shost_use_blk_mq(host)) {
|
||||
@ -3386,15 +3395,6 @@ skip_dpc:
|
||||
|
||||
return 0;
|
||||
|
||||
probe_init_failed:
|
||||
qla2x00_free_req_que(ha, req);
|
||||
ha->req_q_map[0] = NULL;
|
||||
clear_bit(0, ha->req_qid_map);
|
||||
qla2x00_free_rsp_que(ha, rsp);
|
||||
ha->rsp_q_map[0] = NULL;
|
||||
clear_bit(0, ha->rsp_qid_map);
|
||||
ha->max_req_queues = ha->max_rsp_queues = 0;
|
||||
|
||||
probe_failed:
|
||||
if (base_vha->timer_active)
|
||||
qla2x00_stop_timer(base_vha);
|
||||
@ -3624,6 +3624,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
||||
}
|
||||
qla2x00_wait_for_hba_ready(base_vha);
|
||||
|
||||
qla2x00_wait_for_sess_deletion(base_vha);
|
||||
|
||||
/*
|
||||
* if UNLOAD flag is already set, then continue unload,
|
||||
* where it was set first.
|
||||
@ -4505,11 +4507,17 @@ qla2x00_mem_free(struct qla_hw_data *ha)
|
||||
if (ha->init_cb)
|
||||
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
|
||||
ha->init_cb, ha->init_cb_dma);
|
||||
vfree(ha->optrom_buffer);
|
||||
kfree(ha->nvram);
|
||||
kfree(ha->npiv_info);
|
||||
kfree(ha->swl);
|
||||
kfree(ha->loop_id_map);
|
||||
|
||||
if (ha->optrom_buffer)
|
||||
vfree(ha->optrom_buffer);
|
||||
if (ha->nvram)
|
||||
kfree(ha->nvram);
|
||||
if (ha->npiv_info)
|
||||
kfree(ha->npiv_info);
|
||||
if (ha->swl)
|
||||
kfree(ha->swl);
|
||||
if (ha->loop_id_map)
|
||||
kfree(ha->loop_id_map);
|
||||
|
||||
ha->srb_mempool = NULL;
|
||||
ha->ctx_mempool = NULL;
|
||||
@ -4525,6 +4533,15 @@ qla2x00_mem_free(struct qla_hw_data *ha)
|
||||
ha->ex_init_cb_dma = 0;
|
||||
ha->async_pd = NULL;
|
||||
ha->async_pd_dma = 0;
|
||||
ha->loop_id_map = NULL;
|
||||
ha->npiv_info = NULL;
|
||||
ha->optrom_buffer = NULL;
|
||||
ha->swl = NULL;
|
||||
ha->nvram = NULL;
|
||||
ha->mctp_dump = NULL;
|
||||
ha->dcbx_tlv = NULL;
|
||||
ha->xgmac_data = NULL;
|
||||
ha->sfp_data = NULL;
|
||||
|
||||
ha->s_dma_pool = NULL;
|
||||
ha->dl_dma_pool = NULL;
|
||||
@ -4574,6 +4591,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
|
||||
|
||||
spin_lock_init(&vha->work_lock);
|
||||
spin_lock_init(&vha->cmd_list_lock);
|
||||
spin_lock_init(&vha->gnl.fcports_lock);
|
||||
init_waitqueue_head(&vha->fcport_waitQ);
|
||||
init_waitqueue_head(&vha->vref_waitq);
|
||||
|
||||
@ -4879,6 +4897,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
|
||||
}
|
||||
qlt_plogi_ack_unref(vha, pla);
|
||||
} else {
|
||||
fc_port_t *dfcp = NULL;
|
||||
|
||||
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
||||
tfcp = qla2x00_find_fcport_by_nportid(vha,
|
||||
&e->u.new_sess.id, 1);
|
||||
@ -4901,11 +4921,13 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
|
||||
default:
|
||||
fcport->login_pause = 1;
|
||||
tfcp->conflict = fcport;
|
||||
qlt_schedule_sess_for_deletion(tfcp);
|
||||
dfcp = tfcp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
|
||||
if (dfcp)
|
||||
qlt_schedule_sess_for_deletion(tfcp);
|
||||
|
||||
wwn = wwn_to_u64(fcport->node_name);
|
||||
|
||||
|
@ -1227,10 +1227,10 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess)
|
||||
}
|
||||
}
|
||||
|
||||
/* ha->tgt.sess_lock supposed to be held on entry */
|
||||
void qlt_schedule_sess_for_deletion(struct fc_port *sess)
|
||||
{
|
||||
struct qla_tgt *tgt = sess->tgt;
|
||||
struct qla_hw_data *ha = sess->vha->hw;
|
||||
unsigned long flags;
|
||||
|
||||
if (sess->disc_state == DSC_DELETE_PEND)
|
||||
@ -1247,16 +1247,16 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||
if (sess->deleted == QLA_SESS_DELETED)
|
||||
sess->logout_on_delete = 0;
|
||||
|
||||
spin_lock_irqsave(&sess->vha->work_lock, flags);
|
||||
if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
|
||||
spin_unlock_irqrestore(&sess->vha->work_lock, flags);
|
||||
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||
return;
|
||||
}
|
||||
sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
|
||||
spin_unlock_irqrestore(&sess->vha->work_lock, flags);
|
||||
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||
|
||||
sess->disc_state = DSC_DELETE_PEND;
|
||||
|
||||
@ -1265,13 +1265,10 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
|
||||
ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
|
||||
"Scheduling sess %p for deletion\n", sess);
|
||||
|
||||
/* use cancel to push work element through before re-queue */
|
||||
cancel_work_sync(&sess->del_work);
|
||||
INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn);
|
||||
queue_work(sess->vha->hw->wq, &sess->del_work);
|
||||
WARN_ON(!queue_work(sess->vha->hw->wq, &sess->del_work));
|
||||
}
|
||||
|
||||
/* ha->tgt.sess_lock supposed to be held on entry */
|
||||
static void qlt_clear_tgt_db(struct qla_tgt *tgt)
|
||||
{
|
||||
struct fc_port *sess;
|
||||
@ -1454,8 +1451,8 @@ qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
|
||||
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess);
|
||||
|
||||
sess->local = 1;
|
||||
qlt_schedule_sess_for_deletion(sess);
|
||||
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
|
||||
qlt_schedule_sess_for_deletion(sess);
|
||||
}
|
||||
|
||||
static inline int test_tgt_sess_count(struct qla_tgt *tgt)
|
||||
@ -1515,10 +1512,8 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
|
||||
* Lock is needed, because we still can get an incoming packet.
|
||||
*/
|
||||
mutex_lock(&vha->vha_tgt.tgt_mutex);
|
||||
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||
tgt->tgt_stop = 1;
|
||||
qlt_clear_tgt_db(tgt);
|
||||
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||
mutex_unlock(&vha->vha_tgt.tgt_mutex);
|
||||
mutex_unlock(&qla_tgt_mutex);
|
||||
|
||||
@ -4869,8 +4864,6 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
|
||||
sess);
|
||||
qlt_send_term_imm_notif(vha, iocb, 1);
|
||||
res = 0;
|
||||
spin_lock_irqsave(&tgt->ha->tgt.sess_lock,
|
||||
flags);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,8 @@
|
||||
#define DEV_DB_NON_PERSISTENT 0
|
||||
#define DEV_DB_PERSISTENT 1
|
||||
|
||||
#define QL4_ISP_REG_DISCONNECT 0xffffffffU
|
||||
|
||||
#define COPY_ISID(dst_isid, src_isid) { \
|
||||
int i, j; \
|
||||
for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \
|
||||
|
@ -262,6 +262,24 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
|
||||
|
||||
static struct scsi_transport_template *qla4xxx_scsi_transport;
|
||||
|
||||
static int qla4xxx_isp_check_reg(struct scsi_qla_host *ha)
|
||||
{
|
||||
u32 reg_val = 0;
|
||||
int rval = QLA_SUCCESS;
|
||||
|
||||
if (is_qla8022(ha))
|
||||
reg_val = readl(&ha->qla4_82xx_reg->host_status);
|
||||
else if (is_qla8032(ha) || is_qla8042(ha))
|
||||
reg_val = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER);
|
||||
else
|
||||
reg_val = readw(&ha->reg->ctrl_status);
|
||||
|
||||
if (reg_val == QL4_ISP_REG_DISCONNECT)
|
||||
rval = QLA_ERROR;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,
|
||||
uint32_t iface_type, uint32_t payload_size,
|
||||
uint32_t pid, struct sockaddr *dst_addr)
|
||||
@ -9184,10 +9202,17 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
|
||||
struct srb *srb = NULL;
|
||||
int ret = SUCCESS;
|
||||
int wait = 0;
|
||||
int rval;
|
||||
|
||||
ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n",
|
||||
ha->host_no, id, lun, cmd, cmd->cmnd[0]);
|
||||
|
||||
rval = qla4xxx_isp_check_reg(ha);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
srb = (struct srb *) CMD_SP(cmd);
|
||||
if (!srb) {
|
||||
@ -9239,6 +9264,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
||||
struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
|
||||
struct ddb_entry *ddb_entry = cmd->device->hostdata;
|
||||
int ret = FAILED, stat;
|
||||
int rval;
|
||||
|
||||
if (!ddb_entry)
|
||||
return ret;
|
||||
@ -9258,6 +9284,12 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
||||
cmd, jiffies, cmd->request->timeout / HZ,
|
||||
ha->dpc_flags, cmd->result, cmd->allowed));
|
||||
|
||||
rval = qla4xxx_isp_check_reg(ha);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* FIXME: wait for hba to go online */
|
||||
stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);
|
||||
if (stat != QLA_SUCCESS) {
|
||||
@ -9301,6 +9333,7 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
|
||||
struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
|
||||
struct ddb_entry *ddb_entry = cmd->device->hostdata;
|
||||
int stat, ret;
|
||||
int rval;
|
||||
|
||||
if (!ddb_entry)
|
||||
return FAILED;
|
||||
@ -9318,6 +9351,12 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
|
||||
ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
|
||||
ha->dpc_flags, cmd->result, cmd->allowed));
|
||||
|
||||
rval = qla4xxx_isp_check_reg(ha);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
stat = qla4xxx_reset_target(ha, ddb_entry);
|
||||
if (stat != QLA_SUCCESS) {
|
||||
starget_printk(KERN_INFO, scsi_target(cmd->device),
|
||||
@ -9372,9 +9411,16 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
int return_status = FAILED;
|
||||
struct scsi_qla_host *ha;
|
||||
int rval;
|
||||
|
||||
ha = to_qla_host(cmd->device->host);
|
||||
|
||||
rval = qla4xxx_isp_check_reg(ha);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if ((is_qla8032(ha) || is_qla8042(ha)) && ql4xdontresethba)
|
||||
qla4_83xx_set_idc_dontreset(ha);
|
||||
|
||||
|
@ -229,7 +229,8 @@ static void scsi_eh_reset(struct scsi_cmnd *scmd)
|
||||
|
||||
static void scsi_eh_inc_host_failed(struct rcu_head *head)
|
||||
{
|
||||
struct Scsi_Host *shost = container_of(head, typeof(*shost), rcu);
|
||||
struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
|
||||
struct Scsi_Host *shost = scmd->device->host;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
@ -265,7 +266,7 @@ void scsi_eh_scmd_add(struct scsi_cmnd *scmd)
|
||||
* Ensure that all tasks observe the host state change before the
|
||||
* host_failed change.
|
||||
*/
|
||||
call_rcu(&shost->rcu, scsi_eh_inc_host_failed);
|
||||
call_rcu(&scmd->rcu, scsi_eh_inc_host_failed);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -683,6 +683,7 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
|
||||
if (!blk_rq_is_scsi(req)) {
|
||||
WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
|
||||
cmd->flags &= ~SCMD_INITIALIZED;
|
||||
destroy_rcu_head(&cmd->rcu);
|
||||
}
|
||||
|
||||
if (req->mq_ctx) {
|
||||
@ -732,6 +733,8 @@ static blk_status_t __scsi_error_from_host_byte(struct scsi_cmnd *cmd,
|
||||
int result)
|
||||
{
|
||||
switch (host_byte(result)) {
|
||||
case DID_OK:
|
||||
return BLK_STS_OK;
|
||||
case DID_TRANSPORT_FAILFAST:
|
||||
return BLK_STS_TRANSPORT;
|
||||
case DID_TARGET_FAILURE:
|
||||
@ -1174,6 +1177,7 @@ static void scsi_initialize_rq(struct request *rq)
|
||||
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
|
||||
|
||||
scsi_req_init(&cmd->req);
|
||||
init_rcu_head(&cmd->rcu);
|
||||
cmd->jiffies_at_alloc = jiffies;
|
||||
cmd->retries = 0;
|
||||
}
|
||||
|
@ -2484,6 +2484,8 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
|
||||
sector_size = old_sector_size;
|
||||
goto got_data;
|
||||
}
|
||||
/* Remember that READ CAPACITY(16) succeeded */
|
||||
sdp->try_rc_10_first = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2595,6 +2597,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
|
||||
int res;
|
||||
struct scsi_device *sdp = sdkp->device;
|
||||
struct scsi_mode_data data;
|
||||
int disk_ro = get_disk_ro(sdkp->disk);
|
||||
int old_wp = sdkp->write_prot;
|
||||
|
||||
set_disk_ro(sdkp->disk, 0);
|
||||
@ -2635,7 +2638,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
|
||||
"Test WP failed, assume Write Enabled\n");
|
||||
} else {
|
||||
sdkp->write_prot = ((data.device_specific & 0x80) != 0);
|
||||
set_disk_ro(sdkp->disk, sdkp->write_prot);
|
||||
set_disk_ro(sdkp->disk, sdkp->write_prot || disk_ro);
|
||||
if (sdkp->first_scan || old_wp != sdkp->write_prot) {
|
||||
sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
|
||||
sdkp->write_prot ? "on" : "off");
|
||||
|
@ -403,7 +403,7 @@ static int sd_zbc_check_capacity(struct scsi_disk *sdkp, unsigned char *buf)
|
||||
*/
|
||||
static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
|
||||
{
|
||||
u64 zone_blocks;
|
||||
u64 zone_blocks = 0;
|
||||
sector_t block = 0;
|
||||
unsigned char *buf;
|
||||
unsigned char *rec;
|
||||
@ -421,10 +421,8 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
|
||||
|
||||
/* Do a report zone to get the same field */
|
||||
ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, 0);
|
||||
if (ret) {
|
||||
zone_blocks = 0;
|
||||
goto out;
|
||||
}
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
same = buf[4] & 0x0f;
|
||||
if (same > 0) {
|
||||
@ -464,7 +462,7 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
|
||||
ret = sd_zbc_report_zones(sdkp, buf,
|
||||
SD_ZBC_BUF_SIZE, block);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
} while (block < sdkp->capacity);
|
||||
@ -472,35 +470,32 @@ static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
|
||||
zone_blocks = sdkp->zone_blocks;
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
|
||||
if (!zone_blocks) {
|
||||
if (sdkp->first_scan)
|
||||
sd_printk(KERN_NOTICE, sdkp,
|
||||
"Devices with non constant zone "
|
||||
"size are not supported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!is_power_of_2(zone_blocks)) {
|
||||
ret = -ENODEV;
|
||||
} else if (!is_power_of_2(zone_blocks)) {
|
||||
if (sdkp->first_scan)
|
||||
sd_printk(KERN_NOTICE, sdkp,
|
||||
"Devices with non power of 2 zone "
|
||||
"size are not supported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
|
||||
ret = -ENODEV;
|
||||
} else if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
|
||||
if (sdkp->first_scan)
|
||||
sd_printk(KERN_NOTICE, sdkp,
|
||||
"Zone size too large\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
} else {
|
||||
sdkp->zone_blocks = zone_blocks;
|
||||
sdkp->zone_shift = ilog2(zone_blocks);
|
||||
}
|
||||
|
||||
sdkp->zone_blocks = zone_blocks;
|
||||
sdkp->zone_shift = ilog2(zone_blocks);
|
||||
out_free:
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1311,7 +1311,8 @@ static int storvsc_do_io(struct hv_device *device,
|
||||
*/
|
||||
cpumask_and(&alloced_mask, &stor_device->alloced_cpus,
|
||||
cpumask_of_node(cpu_to_node(q_num)));
|
||||
for_each_cpu(tgt_cpu, &alloced_mask) {
|
||||
for_each_cpu_wrap(tgt_cpu, &alloced_mask,
|
||||
outgoing_channel->target_cpu + 1) {
|
||||
if (tgt_cpu != outgoing_channel->target_cpu) {
|
||||
outgoing_channel =
|
||||
stor_device->stor_chns[tgt_cpu];
|
||||
@ -1657,7 +1658,7 @@ static struct scsi_host_template scsi_driver = {
|
||||
.eh_timed_out = storvsc_eh_timed_out,
|
||||
.slave_alloc = storvsc_device_alloc,
|
||||
.slave_configure = storvsc_device_configure,
|
||||
.cmd_per_lun = 255,
|
||||
.cmd_per_lun = 2048,
|
||||
.this_id = -1,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
/* Make sure we dont get a sg segment crosses a page boundary */
|
||||
|
@ -536,7 +536,7 @@ sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fa
|
||||
* Look for the greatest clock divisor that allows an
|
||||
* input speed faster than the period.
|
||||
*/
|
||||
while (div-- > 0)
|
||||
while (--div > 0)
|
||||
if (kpc >= (div_10M[div] << 2)) break;
|
||||
|
||||
/*
|
||||
|
@ -4331,6 +4331,8 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
|
||||
/* REPORT SUPPORTED OPERATION CODES is not supported */
|
||||
sdev->no_report_opcodes = 1;
|
||||
|
||||
/* WRITE_SAME command is not supported */
|
||||
sdev->no_write_same = 1;
|
||||
|
||||
ufshcd_set_queue_depth(sdev);
|
||||
|
||||
|
@ -91,9 +91,6 @@ struct virtio_scsi_vq {
|
||||
struct virtio_scsi_target_state {
|
||||
seqcount_t tgt_seq;
|
||||
|
||||
/* Count of outstanding requests. */
|
||||
atomic_t reqs;
|
||||
|
||||
/* Currently active virtqueue for requests sent to this target. */
|
||||
struct virtio_scsi_vq *req_vq;
|
||||
};
|
||||
@ -152,8 +149,6 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf)
|
||||
struct virtio_scsi_cmd *cmd = buf;
|
||||
struct scsi_cmnd *sc = cmd->sc;
|
||||
struct virtio_scsi_cmd_resp *resp = &cmd->resp.cmd;
|
||||
struct virtio_scsi_target_state *tgt =
|
||||
scsi_target(sc->device)->hostdata;
|
||||
|
||||
dev_dbg(&sc->device->sdev_gendev,
|
||||
"cmd %p response %u status %#02x sense_len %u\n",
|
||||
@ -210,8 +205,6 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf)
|
||||
}
|
||||
|
||||
sc->scsi_done(sc);
|
||||
|
||||
atomic_dec(&tgt->reqs);
|
||||
}
|
||||
|
||||
static void virtscsi_vq_done(struct virtio_scsi *vscsi,
|
||||
@ -529,11 +522,20 @@ static void virtio_scsi_init_hdr_pi(struct virtio_device *vdev,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
|
||||
struct virtio_scsi_vq *req_vq,
|
||||
static struct virtio_scsi_vq *virtscsi_pick_vq_mq(struct virtio_scsi *vscsi,
|
||||
struct scsi_cmnd *sc)
|
||||
{
|
||||
u32 tag = blk_mq_unique_tag(sc->request);
|
||||
u16 hwq = blk_mq_unique_tag_to_hwq(tag);
|
||||
|
||||
return &vscsi->req_vqs[hwq];
|
||||
}
|
||||
|
||||
static int virtscsi_queuecommand(struct Scsi_Host *shost,
|
||||
struct scsi_cmnd *sc)
|
||||
{
|
||||
struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
|
||||
struct virtio_scsi *vscsi = shost_priv(shost);
|
||||
struct virtio_scsi_vq *req_vq = virtscsi_pick_vq_mq(vscsi, sc);
|
||||
struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc);
|
||||
unsigned long flags;
|
||||
int req_size;
|
||||
@ -576,79 +578,6 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virtscsi_queuecommand_single(struct Scsi_Host *sh,
|
||||
struct scsi_cmnd *sc)
|
||||
{
|
||||
struct virtio_scsi *vscsi = shost_priv(sh);
|
||||
struct virtio_scsi_target_state *tgt =
|
||||
scsi_target(sc->device)->hostdata;
|
||||
|
||||
atomic_inc(&tgt->reqs);
|
||||
return virtscsi_queuecommand(vscsi, &vscsi->req_vqs[0], sc);
|
||||
}
|
||||
|
||||
static struct virtio_scsi_vq *virtscsi_pick_vq_mq(struct virtio_scsi *vscsi,
|
||||
struct scsi_cmnd *sc)
|
||||
{
|
||||
u32 tag = blk_mq_unique_tag(sc->request);
|
||||
u16 hwq = blk_mq_unique_tag_to_hwq(tag);
|
||||
|
||||
return &vscsi->req_vqs[hwq];
|
||||
}
|
||||
|
||||
static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi,
|
||||
struct virtio_scsi_target_state *tgt)
|
||||
{
|
||||
struct virtio_scsi_vq *vq;
|
||||
unsigned long flags;
|
||||
u32 queue_num;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (atomic_inc_return(&tgt->reqs) > 1) {
|
||||
unsigned long seq;
|
||||
|
||||
do {
|
||||
seq = read_seqcount_begin(&tgt->tgt_seq);
|
||||
vq = tgt->req_vq;
|
||||
} while (read_seqcount_retry(&tgt->tgt_seq, seq));
|
||||
} else {
|
||||
/* no writes can be concurrent because of atomic_t */
|
||||
write_seqcount_begin(&tgt->tgt_seq);
|
||||
|
||||
/* keep previous req_vq if a reader just arrived */
|
||||
if (unlikely(atomic_read(&tgt->reqs) > 1)) {
|
||||
vq = tgt->req_vq;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
queue_num = smp_processor_id();
|
||||
while (unlikely(queue_num >= vscsi->num_queues))
|
||||
queue_num -= vscsi->num_queues;
|
||||
tgt->req_vq = vq = &vscsi->req_vqs[queue_num];
|
||||
unlock:
|
||||
write_seqcount_end(&tgt->tgt_seq);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
return vq;
|
||||
}
|
||||
|
||||
static int virtscsi_queuecommand_multi(struct Scsi_Host *sh,
|
||||
struct scsi_cmnd *sc)
|
||||
{
|
||||
struct virtio_scsi *vscsi = shost_priv(sh);
|
||||
struct virtio_scsi_target_state *tgt =
|
||||
scsi_target(sc->device)->hostdata;
|
||||
struct virtio_scsi_vq *req_vq;
|
||||
|
||||
if (shost_use_blk_mq(sh))
|
||||
req_vq = virtscsi_pick_vq_mq(vscsi, sc);
|
||||
else
|
||||
req_vq = virtscsi_pick_vq(vscsi, tgt);
|
||||
|
||||
return virtscsi_queuecommand(vscsi, req_vq, sc);
|
||||
}
|
||||
|
||||
static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(comp);
|
||||
@ -775,7 +704,6 @@ static int virtscsi_target_alloc(struct scsi_target *starget)
|
||||
return -ENOMEM;
|
||||
|
||||
seqcount_init(&tgt->tgt_seq);
|
||||
atomic_set(&tgt->reqs, 0);
|
||||
tgt->req_vq = &vscsi->req_vqs[0];
|
||||
|
||||
starget->hostdata = tgt;
|
||||
@ -805,33 +733,13 @@ static enum blk_eh_timer_return virtscsi_eh_timed_out(struct scsi_cmnd *scmnd)
|
||||
return BLK_EH_RESET_TIMER;
|
||||
}
|
||||
|
||||
static struct scsi_host_template virtscsi_host_template_single = {
|
||||
static struct scsi_host_template virtscsi_host_template = {
|
||||
.module = THIS_MODULE,
|
||||
.name = "Virtio SCSI HBA",
|
||||
.proc_name = "virtio_scsi",
|
||||
.this_id = -1,
|
||||
.cmd_size = sizeof(struct virtio_scsi_cmd),
|
||||
.queuecommand = virtscsi_queuecommand_single,
|
||||
.change_queue_depth = virtscsi_change_queue_depth,
|
||||
.eh_abort_handler = virtscsi_abort,
|
||||
.eh_device_reset_handler = virtscsi_device_reset,
|
||||
.eh_timed_out = virtscsi_eh_timed_out,
|
||||
.slave_alloc = virtscsi_device_alloc,
|
||||
|
||||
.dma_boundary = UINT_MAX,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.target_alloc = virtscsi_target_alloc,
|
||||
.target_destroy = virtscsi_target_destroy,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
static struct scsi_host_template virtscsi_host_template_multi = {
|
||||
.module = THIS_MODULE,
|
||||
.name = "Virtio SCSI HBA",
|
||||
.proc_name = "virtio_scsi",
|
||||
.this_id = -1,
|
||||
.cmd_size = sizeof(struct virtio_scsi_cmd),
|
||||
.queuecommand = virtscsi_queuecommand_multi,
|
||||
.queuecommand = virtscsi_queuecommand,
|
||||
.change_queue_depth = virtscsi_change_queue_depth,
|
||||
.eh_abort_handler = virtscsi_abort,
|
||||
.eh_device_reset_handler = virtscsi_device_reset,
|
||||
@ -844,6 +752,7 @@ static struct scsi_host_template virtscsi_host_template_multi = {
|
||||
.target_destroy = virtscsi_target_destroy,
|
||||
.map_queues = virtscsi_map_queues,
|
||||
.track_queue_depth = 1,
|
||||
.force_blk_mq = 1,
|
||||
};
|
||||
|
||||
#define virtscsi_config_get(vdev, fld) \
|
||||
@ -936,7 +845,6 @@ static int virtscsi_probe(struct virtio_device *vdev)
|
||||
u32 sg_elems, num_targets;
|
||||
u32 cmd_per_lun;
|
||||
u32 num_queues;
|
||||
struct scsi_host_template *hostt;
|
||||
|
||||
if (!vdev->config->get) {
|
||||
dev_err(&vdev->dev, "%s failure: config access disabled\n",
|
||||
@ -949,12 +857,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
|
||||
|
||||
num_targets = virtscsi_config_get(vdev, max_target) + 1;
|
||||
|
||||
if (num_queues == 1)
|
||||
hostt = &virtscsi_host_template_single;
|
||||
else
|
||||
hostt = &virtscsi_host_template_multi;
|
||||
|
||||
shost = scsi_host_alloc(hostt,
|
||||
shost = scsi_host_alloc(&virtscsi_host_template,
|
||||
sizeof(*vscsi) + sizeof(vscsi->req_vqs[0]) * num_queues);
|
||||
if (!shost)
|
||||
return -ENOMEM;
|
||||
|
@ -68,6 +68,9 @@ struct scsi_cmnd {
|
||||
struct list_head list; /* scsi_cmnd participates in queue lists */
|
||||
struct list_head eh_entry; /* entry for the host eh_cmd_q */
|
||||
struct delayed_work abort_work;
|
||||
|
||||
struct rcu_head rcu;
|
||||
|
||||
int eh_eflags; /* Used by error handlr */
|
||||
|
||||
/*
|
||||
|
@ -437,6 +437,9 @@ struct scsi_host_template {
|
||||
/* True if the controller does not support WRITE SAME */
|
||||
unsigned no_write_same:1;
|
||||
|
||||
/* True if the low-level driver supports blk-mq only */
|
||||
unsigned force_blk_mq:1;
|
||||
|
||||
/*
|
||||
* Countdown for host blocking with no commands outstanding.
|
||||
*/
|
||||
@ -553,8 +556,6 @@ struct Scsi_Host {
|
||||
struct blk_mq_tag_set tag_set;
|
||||
};
|
||||
|
||||
struct rcu_head rcu;
|
||||
|
||||
atomic_t host_busy; /* commands actually active on low-level */
|
||||
atomic_t host_blocked;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user