mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
Merge 746fc76b82 ("Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi") into android-mainline
Steps on the way to 6.0-rc1 Resolves merge conflicts with: include/ufs/ufshcd.h Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ifb6b6d3fefbce01620b120ccefd51acf252d72d5
This commit is contained in:
commit
1bbf97a79c
|
|
@ -26,6 +26,7 @@ properties:
|
|||
- qcom,msm8994-ufshc
|
||||
- qcom,msm8996-ufshc
|
||||
- qcom,msm8998-ufshc
|
||||
- qcom,sc8280xp-ufshc
|
||||
- qcom,sdm845-ufshc
|
||||
- qcom,sm6350-ufshc
|
||||
- qcom,sm8150-ufshc
|
||||
|
|
@ -98,6 +99,7 @@ allOf:
|
|||
contains:
|
||||
enum:
|
||||
- qcom,msm8998-ufshc
|
||||
- qcom,sc8280xp-ufshc
|
||||
- qcom,sm8250-ufshc
|
||||
- qcom,sm8350-ufshc
|
||||
- qcom,sm8450-ufshc
|
||||
|
|
|
|||
61
Documentation/devicetree/bindings/ufs/renesas,ufs.yaml
Normal file
61
Documentation/devicetree/bindings/ufs/renesas,ufs.yaml
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ufs/renesas,ufs.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R-Car UFS Host Controller
|
||||
|
||||
maintainers:
|
||||
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
|
||||
|
||||
allOf:
|
||||
- $ref: ufs-common.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: renesas,r8a779f0-ufs
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: fck
|
||||
- const: ref_clk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- resets
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/r8a779f0-sysc.h>
|
||||
|
||||
ufs: ufs@e686000 {
|
||||
compatible = "renesas,r8a779f0-ufs";
|
||||
reg = <0xe6860000 0x100>;
|
||||
interrupts = <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 1514>, <&ufs30_clk>;
|
||||
clock-names = "fck", "ref_clk";
|
||||
freq-table-hz = <200000000 200000000>, <38400000 38400000>;
|
||||
power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 1514>;
|
||||
};
|
||||
|
|
@ -21,6 +21,7 @@ properties:
|
|||
- samsung,exynos7-ufs
|
||||
- samsung,exynosautov9-ufs
|
||||
- samsung,exynosautov9-ufs-vh
|
||||
- tesla,fsd-ufs
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ Universal Flash Storage
|
|||
3.2 UTP Transfer requests
|
||||
3.3 UFS error handling
|
||||
3.4 SCSI Error handling
|
||||
4. BSG Support
|
||||
5. UFS Reference Clock Frequency configuration
|
||||
|
||||
|
||||
1. Overview
|
||||
|
|
@ -193,3 +195,16 @@ UFS specifications can be found at:
|
|||
|
||||
- UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf
|
||||
- UFSHCI - http://www.jedec.org/sites/default/files/docs/JESD223.pdf
|
||||
|
||||
5. UFS Reference Clock Frequency configuration
|
||||
==============================================
|
||||
|
||||
Devicetree can define a clock named "ref_clk" under the UFS controller node
|
||||
to specify the intended reference clock frequency for the UFS storage
|
||||
parts. ACPI-based system can specify the frequency using ACPI
|
||||
Device-Specific Data property named "ref-clk-freq". In both ways the value
|
||||
is interpreted as frequency in Hz and must match one of the values given in
|
||||
the UFS specification. UFS subsystem will attempt to read the value when
|
||||
executing common controller initialization. If the value is available, UFS
|
||||
subsytem will ensure the bRefClkFreq attribute of the UFS storage device is
|
||||
set accordingly and will modify it if there is a mismatch.
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ Code Seq# Include File Comments
|
|||
'C' 01-2F linux/capi.h conflict!
|
||||
'C' F0-FF drivers/net/wan/cosa.h conflict!
|
||||
'D' all arch/s390/include/asm/dasd.h
|
||||
'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h
|
||||
'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h Dead since 2022
|
||||
'D' 05 drivers/scsi/pmcraid.h
|
||||
'E' all linux/input.h conflict!
|
||||
'E' 00-0F xen/evtchn.h conflict!
|
||||
|
|
|
|||
19
MAINTAINERS
19
MAINTAINERS
|
|
@ -5511,7 +5511,7 @@ W: http://www.chelsio.com
|
|||
F: drivers/net/ethernet/chelsio/cxgb3/
|
||||
|
||||
CXGB3 ISCSI DRIVER (CXGB3I)
|
||||
M: Karen Xie <kxie@chelsio.com>
|
||||
M: Varun Prakash <varun@chelsio.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://www.chelsio.com
|
||||
|
|
@ -5543,7 +5543,7 @@ W: http://www.chelsio.com
|
|||
F: drivers/net/ethernet/chelsio/cxgb4/
|
||||
|
||||
CXGB4 ISCSI DRIVER (CXGB4I)
|
||||
M: Karen Xie <kxie@chelsio.com>
|
||||
M: Varun Prakash <varun@chelsio.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://www.chelsio.com
|
||||
|
|
@ -6275,14 +6275,6 @@ F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive
|
|||
F: drivers/net/ethernet/freescale/dpaa2/dpaa2-switch*
|
||||
F: drivers/net/ethernet/freescale/dpaa2/dpsw*
|
||||
|
||||
DPT_I2O SCSI RAID DRIVER
|
||||
M: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://www.adaptec.com/
|
||||
F: drivers/scsi/dpt*
|
||||
F: drivers/scsi/dpt/
|
||||
|
||||
DRBD DRIVER
|
||||
M: Philipp Reisner <philipp.reisner@linbit.com>
|
||||
M: Lars Ellenberg <lars.ellenberg@linbit.com>
|
||||
|
|
@ -20818,6 +20810,13 @@ L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
|
|||
S: Maintained
|
||||
F: drivers/ufs/host/ufs-mediatek*
|
||||
|
||||
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER RENESAS HOOKS
|
||||
M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/ufs/host/ufs-renesas.c
|
||||
|
||||
UNSORTED BLOCK IMAGES (UBI)
|
||||
M: Richard Weinberger <richard@nod.at>
|
||||
L: linux-mtd@lists.infradead.org
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ static void bsg_device_release(struct device *dev)
|
|||
{
|
||||
struct bsg_device *bd = container_of(dev, struct bsg_device, device);
|
||||
|
||||
ida_simple_remove(&bsg_minor_ida, MINOR(bd->device.devt));
|
||||
ida_free(&bsg_minor_ida, MINOR(bd->device.devt));
|
||||
kfree(bd);
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ struct bsg_device *bsg_register_queue(struct request_queue *q,
|
|||
bd->queue = q;
|
||||
bd->sg_io_fn = sg_io_fn;
|
||||
|
||||
ret = ida_simple_get(&bsg_minor_ida, 0, BSG_MAX_DEVS, GFP_KERNEL);
|
||||
ret = ida_alloc_max(&bsg_minor_ida, BSG_MAX_DEVS - 1, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOSPC)
|
||||
dev_err(parent, "bsg: too many bsg devices\n");
|
||||
|
|
|
|||
|
|
@ -568,7 +568,7 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
|
|||
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
||||
|
||||
iscsi_session_teardown(cls_session);
|
||||
iscsi_host_remove(shost);
|
||||
iscsi_host_remove(shost, false);
|
||||
iscsi_host_free(shost);
|
||||
}
|
||||
|
||||
|
|
@ -685,7 +685,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
|
|||
return cls_session;
|
||||
|
||||
remove_host:
|
||||
iscsi_host_remove(shost);
|
||||
iscsi_host_remove(shost, false);
|
||||
free_host:
|
||||
iscsi_host_free(shost);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ static u8 mptspiInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for interna
|
|||
* @target: per target private data
|
||||
* @sdev: SCSI device
|
||||
*
|
||||
* Update the target negotiation parameters based on the the Inquiry
|
||||
* Update the target negotiation parameters based on the Inquiry
|
||||
* data, adapter capabilities, and NVRAM settings.
|
||||
**/
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* zfcp device driver
|
||||
*
|
||||
* Definitions for handling diagnostics in the the zfcp device driver.
|
||||
* Definitions for handling diagnostics in the zfcp device driver.
|
||||
*
|
||||
* Copyright IBM Corp. 2018, 2020
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -672,7 +672,7 @@ ZFCP_DEFINE_SCSI_ATTR(zfcp_in_recovery, "%d\n",
|
|||
ZFCP_DEFINE_SCSI_ATTR(zfcp_status, "0x%08x\n",
|
||||
atomic_read(&zfcp_sdev->status));
|
||||
|
||||
struct attribute *zfcp_sdev_attrs[] = {
|
||||
static struct attribute *zfcp_sdev_attrs[] = {
|
||||
&dev_attr_fcp_lun.attr,
|
||||
&dev_attr_wwpn.attr,
|
||||
&dev_attr_hba_id.attr,
|
||||
|
|
|
|||
|
|
@ -2515,12 +2515,26 @@ static int blogic_resultcode(struct blogic_adapter *adapter,
|
|||
return (hoststatus << 16) | tgt_status;
|
||||
}
|
||||
|
||||
/*
|
||||
* turn the dma address from an inbox into a ccb pointer
|
||||
* This is rather inefficient.
|
||||
*/
|
||||
static struct blogic_ccb *
|
||||
blogic_inbox_to_ccb(struct blogic_adapter *adapter, struct blogic_inbox *inbox)
|
||||
{
|
||||
struct blogic_ccb *ccb;
|
||||
|
||||
for (ccb = adapter->all_ccbs; ccb; ccb = ccb->next_all)
|
||||
if (inbox->ccb == ccb->dma_handle)
|
||||
break;
|
||||
|
||||
return ccb;
|
||||
}
|
||||
|
||||
/*
|
||||
blogic_scan_inbox scans the Incoming Mailboxes saving any
|
||||
Incoming Mailbox entries for completion processing.
|
||||
*/
|
||||
|
||||
static void blogic_scan_inbox(struct blogic_adapter *adapter)
|
||||
{
|
||||
/*
|
||||
|
|
@ -2540,17 +2554,14 @@ static void blogic_scan_inbox(struct blogic_adapter *adapter)
|
|||
enum blogic_cmplt_code comp_code;
|
||||
|
||||
while ((comp_code = next_inbox->comp_code) != BLOGIC_INBOX_FREE) {
|
||||
/*
|
||||
We are only allowed to do this because we limit our
|
||||
architectures we run on to machines where bus_to_virt(
|
||||
actually works. There *needs* to be a dma_addr_to_virt()
|
||||
in the new PCI DMA mapping interface to replace
|
||||
bus_to_virt() or else this code is going to become very
|
||||
innefficient.
|
||||
*/
|
||||
struct blogic_ccb *ccb =
|
||||
(struct blogic_ccb *) bus_to_virt(next_inbox->ccb);
|
||||
if (comp_code != BLOGIC_CMD_NOTFOUND) {
|
||||
struct blogic_ccb *ccb = blogic_inbox_to_ccb(adapter, next_inbox);
|
||||
if (!ccb) {
|
||||
/*
|
||||
* This should never happen, unless the CCB list is
|
||||
* corrupted in memory.
|
||||
*/
|
||||
blogic_warn("Could not find CCB for dma address %x\n", adapter, next_inbox->ccb);
|
||||
} else if (comp_code != BLOGIC_CMD_NOTFOUND) {
|
||||
if (ccb->status == BLOGIC_CCB_ACTIVE ||
|
||||
ccb->status == BLOGIC_CCB_RESET) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -458,17 +458,6 @@ config SCSI_MVUMI
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called mvumi.
|
||||
|
||||
config SCSI_DPT_I2O
|
||||
tristate "Adaptec I2O RAID support "
|
||||
depends on SCSI && PCI && VIRT_TO_BUS
|
||||
help
|
||||
This driver supports all of Adaptec's I2O based RAID controllers as
|
||||
well as the DPT SmartRaid V cards. This is an Adaptec maintained
|
||||
driver by Deanna Bonds. See <file:Documentation/scsi/dpti.rst>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called dpt_i2o.
|
||||
|
||||
config SCSI_ADVANSYS
|
||||
tristate "AdvanSys SCSI support"
|
||||
depends on SCSI
|
||||
|
|
@ -513,7 +502,7 @@ config SCSI_HPTIOP
|
|||
|
||||
config SCSI_BUSLOGIC
|
||||
tristate "BusLogic SCSI support"
|
||||
depends on PCI && SCSI && VIRT_TO_BUS
|
||||
depends on PCI && SCSI
|
||||
help
|
||||
This is support for BusLogic MultiMaster and FlashPoint SCSI Host
|
||||
Adapters. Consult the SCSI-HOWTO, available from
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ obj-$(CONFIG_BVME6000_SCSI) += 53c700.o bvme6000_scsi.o
|
|||
obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o
|
||||
obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o
|
||||
obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o
|
||||
obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o
|
||||
obj-$(CONFIG_SCSI_ARCMSR) += arcmsr/
|
||||
obj-$(CONFIG_SCSI_AHA152X) += aha152x.o
|
||||
obj-$(CONFIG_SCSI_AHA1542) += aha1542.o
|
||||
|
|
|
|||
|
|
@ -24,8 +24,11 @@
|
|||
struct a2091_hostdata {
|
||||
struct WD33C93_hostdata wh;
|
||||
struct a2091_scsiregs *regs;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
#define DMA_DIR(d) ((d == DATA_OUT_DIR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE)
|
||||
|
||||
static irqreturn_t a2091_intr(int irq, void *data)
|
||||
{
|
||||
struct Scsi_Host *instance = data;
|
||||
|
|
@ -45,15 +48,31 @@ static irqreturn_t a2091_intr(int irq, void *data)
|
|||
static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
|
||||
unsigned long len = scsi_pointer->this_residual;
|
||||
struct Scsi_Host *instance = cmd->device->host;
|
||||
struct a2091_hostdata *hdata = shost_priv(instance);
|
||||
struct WD33C93_hostdata *wh = &hdata->wh;
|
||||
struct a2091_scsiregs *regs = hdata->regs;
|
||||
unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
|
||||
unsigned long addr = virt_to_bus(scsi_pointer->ptr);
|
||||
dma_addr_t addr;
|
||||
|
||||
addr = dma_map_single(hdata->dev, scsi_pointer->ptr,
|
||||
len, DMA_DIR(dir_in));
|
||||
if (dma_mapping_error(hdata->dev, addr)) {
|
||||
dev_warn(hdata->dev, "cannot map SCSI data block %p\n",
|
||||
scsi_pointer->ptr);
|
||||
return 1;
|
||||
}
|
||||
scsi_pointer->dma_handle = addr;
|
||||
|
||||
/* don't allow DMA if the physical address is bad */
|
||||
if (addr & A2091_XFER_MASK) {
|
||||
/* drop useless mapping */
|
||||
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
|
||||
scsi_pointer->this_residual,
|
||||
DMA_DIR(dir_in));
|
||||
scsi_pointer->dma_handle = (dma_addr_t) NULL;
|
||||
|
||||
wh->dma_bounce_len = (scsi_pointer->this_residual + 511) & ~0x1ff;
|
||||
wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len,
|
||||
GFP_KERNEL);
|
||||
|
|
@ -64,8 +83,21 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* get the physical address of the bounce buffer */
|
||||
addr = virt_to_bus(wh->dma_bounce_buffer);
|
||||
if (!dir_in) {
|
||||
/* copy to bounce buffer for a write */
|
||||
memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
|
||||
scsi_pointer->this_residual);
|
||||
}
|
||||
|
||||
/* will flush/invalidate cache for us */
|
||||
addr = dma_map_single(hdata->dev, wh->dma_bounce_buffer,
|
||||
wh->dma_bounce_len, DMA_DIR(dir_in));
|
||||
/* can't map buffer; use PIO */
|
||||
if (dma_mapping_error(hdata->dev, addr)) {
|
||||
dev_warn(hdata->dev, "cannot map bounce buffer %p\n",
|
||||
wh->dma_bounce_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* the bounce buffer may not be in the first 16M of physmem */
|
||||
if (addr & A2091_XFER_MASK) {
|
||||
|
|
@ -76,11 +108,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!dir_in) {
|
||||
/* copy to bounce buffer for a write */
|
||||
memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
|
||||
scsi_pointer->this_residual);
|
||||
}
|
||||
scsi_pointer->dma_handle = addr;
|
||||
}
|
||||
|
||||
/* setup dma direction */
|
||||
|
|
@ -95,13 +123,8 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
/* setup DMA *physical* address */
|
||||
regs->ACR = addr;
|
||||
|
||||
if (dir_in) {
|
||||
/* invalidate any cache */
|
||||
cache_clear(addr, scsi_pointer->this_residual);
|
||||
} else {
|
||||
/* push any dirty cache */
|
||||
cache_push(addr, scsi_pointer->this_residual);
|
||||
}
|
||||
/* no more cache flush here - dma_map_single() takes care */
|
||||
|
||||
/* start DMA */
|
||||
regs->ST_DMA = 1;
|
||||
|
||||
|
|
@ -142,6 +165,10 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
|
|||
/* restore the CONTROL bits (minus the direction flag) */
|
||||
regs->CNTR = CNTR_PDMD | CNTR_INTEN;
|
||||
|
||||
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
|
||||
scsi_pointer->this_residual,
|
||||
DMA_DIR(wh->dma_dir));
|
||||
|
||||
/* copy from a bounce buffer, if necessary */
|
||||
if (status && wh->dma_bounce_buffer) {
|
||||
if (wh->dma_dir)
|
||||
|
|
@ -178,6 +205,11 @@ static int a2091_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
|
|||
wd33c93_regs wdregs;
|
||||
struct a2091_hostdata *hdata;
|
||||
|
||||
if (dma_set_mask_and_coherent(&z->dev, DMA_BIT_MASK(24))) {
|
||||
dev_warn(&z->dev, "cannot use 24 bit DMA\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!request_mem_region(z->resource.start, 256, "wd33c93"))
|
||||
return -EBUSY;
|
||||
|
||||
|
|
@ -198,6 +230,7 @@ static int a2091_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
|
|||
wdregs.SCMD = ®s->SCMD;
|
||||
|
||||
hdata = shost_priv(instance);
|
||||
hdata->dev = &z->dev;
|
||||
hdata->wh.no_sync = 0xff;
|
||||
hdata->wh.fast = 0;
|
||||
hdata->wh.dma_mode = CTRL_DMA;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
|
|
@ -25,8 +26,11 @@
|
|||
struct a3000_hostdata {
|
||||
struct WD33C93_hostdata wh;
|
||||
struct a3000_scsiregs *regs;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
#define DMA_DIR(d) ((d == DATA_OUT_DIR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE)
|
||||
|
||||
static irqreturn_t a3000_intr(int irq, void *data)
|
||||
{
|
||||
struct Scsi_Host *instance = data;
|
||||
|
|
@ -49,20 +53,38 @@ static irqreturn_t a3000_intr(int irq, void *data)
|
|||
static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
|
||||
unsigned long len = scsi_pointer->this_residual;
|
||||
struct Scsi_Host *instance = cmd->device->host;
|
||||
struct a3000_hostdata *hdata = shost_priv(instance);
|
||||
struct WD33C93_hostdata *wh = &hdata->wh;
|
||||
struct a3000_scsiregs *regs = hdata->regs;
|
||||
unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
|
||||
unsigned long addr = virt_to_bus(scsi_pointer->ptr);
|
||||
dma_addr_t addr;
|
||||
|
||||
addr = dma_map_single(hdata->dev, scsi_pointer->ptr,
|
||||
len, DMA_DIR(dir_in));
|
||||
if (dma_mapping_error(hdata->dev, addr)) {
|
||||
dev_warn(hdata->dev, "cannot map SCSI data block %p\n",
|
||||
scsi_pointer->ptr);
|
||||
return 1;
|
||||
}
|
||||
scsi_pointer->dma_handle = addr;
|
||||
|
||||
/*
|
||||
* if the physical address has the wrong alignment, or if
|
||||
* physical address is bad, or if it is a write and at the
|
||||
* end of a physical memory chunk, then allocate a bounce
|
||||
* buffer
|
||||
* MSch 20220629 - only wrong alignment tested - bounce
|
||||
* buffer returned by kmalloc is guaranteed to be aligned
|
||||
*/
|
||||
if (addr & A3000_XFER_MASK) {
|
||||
WARN_ONCE(1, "Invalid alignment for DMA!");
|
||||
/* drop useless mapping */
|
||||
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
|
||||
scsi_pointer->this_residual,
|
||||
DMA_DIR(dir_in));
|
||||
|
||||
wh->dma_bounce_len = (scsi_pointer->this_residual + 511) & ~0x1ff;
|
||||
wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len,
|
||||
GFP_KERNEL);
|
||||
|
|
@ -70,6 +92,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
/* can't allocate memory; use PIO */
|
||||
if (!wh->dma_bounce_buffer) {
|
||||
wh->dma_bounce_len = 0;
|
||||
scsi_pointer->dma_handle = (dma_addr_t) NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +102,15 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
scsi_pointer->this_residual);
|
||||
}
|
||||
|
||||
addr = virt_to_bus(wh->dma_bounce_buffer);
|
||||
addr = dma_map_single(hdata->dev, scsi_pointer->ptr,
|
||||
len, DMA_DIR(dir_in));
|
||||
if (dma_mapping_error(hdata->dev, addr)) {
|
||||
dev_warn(hdata->dev,
|
||||
"cannot map SCSI data block %p\n",
|
||||
scsi_pointer->ptr);
|
||||
return 1;
|
||||
}
|
||||
scsi_pointer->dma_handle = addr;
|
||||
}
|
||||
|
||||
/* setup dma direction */
|
||||
|
|
@ -94,13 +125,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
/* setup DMA *physical* address */
|
||||
regs->ACR = addr;
|
||||
|
||||
if (dir_in) {
|
||||
/* invalidate any cache */
|
||||
cache_clear(addr, scsi_pointer->this_residual);
|
||||
} else {
|
||||
/* push any dirty cache */
|
||||
cache_push(addr, scsi_pointer->this_residual);
|
||||
}
|
||||
/* no more cache flush here - dma_map_single() takes care */
|
||||
|
||||
/* start DMA */
|
||||
mb(); /* make sure setup is completed */
|
||||
|
|
@ -151,6 +176,10 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
|
|||
regs->CNTR = CNTR_PDMD | CNTR_INTEN;
|
||||
mb(); /* make sure CNTR is updated before next IO */
|
||||
|
||||
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
|
||||
scsi_pointer->this_residual,
|
||||
DMA_DIR(wh->dma_dir));
|
||||
|
||||
/* copy from a bounce buffer, if necessary */
|
||||
if (status && wh->dma_bounce_buffer) {
|
||||
if (SCpnt) {
|
||||
|
|
@ -193,6 +222,11 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev)
|
|||
wd33c93_regs wdregs;
|
||||
struct a3000_hostdata *hdata;
|
||||
|
||||
if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
|
||||
dev_warn(&pdev->dev, "cannot use 32 bit DMA\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
|
@ -216,6 +250,7 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev)
|
|||
wdregs.SCMD = ®s->SCMD;
|
||||
|
||||
hdata = shost_priv(instance);
|
||||
hdata->dev = &pdev->dev;
|
||||
hdata->wh.no_sync = 0xff;
|
||||
hdata->wh.fast = 0;
|
||||
hdata->wh.dma_mode = CTRL_DMA;
|
||||
|
|
|
|||
|
|
@ -1050,7 +1050,7 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
|
|||
vpdpage83data.type1.productid));
|
||||
|
||||
/* Convert to ascii based serial number.
|
||||
* The LSB is the the end.
|
||||
* The LSB is the end.
|
||||
*/
|
||||
for (i = 0; i < 8; i++) {
|
||||
u8 temp =
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ static int asd_init_target_ddb(struct domain_device *dev)
|
|||
flags |= OPEN_REQUIRED;
|
||||
if ((dev->dev_type == SAS_SATA_DEV) ||
|
||||
(dev->tproto & SAS_PROTOCOL_STP)) {
|
||||
struct smp_resp *rps_resp = &dev->sata_dev.rps_resp;
|
||||
struct smp_rps_resp *rps_resp = &dev->sata_dev.rps_resp;
|
||||
if (rps_resp->frame_type == SMP_RESPONSE &&
|
||||
rps_resp->function == SMP_REPORT_PHY_SATA &&
|
||||
rps_resp->result == SMP_RESP_FUNC_ACC) {
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
|
|||
cls_session = starget_to_session(scsi_target(sc->device));
|
||||
session = cls_session->dd_data;
|
||||
|
||||
completion_check:
|
||||
/* check if we raced, task just got cleaned up under us */
|
||||
spin_lock_bh(&session->back_lock);
|
||||
if (!abrt_task || !abrt_task->sc) {
|
||||
|
|
@ -238,7 +239,13 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
|
|||
return SUCCESS;
|
||||
}
|
||||
/* get a task ref till FW processes the req for the ICD used */
|
||||
__iscsi_get_task(abrt_task);
|
||||
if (!iscsi_get_task(abrt_task)) {
|
||||
spin_unlock(&session->back_lock);
|
||||
/* We are just about to call iscsi_free_task so wait for it. */
|
||||
udelay(5);
|
||||
goto completion_check;
|
||||
}
|
||||
|
||||
abrt_io_task = abrt_task->dd_data;
|
||||
conn = abrt_task->conn;
|
||||
beiscsi_conn = conn->dd_data;
|
||||
|
|
@ -323,7 +330,15 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
|
|||
}
|
||||
|
||||
/* get a task ref till FW processes the req for the ICD used */
|
||||
__iscsi_get_task(task);
|
||||
if (!iscsi_get_task(task)) {
|
||||
/*
|
||||
* The task has completed in the driver and is
|
||||
* completing in libiscsi. Just ignore it here. When we
|
||||
* call iscsi_eh_device_reset, it will wait for us.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
io_task = task->dd_data;
|
||||
/* mark WRB invalid which have been not processed by FW yet */
|
||||
if (is_chip_be2_be3r(phba)) {
|
||||
|
|
@ -5745,7 +5760,7 @@ static void beiscsi_remove(struct pci_dev *pcidev)
|
|||
cancel_work_sync(&phba->sess_work);
|
||||
|
||||
beiscsi_iface_destroy_default(phba);
|
||||
iscsi_host_remove(phba->shost);
|
||||
iscsi_host_remove(phba->shost, false);
|
||||
beiscsi_disable_port(phba, 1);
|
||||
|
||||
/* after cancelling boot_work */
|
||||
|
|
|
|||
|
|
@ -909,7 +909,7 @@ void bnx2i_free_hba(struct bnx2i_hba *hba)
|
|||
{
|
||||
struct Scsi_Host *shost = hba->shost;
|
||||
|
||||
iscsi_host_remove(shost);
|
||||
iscsi_host_remove(shost, false);
|
||||
INIT_LIST_HEAD(&hba->ep_ofld_list);
|
||||
INIT_LIST_HEAD(&hba->ep_active_list);
|
||||
INIT_LIST_HEAD(&hba->ep_destroy_list);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static int verbose = 1;
|
|||
module_param(verbose, int, 0644);
|
||||
MODULE_PARM_DESC(verbose,"be verbose (default: on)");
|
||||
|
||||
static int debug = 0;
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug,"enable/disable debug messages, also prints more "
|
||||
"detailed sense codes on scsi errors (default: off)");
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev)
|
|||
chba = cdev->hbas[i];
|
||||
if (chba) {
|
||||
cdev->hbas[i] = NULL;
|
||||
iscsi_host_remove(chba->shost);
|
||||
iscsi_host_remove(chba->shost, false);
|
||||
pci_dev_put(cdev->pdev);
|
||||
iscsi_host_free(chba->shost);
|
||||
}
|
||||
|
|
@ -1455,7 +1455,7 @@ void cxgbi_conn_tx_open(struct cxgbi_sock *csk)
|
|||
if (conn) {
|
||||
log_debug(1 << CXGBI_DBG_SOCK,
|
||||
"csk 0x%p, cid %d.\n", csk, conn->id);
|
||||
iscsi_conn_queue_work(conn);
|
||||
iscsi_conn_queue_xmit(conn);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cxgbi_conn_tx_open);
|
||||
|
|
|
|||
|
|
@ -1,441 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef _SCSI_I2O_H
|
||||
#define _SCSI_I2O_H
|
||||
|
||||
/* I2O kernel space accessible structures/APIs
|
||||
*
|
||||
* (c) Copyright 1999, 2000 Red Hat Software
|
||||
*
|
||||
*************************************************************************
|
||||
*
|
||||
* This header file defined the I2O APIs/structures for use by
|
||||
* the I2O kernel modules.
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL__ /* This file to be included by kernel only */
|
||||
|
||||
#include <linux/i2o-dev.h>
|
||||
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
|
||||
/*
|
||||
* Tunable parameters first
|
||||
*/
|
||||
|
||||
/* How many different OSM's are we allowing */
|
||||
#define MAX_I2O_MODULES 64
|
||||
|
||||
#define I2O_EVT_CAPABILITY_OTHER 0x01
|
||||
#define I2O_EVT_CAPABILITY_CHANGED 0x02
|
||||
|
||||
#define I2O_EVT_SENSOR_STATE_CHANGED 0x01
|
||||
|
||||
//#ifdef __KERNEL__ /* ioctl stuff only thing exported to users */
|
||||
|
||||
#define I2O_MAX_MANAGERS 4
|
||||
|
||||
/*
|
||||
* I2O Interface Objects
|
||||
*/
|
||||
|
||||
#include <linux/wait.h>
|
||||
typedef wait_queue_head_t adpt_wait_queue_head_t;
|
||||
#define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait)
|
||||
typedef wait_queue_entry_t adpt_wait_queue_entry_t;
|
||||
|
||||
/*
|
||||
* message structures
|
||||
*/
|
||||
|
||||
struct i2o_message
|
||||
{
|
||||
u8 version_offset;
|
||||
u8 flags;
|
||||
u16 size;
|
||||
u32 target_tid:12;
|
||||
u32 init_tid:12;
|
||||
u32 function:8;
|
||||
u32 initiator_context;
|
||||
/* List follows */
|
||||
};
|
||||
|
||||
struct adpt_device;
|
||||
struct _adpt_hba;
|
||||
struct i2o_device
|
||||
{
|
||||
struct i2o_device *next; /* Chain */
|
||||
struct i2o_device *prev;
|
||||
|
||||
char dev_name[8]; /* linux /dev name if available */
|
||||
i2o_lct_entry lct_data;/* Device LCT information */
|
||||
u32 flags;
|
||||
struct proc_dir_entry* proc_entry; /* /proc dir */
|
||||
struct adpt_device *owner;
|
||||
struct _adpt_hba *controller; /* Controlling IOP */
|
||||
};
|
||||
|
||||
/*
|
||||
* Each I2O controller has one of these objects
|
||||
*/
|
||||
|
||||
struct i2o_controller
|
||||
{
|
||||
char name[16];
|
||||
int unit;
|
||||
int type;
|
||||
int enabled;
|
||||
|
||||
struct notifier_block *event_notifer; /* Events */
|
||||
atomic_t users;
|
||||
struct i2o_device *devices; /* I2O device chain */
|
||||
struct i2o_controller *next; /* Controller chain */
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* I2O System table entry
|
||||
*/
|
||||
struct i2o_sys_tbl_entry
|
||||
{
|
||||
u16 org_id;
|
||||
u16 reserved1;
|
||||
u32 iop_id:12;
|
||||
u32 reserved2:20;
|
||||
u16 seg_num:12;
|
||||
u16 i2o_version:4;
|
||||
u8 iop_state;
|
||||
u8 msg_type;
|
||||
u16 frame_size;
|
||||
u16 reserved3;
|
||||
u32 last_changed;
|
||||
u32 iop_capabilities;
|
||||
u32 inbound_low;
|
||||
u32 inbound_high;
|
||||
};
|
||||
|
||||
struct i2o_sys_tbl
|
||||
{
|
||||
u8 num_entries;
|
||||
u8 version;
|
||||
u16 reserved1;
|
||||
u32 change_ind;
|
||||
u32 reserved2;
|
||||
u32 reserved3;
|
||||
struct i2o_sys_tbl_entry iops[];
|
||||
};
|
||||
|
||||
/*
|
||||
* I2O classes / subclasses
|
||||
*/
|
||||
|
||||
/* Class ID and Code Assignments
|
||||
* (LCT.ClassID.Version field)
|
||||
*/
|
||||
#define I2O_CLASS_VERSION_10 0x00
|
||||
#define I2O_CLASS_VERSION_11 0x01
|
||||
|
||||
/* Class code names
|
||||
* (from v1.5 Table 6-1 Class Code Assignments.)
|
||||
*/
|
||||
|
||||
#define I2O_CLASS_EXECUTIVE 0x000
|
||||
#define I2O_CLASS_DDM 0x001
|
||||
#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010
|
||||
#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011
|
||||
#define I2O_CLASS_LAN 0x020
|
||||
#define I2O_CLASS_WAN 0x030
|
||||
#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040
|
||||
#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041
|
||||
#define I2O_CLASS_SCSI_PERIPHERAL 0x051
|
||||
#define I2O_CLASS_ATE_PORT 0x060
|
||||
#define I2O_CLASS_ATE_PERIPHERAL 0x061
|
||||
#define I2O_CLASS_FLOPPY_CONTROLLER 0x070
|
||||
#define I2O_CLASS_FLOPPY_DEVICE 0x071
|
||||
#define I2O_CLASS_BUS_ADAPTER_PORT 0x080
|
||||
#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090
|
||||
#define I2O_CLASS_PEER_TRANSPORT 0x091
|
||||
|
||||
/* Rest of 0x092 - 0x09f reserved for peer-to-peer classes
|
||||
*/
|
||||
|
||||
#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff
|
||||
|
||||
/* Subclasses
|
||||
*/
|
||||
|
||||
#define I2O_SUBCLASS_i960 0x001
|
||||
#define I2O_SUBCLASS_HDM 0x020
|
||||
#define I2O_SUBCLASS_ISM 0x021
|
||||
|
||||
/* Operation functions */
|
||||
|
||||
#define I2O_PARAMS_FIELD_GET 0x0001
|
||||
#define I2O_PARAMS_LIST_GET 0x0002
|
||||
#define I2O_PARAMS_MORE_GET 0x0003
|
||||
#define I2O_PARAMS_SIZE_GET 0x0004
|
||||
#define I2O_PARAMS_TABLE_GET 0x0005
|
||||
#define I2O_PARAMS_FIELD_SET 0x0006
|
||||
#define I2O_PARAMS_LIST_SET 0x0007
|
||||
#define I2O_PARAMS_ROW_ADD 0x0008
|
||||
#define I2O_PARAMS_ROW_DELETE 0x0009
|
||||
#define I2O_PARAMS_TABLE_CLEAR 0x000A
|
||||
|
||||
/*
|
||||
* I2O serial number conventions / formats
|
||||
* (circa v1.5)
|
||||
*/
|
||||
|
||||
#define I2O_SNFORMAT_UNKNOWN 0
|
||||
#define I2O_SNFORMAT_BINARY 1
|
||||
#define I2O_SNFORMAT_ASCII 2
|
||||
#define I2O_SNFORMAT_UNICODE 3
|
||||
#define I2O_SNFORMAT_LAN48_MAC 4
|
||||
#define I2O_SNFORMAT_WAN 5
|
||||
|
||||
/* Plus new in v2.0 (Yellowstone pdf doc)
|
||||
*/
|
||||
|
||||
#define I2O_SNFORMAT_LAN64_MAC 6
|
||||
#define I2O_SNFORMAT_DDM 7
|
||||
#define I2O_SNFORMAT_IEEE_REG64 8
|
||||
#define I2O_SNFORMAT_IEEE_REG128 9
|
||||
#define I2O_SNFORMAT_UNKNOWN2 0xff
|
||||
|
||||
/* Transaction Reply Lists (TRL) Control Word structure */
|
||||
|
||||
#define TRL_SINGLE_FIXED_LENGTH 0x00
|
||||
#define TRL_SINGLE_VARIABLE_LENGTH 0x40
|
||||
#define TRL_MULTIPLE_FIXED_LENGTH 0x80
|
||||
|
||||
/*
|
||||
* Messaging API values
|
||||
*/
|
||||
|
||||
#define I2O_CMD_ADAPTER_ASSIGN 0xB3
|
||||
#define I2O_CMD_ADAPTER_READ 0xB2
|
||||
#define I2O_CMD_ADAPTER_RELEASE 0xB5
|
||||
#define I2O_CMD_BIOS_INFO_SET 0xA5
|
||||
#define I2O_CMD_BOOT_DEVICE_SET 0xA7
|
||||
#define I2O_CMD_CONFIG_VALIDATE 0xBB
|
||||
#define I2O_CMD_CONN_SETUP 0xCA
|
||||
#define I2O_CMD_DDM_DESTROY 0xB1
|
||||
#define I2O_CMD_DDM_ENABLE 0xD5
|
||||
#define I2O_CMD_DDM_QUIESCE 0xC7
|
||||
#define I2O_CMD_DDM_RESET 0xD9
|
||||
#define I2O_CMD_DDM_SUSPEND 0xAF
|
||||
#define I2O_CMD_DEVICE_ASSIGN 0xB7
|
||||
#define I2O_CMD_DEVICE_RELEASE 0xB9
|
||||
#define I2O_CMD_HRT_GET 0xA8
|
||||
#define I2O_CMD_ADAPTER_CLEAR 0xBE
|
||||
#define I2O_CMD_ADAPTER_CONNECT 0xC9
|
||||
#define I2O_CMD_ADAPTER_RESET 0xBD
|
||||
#define I2O_CMD_LCT_NOTIFY 0xA2
|
||||
#define I2O_CMD_OUTBOUND_INIT 0xA1
|
||||
#define I2O_CMD_PATH_ENABLE 0xD3
|
||||
#define I2O_CMD_PATH_QUIESCE 0xC5
|
||||
#define I2O_CMD_PATH_RESET 0xD7
|
||||
#define I2O_CMD_STATIC_MF_CREATE 0xDD
|
||||
#define I2O_CMD_STATIC_MF_RELEASE 0xDF
|
||||
#define I2O_CMD_STATUS_GET 0xA0
|
||||
#define I2O_CMD_SW_DOWNLOAD 0xA9
|
||||
#define I2O_CMD_SW_UPLOAD 0xAB
|
||||
#define I2O_CMD_SW_REMOVE 0xAD
|
||||
#define I2O_CMD_SYS_ENABLE 0xD1
|
||||
#define I2O_CMD_SYS_MODIFY 0xC1
|
||||
#define I2O_CMD_SYS_QUIESCE 0xC3
|
||||
#define I2O_CMD_SYS_TAB_SET 0xA3
|
||||
|
||||
#define I2O_CMD_UTIL_NOP 0x00
|
||||
#define I2O_CMD_UTIL_ABORT 0x01
|
||||
#define I2O_CMD_UTIL_CLAIM 0x09
|
||||
#define I2O_CMD_UTIL_RELEASE 0x0B
|
||||
#define I2O_CMD_UTIL_PARAMS_GET 0x06
|
||||
#define I2O_CMD_UTIL_PARAMS_SET 0x05
|
||||
#define I2O_CMD_UTIL_EVT_REGISTER 0x13
|
||||
#define I2O_CMD_UTIL_EVT_ACK 0x14
|
||||
#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10
|
||||
#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D
|
||||
#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F
|
||||
#define I2O_CMD_UTIL_LOCK 0x17
|
||||
#define I2O_CMD_UTIL_LOCK_RELEASE 0x19
|
||||
#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15
|
||||
|
||||
#define I2O_CMD_SCSI_EXEC 0x81
|
||||
#define I2O_CMD_SCSI_ABORT 0x83
|
||||
#define I2O_CMD_SCSI_BUSRESET 0x27
|
||||
|
||||
#define I2O_CMD_BLOCK_READ 0x30
|
||||
#define I2O_CMD_BLOCK_WRITE 0x31
|
||||
#define I2O_CMD_BLOCK_CFLUSH 0x37
|
||||
#define I2O_CMD_BLOCK_MLOCK 0x49
|
||||
#define I2O_CMD_BLOCK_MUNLOCK 0x4B
|
||||
#define I2O_CMD_BLOCK_MMOUNT 0x41
|
||||
#define I2O_CMD_BLOCK_MEJECT 0x43
|
||||
|
||||
#define I2O_PRIVATE_MSG 0xFF
|
||||
|
||||
/*
|
||||
* Init Outbound Q status
|
||||
*/
|
||||
|
||||
#define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS 0x01
|
||||
#define I2O_CMD_OUTBOUND_INIT_REJECTED 0x02
|
||||
#define I2O_CMD_OUTBOUND_INIT_FAILED 0x03
|
||||
#define I2O_CMD_OUTBOUND_INIT_COMPLETE 0x04
|
||||
|
||||
/*
|
||||
* I2O Get Status State values
|
||||
*/
|
||||
|
||||
#define ADAPTER_STATE_INITIALIZING 0x01
|
||||
#define ADAPTER_STATE_RESET 0x02
|
||||
#define ADAPTER_STATE_HOLD 0x04
|
||||
#define ADAPTER_STATE_READY 0x05
|
||||
#define ADAPTER_STATE_OPERATIONAL 0x08
|
||||
#define ADAPTER_STATE_FAILED 0x10
|
||||
#define ADAPTER_STATE_FAULTED 0x11
|
||||
|
||||
/* I2O API function return values */
|
||||
|
||||
#define I2O_RTN_NO_ERROR 0
|
||||
#define I2O_RTN_NOT_INIT 1
|
||||
#define I2O_RTN_FREE_Q_EMPTY 2
|
||||
#define I2O_RTN_TCB_ERROR 3
|
||||
#define I2O_RTN_TRANSACTION_ERROR 4
|
||||
#define I2O_RTN_ADAPTER_ALREADY_INIT 5
|
||||
#define I2O_RTN_MALLOC_ERROR 6
|
||||
#define I2O_RTN_ADPTR_NOT_REGISTERED 7
|
||||
#define I2O_RTN_MSG_REPLY_TIMEOUT 8
|
||||
#define I2O_RTN_NO_STATUS 9
|
||||
#define I2O_RTN_NO_FIRM_VER 10
|
||||
#define I2O_RTN_NO_LINK_SPEED 11
|
||||
|
||||
/* Reply message status defines for all messages */
|
||||
|
||||
#define I2O_REPLY_STATUS_SUCCESS 0x00
|
||||
#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
|
||||
#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
|
||||
#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
|
||||
#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
|
||||
#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
|
||||
#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
|
||||
#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08
|
||||
#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09
|
||||
#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A
|
||||
#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B
|
||||
#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80
|
||||
|
||||
/* Status codes and Error Information for Parameter functions */
|
||||
|
||||
#define I2O_PARAMS_STATUS_SUCCESS 0x00
|
||||
#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01
|
||||
#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02
|
||||
#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03
|
||||
#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04
|
||||
#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05
|
||||
#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06
|
||||
#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07
|
||||
#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08
|
||||
#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09
|
||||
#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A
|
||||
#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B
|
||||
#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C
|
||||
#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D
|
||||
#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E
|
||||
#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F
|
||||
#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10
|
||||
|
||||
/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error
|
||||
* messages: Table 3-2 Detailed Status Codes.*/
|
||||
|
||||
#define I2O_DSC_SUCCESS 0x0000
|
||||
#define I2O_DSC_BAD_KEY 0x0002
|
||||
#define I2O_DSC_TCL_ERROR 0x0003
|
||||
#define I2O_DSC_REPLY_BUFFER_FULL 0x0004
|
||||
#define I2O_DSC_NO_SUCH_PAGE 0x0005
|
||||
#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006
|
||||
#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007
|
||||
#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009
|
||||
#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A
|
||||
#define I2O_DSC_DEVICE_LOCKED 0x000B
|
||||
#define I2O_DSC_DEVICE_RESET 0x000C
|
||||
#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D
|
||||
#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E
|
||||
#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F
|
||||
#define I2O_DSC_INVALID_OFFSET 0x0010
|
||||
#define I2O_DSC_INVALID_PARAMETER 0x0011
|
||||
#define I2O_DSC_INVALID_REQUEST 0x0012
|
||||
#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013
|
||||
#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014
|
||||
#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015
|
||||
#define I2O_DSC_MISSING_PARAMETER 0x0016
|
||||
#define I2O_DSC_TIMEOUT 0x0017
|
||||
#define I2O_DSC_UNKNOWN_ERROR 0x0018
|
||||
#define I2O_DSC_UNKNOWN_FUNCTION 0x0019
|
||||
#define I2O_DSC_UNSUPPORTED_VERSION 0x001A
|
||||
#define I2O_DSC_DEVICE_BUSY 0x001B
|
||||
#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C
|
||||
|
||||
/* Device Claim Types */
|
||||
#define I2O_CLAIM_PRIMARY 0x01000000
|
||||
#define I2O_CLAIM_MANAGEMENT 0x02000000
|
||||
#define I2O_CLAIM_AUTHORIZED 0x03000000
|
||||
#define I2O_CLAIM_SECONDARY 0x04000000
|
||||
|
||||
/* Message header defines for VersionOffset */
|
||||
#define I2OVER15 0x0001
|
||||
#define I2OVER20 0x0002
|
||||
/* Default is 1.5, FIXME: Need support for both 1.5 and 2.0 */
|
||||
#define I2OVERSION I2OVER15
|
||||
#define SGL_OFFSET_0 I2OVERSION
|
||||
#define SGL_OFFSET_4 (0x0040 | I2OVERSION)
|
||||
#define SGL_OFFSET_5 (0x0050 | I2OVERSION)
|
||||
#define SGL_OFFSET_6 (0x0060 | I2OVERSION)
|
||||
#define SGL_OFFSET_7 (0x0070 | I2OVERSION)
|
||||
#define SGL_OFFSET_8 (0x0080 | I2OVERSION)
|
||||
#define SGL_OFFSET_9 (0x0090 | I2OVERSION)
|
||||
#define SGL_OFFSET_10 (0x00A0 | I2OVERSION)
|
||||
#define SGL_OFFSET_12 (0x00C0 | I2OVERSION)
|
||||
|
||||
#define TRL_OFFSET_5 (0x0050 | I2OVERSION)
|
||||
#define TRL_OFFSET_6 (0x0060 | I2OVERSION)
|
||||
|
||||
/* msg header defines for MsgFlags */
|
||||
#define MSG_STATIC 0x0100
|
||||
#define MSG_64BIT_CNTXT 0x0200
|
||||
#define MSG_MULTI_TRANS 0x1000
|
||||
#define MSG_FAIL 0x2000
|
||||
#define MSG_LAST 0x4000
|
||||
#define MSG_REPLY 0x8000
|
||||
|
||||
/* minimum size msg */
|
||||
#define THREE_WORD_MSG_SIZE 0x00030000
|
||||
#define FOUR_WORD_MSG_SIZE 0x00040000
|
||||
#define FIVE_WORD_MSG_SIZE 0x00050000
|
||||
#define SIX_WORD_MSG_SIZE 0x00060000
|
||||
#define SEVEN_WORD_MSG_SIZE 0x00070000
|
||||
#define EIGHT_WORD_MSG_SIZE 0x00080000
|
||||
#define NINE_WORD_MSG_SIZE 0x00090000
|
||||
#define TEN_WORD_MSG_SIZE 0x000A0000
|
||||
#define I2O_MESSAGE_SIZE(x) ((x)<<16)
|
||||
|
||||
|
||||
/* Special TID Assignments */
|
||||
|
||||
#define ADAPTER_TID 0
|
||||
#define HOST_TID 1
|
||||
|
||||
#define MSG_FRAME_SIZE 128
|
||||
#define NMBR_MSG_FRAMES 128
|
||||
|
||||
#define MSG_POOL_SIZE 16384
|
||||
|
||||
#define I2O_POST_WAIT_OK 0
|
||||
#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _SCSI_I2O_H */
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/***************************************************************************
|
||||
dpti_ioctl.h - description
|
||||
-------------------
|
||||
begin : Thu Sep 7 2000
|
||||
copyright : (C) 2001 by Adaptec
|
||||
|
||||
See Documentation/scsi/dpti.rst for history, notes, license info
|
||||
and credits
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This file is generated from osd_unix.h *
|
||||
* *************************************************************************/
|
||||
|
||||
#ifndef _dpti_ioctl_h
|
||||
#define _dpti_ioctl_h
|
||||
|
||||
// IOCTL interface commands
|
||||
|
||||
#ifndef _IOWR
|
||||
# define _IOWR(x,y,z) (((x)<<8)|y)
|
||||
#endif
|
||||
#ifndef _IOW
|
||||
# define _IOW(x,y,z) (((x)<<8)|y)
|
||||
#endif
|
||||
#ifndef _IOR
|
||||
# define _IOR(x,y,z) (((x)<<8)|y)
|
||||
#endif
|
||||
#ifndef _IO
|
||||
# define _IO(x,y) (((x)<<8)|y)
|
||||
#endif
|
||||
/* EATA PassThrough Command */
|
||||
#define EATAUSRCMD _IOWR('D',65,EATA_CP)
|
||||
/* Set Debug Level If Enabled */
|
||||
#define DPT_DEBUG _IOW('D',66,int)
|
||||
/* Get Signature Structure */
|
||||
#define DPT_SIGNATURE _IOR('D',67,dpt_sig_S)
|
||||
#if defined __bsdi__
|
||||
#define DPT_SIGNATURE_PACKED _IOR('D',67,dpt_sig_S_Packed)
|
||||
#endif
|
||||
/* Get Number Of DPT Adapters */
|
||||
#define DPT_NUMCTRLS _IOR('D',68,int)
|
||||
/* Get Adapter Info Structure */
|
||||
#define DPT_CTRLINFO _IOR('D',69,CtrlInfo)
|
||||
/* Get Statistics If Enabled */
|
||||
#define DPT_STATINFO _IO('D',70)
|
||||
/* Clear Stats If Enabled */
|
||||
#define DPT_CLRSTAT _IO('D',71)
|
||||
/* Get System Info Structure */
|
||||
#define DPT_SYSINFO _IOR('D',72,sysInfo_S)
|
||||
/* Set Timeout Value */
|
||||
#define DPT_TIMEOUT _IO('D',73)
|
||||
/* Get config Data */
|
||||
#define DPT_CONFIG _IO('D',74)
|
||||
/* Get Blink LED Code */
|
||||
#define DPT_BLINKLED _IOR('D',75,int)
|
||||
/* Get Statistical information (if available) */
|
||||
#define DPT_STATS_INFO _IOR('D',80,STATS_DATA)
|
||||
/* Clear the statistical information */
|
||||
#define DPT_STATS_CLEAR _IO('D',81)
|
||||
/* Get Performance metrics */
|
||||
#define DPT_PERF_INFO _IOR('D',82,dpt_perf_t)
|
||||
/* Send an I2O command */
|
||||
#define I2OUSRCMD _IO('D',76)
|
||||
/* Inform driver to re-acquire LCT information */
|
||||
#define I2ORESCANCMD _IO('D',77)
|
||||
/* Inform driver to reset adapter */
|
||||
#define I2ORESETCMD _IO('D',78)
|
||||
/* See if the target is mounted */
|
||||
#define DPT_TARGET_BUSY _IOR('D',79, TARGET_BUSY_T)
|
||||
|
||||
|
||||
/* Structure Returned From Get Controller Info */
|
||||
|
||||
typedef struct {
|
||||
uCHAR state; /* Operational state */
|
||||
uCHAR id; /* Host adapter SCSI id */
|
||||
int vect; /* Interrupt vector number */
|
||||
int base; /* Base I/O address */
|
||||
int njobs; /* # of jobs sent to HA */
|
||||
int qdepth; /* Controller queue depth. */
|
||||
int wakebase; /* mpx wakeup base index. */
|
||||
uINT SGsize; /* Scatter/Gather list size. */
|
||||
unsigned heads; /* heads for drives on cntlr. */
|
||||
unsigned sectors; /* sectors for drives on cntlr. */
|
||||
uCHAR do_drive32; /* Flag for Above 16 MB Ability */
|
||||
uCHAR BusQuiet; /* SCSI Bus Quiet Flag */
|
||||
char idPAL[4]; /* 4 Bytes Of The ID Pal */
|
||||
uCHAR primary; /* 1 For Primary, 0 For Secondary */
|
||||
uCHAR eataVersion; /* EATA Version */
|
||||
uINT cpLength; /* EATA Command Packet Length */
|
||||
uINT spLength; /* EATA Status Packet Length */
|
||||
uCHAR drqNum; /* DRQ Index (0,5,6,7) */
|
||||
uCHAR flag1; /* EATA Flags 1 (Byte 9) */
|
||||
uCHAR flag2; /* EATA Flags 2 (Byte 30) */
|
||||
} CtrlInfo;
|
||||
|
||||
typedef struct {
|
||||
uSHORT length; // Remaining length of this
|
||||
uSHORT drvrHBAnum; // Relative HBA # used by the driver
|
||||
uINT baseAddr; // Base I/O address
|
||||
uSHORT blinkState; // Blink LED state (0=Not in blink LED)
|
||||
uCHAR pciBusNum; // PCI Bus # (Optional)
|
||||
uCHAR pciDeviceNum; // PCI Device # (Optional)
|
||||
uSHORT hbaFlags; // Miscellaneous HBA flags
|
||||
uSHORT Interrupt; // Interrupt set for this device.
|
||||
# if (defined(_DPT_ARC))
|
||||
uINT baseLength;
|
||||
ADAPTER_OBJECT *AdapterObject;
|
||||
LARGE_INTEGER DmaLogicalAddress;
|
||||
PVOID DmaVirtualAddress;
|
||||
LARGE_INTEGER ReplyLogicalAddress;
|
||||
PVOID ReplyVirtualAddress;
|
||||
# else
|
||||
uINT reserved1; // Reserved for future expansion
|
||||
uINT reserved2; // Reserved for future expansion
|
||||
uINT reserved3; // Reserved for future expansion
|
||||
# endif
|
||||
} drvrHBAinfo_S;
|
||||
|
||||
typedef struct TARGET_BUSY
|
||||
{
|
||||
uLONG channel;
|
||||
uLONG id;
|
||||
uLONG lun;
|
||||
uLONG isBusy;
|
||||
} TARGET_BUSY_T;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,336 +0,0 @@
|
|||
/* BSDI dptsig.h,v 1.7 1998/06/03 19:15:00 karels Exp */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-1999 Distributed Processing Technology Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source form, with or without modification, are
|
||||
* permitted provided that redistributions of source code must retain the
|
||||
* above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* This software is provided `as is' by Distributed Processing Technology 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 Distributed Processing Technology 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
|
||||
* interruptions) 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 driver software, even if advised
|
||||
* of the possibility of such damage.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DPTSIG_H_
|
||||
#define __DPTSIG_H_
|
||||
#ifdef _SINIX_ADDON
|
||||
#include "dpt.h"
|
||||
#endif
|
||||
/* DPT SIGNATURE SPEC AND HEADER FILE */
|
||||
/* Signature Version 1 (sorry no 'A') */
|
||||
|
||||
/* to make sure we are talking the same size under all OS's */
|
||||
typedef unsigned char sigBYTE;
|
||||
typedef unsigned short sigWORD;
|
||||
typedef unsigned int sigINT;
|
||||
|
||||
/*
|
||||
* use sigWORDLittleEndian for:
|
||||
* dsCapabilities
|
||||
* dsDeviceSupp
|
||||
* dsAdapterSupp
|
||||
* dsApplication
|
||||
* use sigLONGLittleEndian for:
|
||||
* dsOS
|
||||
* so that the sig can be standardised to Little Endian
|
||||
*/
|
||||
#if (defined(_DPT_BIG_ENDIAN))
|
||||
# define sigWORDLittleEndian(x) ((((x)&0xFF)<<8)|(((x)>>8)&0xFF))
|
||||
# define sigLONGLittleEndian(x) \
|
||||
((((x)&0xFF)<<24) | \
|
||||
(((x)&0xFF00)<<8) | \
|
||||
(((x)&0xFF0000L)>>8) | \
|
||||
(((x)&0xFF000000L)>>24))
|
||||
#else
|
||||
# define sigWORDLittleEndian(x) (x)
|
||||
# define sigLONGLittleEndian(x) (x)
|
||||
#endif
|
||||
|
||||
/* must make sure the structure is not word or double-word aligned */
|
||||
/* --------------------------------------------------------------- */
|
||||
/* Borland will ignore the following pragma: */
|
||||
/* Word alignment is OFF by default. If in the, IDE make */
|
||||
/* sure that Options | Compiler | Code Generation | Word Alignment */
|
||||
/* is not checked. If using BCC, do not use the -a option. */
|
||||
|
||||
#ifndef NO_PACK
|
||||
#if defined (_DPT_AIX)
|
||||
#pragma options align=packed
|
||||
#else
|
||||
#pragma pack(1)
|
||||
#endif /* aix */
|
||||
#endif
|
||||
/* For the Macintosh */
|
||||
#ifdef STRUCTALIGNMENTSUPPORTED
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
|
||||
|
||||
/* Current Signature Version - sigBYTE dsSigVersion; */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define SIG_VERSION 1
|
||||
|
||||
/* Processor Family - sigBYTE dsProcessorFamily; DISTINCT VALUES */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* What type of processor the file is meant to run on. */
|
||||
/* This will let us know whether to read sigWORDs as high/low or low/high. */
|
||||
#define PROC_INTEL 0x00 /* Intel 80x86/ia64 */
|
||||
#define PROC_MOTOROLA 0x01 /* Motorola 68K */
|
||||
#define PROC_MIPS4000 0x02 /* MIPS RISC 4000 */
|
||||
#define PROC_ALPHA 0x03 /* DEC Alpha */
|
||||
#define PROC_POWERPC 0x04 /* IBM Power PC */
|
||||
#define PROC_i960 0x05 /* Intel i960 */
|
||||
#define PROC_ULTRASPARC 0x06 /* SPARC processor */
|
||||
|
||||
/* Specific Minimim Processor - sigBYTE dsProcessor; FLAG BITS */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Different bit definitions dependent on processor_family */
|
||||
|
||||
/* PROC_INTEL: */
|
||||
#define PROC_8086 0x01 /* Intel 8086 */
|
||||
#define PROC_286 0x02 /* Intel 80286 */
|
||||
#define PROC_386 0x04 /* Intel 80386 */
|
||||
#define PROC_486 0x08 /* Intel 80486 */
|
||||
#define PROC_PENTIUM 0x10 /* Intel 586 aka P5 aka Pentium */
|
||||
#define PROC_SEXIUM 0x20 /* Intel 686 aka P6 aka Pentium Pro or MMX */
|
||||
#define PROC_IA64 0x40 /* Intel IA64 processor */
|
||||
|
||||
/* PROC_i960: */
|
||||
#define PROC_960RX 0x01 /* Intel 80960RC/RD */
|
||||
#define PROC_960HX 0x02 /* Intel 80960HA/HD/HT */
|
||||
|
||||
/* PROC_MOTOROLA: */
|
||||
#define PROC_68000 0x01 /* Motorola 68000 */
|
||||
#define PROC_68010 0x02 /* Motorola 68010 */
|
||||
#define PROC_68020 0x04 /* Motorola 68020 */
|
||||
#define PROC_68030 0x08 /* Motorola 68030 */
|
||||
#define PROC_68040 0x10 /* Motorola 68040 */
|
||||
|
||||
/* PROC_POWERPC */
|
||||
#define PROC_PPC601 0x01 /* PowerPC 601 */
|
||||
#define PROC_PPC603 0x02 /* PowerPC 603 */
|
||||
#define PROC_PPC604 0x04 /* PowerPC 604 */
|
||||
|
||||
/* PROC_MIPS4000: */
|
||||
#define PROC_R4000 0x01 /* MIPS R4000 */
|
||||
|
||||
/* Filetype - sigBYTE dsFiletype; DISTINCT VALUES */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define FT_EXECUTABLE 0 /* Executable Program */
|
||||
#define FT_SCRIPT 1 /* Script/Batch File??? */
|
||||
#define FT_HBADRVR 2 /* HBA Driver */
|
||||
#define FT_OTHERDRVR 3 /* Other Driver */
|
||||
#define FT_IFS 4 /* Installable Filesystem Driver */
|
||||
#define FT_ENGINE 5 /* DPT Engine */
|
||||
#define FT_COMPDRVR 6 /* Compressed Driver Disk */
|
||||
#define FT_LANGUAGE 7 /* Foreign Language file */
|
||||
#define FT_FIRMWARE 8 /* Downloadable or actual Firmware */
|
||||
#define FT_COMMMODL 9 /* Communications Module */
|
||||
#define FT_INT13 10 /* INT 13 style HBA Driver */
|
||||
#define FT_HELPFILE 11 /* Help file */
|
||||
#define FT_LOGGER 12 /* Event Logger */
|
||||
#define FT_INSTALL 13 /* An Install Program */
|
||||
#define FT_LIBRARY 14 /* Storage Manager Real-Mode Calls */
|
||||
#define FT_RESOURCE 15 /* Storage Manager Resource File */
|
||||
#define FT_MODEM_DB 16 /* Storage Manager Modem Database */
|
||||
|
||||
/* Filetype flags - sigBYTE dsFiletypeFlags; FLAG BITS */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define FTF_DLL 0x01 /* Dynamic Link Library */
|
||||
#define FTF_NLM 0x02 /* Netware Loadable Module */
|
||||
#define FTF_OVERLAYS 0x04 /* Uses overlays */
|
||||
#define FTF_DEBUG 0x08 /* Debug version */
|
||||
#define FTF_TSR 0x10 /* TSR */
|
||||
#define FTF_SYS 0x20 /* DOS Loadable driver */
|
||||
#define FTF_PROTECTED 0x40 /* Runs in protected mode */
|
||||
#define FTF_APP_SPEC 0x80 /* Application Specific */
|
||||
#define FTF_ROM (FTF_SYS|FTF_TSR) /* Special Case */
|
||||
|
||||
/* OEM - sigBYTE dsOEM; DISTINCT VALUES */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define OEM_DPT 0 /* DPT */
|
||||
#define OEM_ATT 1 /* ATT */
|
||||
#define OEM_NEC 2 /* NEC */
|
||||
#define OEM_ALPHA 3 /* Alphatronix */
|
||||
#define OEM_AST 4 /* AST */
|
||||
#define OEM_OLIVETTI 5 /* Olivetti */
|
||||
#define OEM_SNI 6 /* Siemens/Nixdorf */
|
||||
#define OEM_SUN 7 /* SUN Microsystems */
|
||||
|
||||
/* Operating System - sigLONG dsOS; FLAG BITS */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define OS_DOS 0x00000001 /* PC/MS-DOS */
|
||||
#define OS_WINDOWS 0x00000002 /* Microsoft Windows 3.x */
|
||||
#define OS_WINDOWS_NT 0x00000004 /* Microsoft Windows NT */
|
||||
#define OS_OS2M 0x00000008 /* OS/2 1.2.x,MS 1.3.0,IBM 1.3.x - Monolithic */
|
||||
#define OS_OS2L 0x00000010 /* Microsoft OS/2 1.301 - LADDR */
|
||||
#define OS_OS22x 0x00000020 /* IBM OS/2 2.x */
|
||||
#define OS_NW286 0x00000040 /* Novell NetWare 286 */
|
||||
#define OS_NW386 0x00000080 /* Novell NetWare 386 */
|
||||
#define OS_GEN_UNIX 0x00000100 /* Generic Unix */
|
||||
#define OS_SCO_UNIX 0x00000200 /* SCO Unix */
|
||||
#define OS_ATT_UNIX 0x00000400 /* ATT Unix */
|
||||
#define OS_UNIXWARE 0x00000800 /* USL Unix */
|
||||
#define OS_INT_UNIX 0x00001000 /* Interactive Unix */
|
||||
#define OS_SOLARIS 0x00002000 /* SunSoft Solaris */
|
||||
#define OS_QNX 0x00004000 /* QNX for Tom Moch */
|
||||
#define OS_NEXTSTEP 0x00008000 /* NeXTSTEP/OPENSTEP/MACH */
|
||||
#define OS_BANYAN 0x00010000 /* Banyan Vines */
|
||||
#define OS_OLIVETTI_UNIX 0x00020000/* Olivetti Unix */
|
||||
#define OS_MAC_OS 0x00040000 /* Mac OS */
|
||||
#define OS_WINDOWS_95 0x00080000 /* Microsoft Windows '95 */
|
||||
#define OS_NW4x 0x00100000 /* Novell Netware 4.x */
|
||||
#define OS_BSDI_UNIX 0x00200000 /* BSDi Unix BSD/OS 2.0 and up */
|
||||
#define OS_AIX_UNIX 0x00400000 /* AIX Unix */
|
||||
#define OS_FREE_BSD 0x00800000 /* FreeBSD Unix */
|
||||
#define OS_LINUX 0x01000000 /* Linux */
|
||||
#define OS_DGUX_UNIX 0x02000000 /* Data General Unix */
|
||||
#define OS_SINIX_N 0x04000000 /* SNI SINIX-N */
|
||||
#define OS_PLAN9 0x08000000 /* ATT Plan 9 */
|
||||
#define OS_TSX 0x10000000 /* SNH TSX-32 */
|
||||
|
||||
#define OS_OTHER 0x80000000 /* Other */
|
||||
|
||||
/* Capabilities - sigWORD dsCapabilities; FLAG BITS */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define CAP_RAID0 0x0001 /* RAID-0 */
|
||||
#define CAP_RAID1 0x0002 /* RAID-1 */
|
||||
#define CAP_RAID3 0x0004 /* RAID-3 */
|
||||
#define CAP_RAID5 0x0008 /* RAID-5 */
|
||||
#define CAP_SPAN 0x0010 /* Spanning */
|
||||
#define CAP_PASS 0x0020 /* Provides passthrough */
|
||||
#define CAP_OVERLAP 0x0040 /* Passthrough supports overlapped commands */
|
||||
#define CAP_ASPI 0x0080 /* Supports ASPI Command Requests */
|
||||
#define CAP_ABOVE16MB 0x0100 /* ISA Driver supports greater than 16MB */
|
||||
#define CAP_EXTEND 0x8000 /* Extended info appears after description */
|
||||
#ifdef SNI_MIPS
|
||||
#define CAP_CACHEMODE 0x1000 /* dpt_force_cache is set in driver */
|
||||
#endif
|
||||
|
||||
/* Devices Supported - sigWORD dsDeviceSupp; FLAG BITS */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define DEV_DASD 0x0001 /* DASD (hard drives) */
|
||||
#define DEV_TAPE 0x0002 /* Tape drives */
|
||||
#define DEV_PRINTER 0x0004 /* Printers */
|
||||
#define DEV_PROC 0x0008 /* Processors */
|
||||
#define DEV_WORM 0x0010 /* WORM drives */
|
||||
#define DEV_CDROM 0x0020 /* CD-ROM drives */
|
||||
#define DEV_SCANNER 0x0040 /* Scanners */
|
||||
#define DEV_OPTICAL 0x0080 /* Optical Drives */
|
||||
#define DEV_JUKEBOX 0x0100 /* Jukebox */
|
||||
#define DEV_COMM 0x0200 /* Communications Devices */
|
||||
#define DEV_OTHER 0x0400 /* Other Devices */
|
||||
#define DEV_ALL 0xFFFF /* All SCSI Devices */
|
||||
|
||||
/* Adapters Families Supported - sigWORD dsAdapterSupp; FLAG BITS */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define ADF_2001 0x0001 /* PM2001 */
|
||||
#define ADF_2012A 0x0002 /* PM2012A */
|
||||
#define ADF_PLUS_ISA 0x0004 /* PM2011,PM2021 */
|
||||
#define ADF_PLUS_EISA 0x0008 /* PM2012B,PM2022 */
|
||||
#define ADF_SC3_ISA 0x0010 /* PM2021 */
|
||||
#define ADF_SC3_EISA 0x0020 /* PM2022,PM2122, etc */
|
||||
#define ADF_SC3_PCI 0x0040 /* SmartCache III PCI */
|
||||
#define ADF_SC4_ISA 0x0080 /* SmartCache IV ISA */
|
||||
#define ADF_SC4_EISA 0x0100 /* SmartCache IV EISA */
|
||||
#define ADF_SC4_PCI 0x0200 /* SmartCache IV PCI */
|
||||
#define ADF_SC5_PCI 0x0400 /* Fifth Generation I2O products */
|
||||
/*
|
||||
* Combinations of products
|
||||
*/
|
||||
#define ADF_ALL_2000 (ADF_2001|ADF_2012A)
|
||||
#define ADF_ALL_PLUS (ADF_PLUS_ISA|ADF_PLUS_EISA)
|
||||
#define ADF_ALL_SC3 (ADF_SC3_ISA|ADF_SC3_EISA|ADF_SC3_PCI)
|
||||
#define ADF_ALL_SC4 (ADF_SC4_ISA|ADF_SC4_EISA|ADF_SC4_PCI)
|
||||
#define ADF_ALL_SC5 (ADF_SC5_PCI)
|
||||
/* All EATA Cacheing Products */
|
||||
#define ADF_ALL_CACHE (ADF_ALL_PLUS|ADF_ALL_SC3|ADF_ALL_SC4)
|
||||
/* All EATA Bus Mastering Products */
|
||||
#define ADF_ALL_MASTER (ADF_2012A|ADF_ALL_CACHE)
|
||||
/* All EATA Adapter Products */
|
||||
#define ADF_ALL_EATA (ADF_2001|ADF_ALL_MASTER)
|
||||
#define ADF_ALL ADF_ALL_EATA
|
||||
|
||||
/* Application - sigWORD dsApplication; FLAG BITS */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define APP_DPTMGR 0x0001 /* DPT Storage Manager */
|
||||
#define APP_ENGINE 0x0002 /* DPT Engine */
|
||||
#define APP_SYTOS 0x0004 /* Sytron Sytos Plus */
|
||||
#define APP_CHEYENNE 0x0008 /* Cheyenne ARCServe + ARCSolo */
|
||||
#define APP_MSCDEX 0x0010 /* Microsoft CD-ROM extensions */
|
||||
#define APP_NOVABACK 0x0020 /* NovaStor Novaback */
|
||||
#define APP_AIM 0x0040 /* Archive Information Manager */
|
||||
|
||||
/* Requirements - sigBYTE dsRequirements; FLAG BITS */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define REQ_SMARTROM 0x01 /* Requires SmartROM to be present */
|
||||
#define REQ_DPTDDL 0x02 /* Requires DPTDDL.SYS to be loaded */
|
||||
#define REQ_HBA_DRIVER 0x04 /* Requires an HBA driver to be loaded */
|
||||
#define REQ_ASPI_TRAN 0x08 /* Requires an ASPI Transport Modules */
|
||||
#define REQ_ENGINE 0x10 /* Requires a DPT Engine to be loaded */
|
||||
#define REQ_COMM_ENG 0x20 /* Requires a DPT Communications Engine */
|
||||
|
||||
/*
|
||||
* You may adjust dsDescription_size with an override to a value less than
|
||||
* 50 so that the structure allocates less real space.
|
||||
*/
|
||||
#if (!defined(dsDescription_size))
|
||||
# define dsDescription_size 50
|
||||
#endif
|
||||
|
||||
typedef struct dpt_sig {
|
||||
char dsSignature[6]; /* ALWAYS "dPtSiG" */
|
||||
sigBYTE dsSigVersion; /* signature version (currently 1) */
|
||||
sigBYTE dsProcessorFamily; /* what type of processor */
|
||||
sigBYTE dsProcessor; /* precise processor */
|
||||
sigBYTE dsFiletype; /* type of file */
|
||||
sigBYTE dsFiletypeFlags; /* flags to specify load type, etc. */
|
||||
sigBYTE dsOEM; /* OEM file was created for */
|
||||
sigINT dsOS; /* which Operating systems */
|
||||
sigWORD dsCapabilities; /* RAID levels, etc. */
|
||||
sigWORD dsDeviceSupp; /* Types of SCSI devices supported */
|
||||
sigWORD dsAdapterSupp; /* DPT adapter families supported */
|
||||
sigWORD dsApplication; /* applications file is for */
|
||||
sigBYTE dsRequirements; /* Other driver dependencies */
|
||||
sigBYTE dsVersion; /* 1 */
|
||||
sigBYTE dsRevision; /* 'J' */
|
||||
sigBYTE dsSubRevision; /* '9' ' ' if N/A */
|
||||
sigBYTE dsMonth; /* creation month */
|
||||
sigBYTE dsDay; /* creation day */
|
||||
sigBYTE dsYear; /* creation year since 1980 (1993=13) */
|
||||
/* description (NULL terminated) */
|
||||
char dsDescription[dsDescription_size];
|
||||
} dpt_sig_S;
|
||||
/* 32 bytes minimum - with no description. Put NULL at description[0] */
|
||||
/* 81 bytes maximum - with 49 character description plus NULL. */
|
||||
|
||||
/* This line added at Roycroft's request */
|
||||
/* Microsoft's NT compiler gets confused if you do a pack and don't */
|
||||
/* restore it. */
|
||||
|
||||
#ifndef NO_UNPACK
|
||||
#if defined (_DPT_AIX)
|
||||
#pragma options align=reset
|
||||
#elif defined (UNPACK_FOUR)
|
||||
#pragma pack(4)
|
||||
#else
|
||||
#pragma pack()
|
||||
#endif /* aix */
|
||||
#endif
|
||||
/* For the Macintosh */
|
||||
#ifdef STRUCTALIGNMENTSUPPORTED
|
||||
#pragma options align=reset
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/* BSDI osd_defs.h,v 1.4 1998/06/03 19:14:58 karels Exp */
|
||||
/*
|
||||
* Copyright (c) 1996-1999 Distributed Processing Technology Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source form, with or without modification, are
|
||||
* permitted provided that redistributions of source code must retain the
|
||||
* above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* This software is provided `as is' by Distributed Processing Technology 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 Distributed Processing Technology 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
|
||||
* interruptions) 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 driver software, even if advised
|
||||
* of the possibility of such damage.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _OSD_DEFS_H
|
||||
#define _OSD_DEFS_H
|
||||
|
||||
/*File - OSD_DEFS.H
|
||||
****************************************************************************
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This file contains the OS dependent defines. This file is included
|
||||
*in osd_util.h and provides the OS specific defines for that file.
|
||||
*
|
||||
*Copyright Distributed Processing Technology, Corp.
|
||||
* 140 Candace Dr.
|
||||
* Maitland, Fl. 32751 USA
|
||||
* Phone: (407) 830-5522 Fax: (407) 260-5366
|
||||
* All Rights Reserved
|
||||
*
|
||||
*Author: Doug Anderson
|
||||
*Date: 1/31/94
|
||||
*
|
||||
*Editors:
|
||||
*
|
||||
*Remarks:
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/*Definitions - Defines & Constants ----------------------------------------- */
|
||||
|
||||
/* Define the operating system */
|
||||
#if (defined(__linux__))
|
||||
# define _DPT_LINUX
|
||||
#elif (defined(__bsdi__))
|
||||
# define _DPT_BSDI
|
||||
#elif (defined(__FreeBSD__))
|
||||
# define _DPT_FREE_BSD
|
||||
#else
|
||||
# define _DPT_SCO
|
||||
#endif
|
||||
|
||||
#if defined (ZIL_CURSES)
|
||||
#define _DPT_CURSES
|
||||
#else
|
||||
#define _DPT_MOTIF
|
||||
#endif
|
||||
|
||||
/* Redefine 'far' to nothing - no far pointer type required in UNIX */
|
||||
#define far
|
||||
|
||||
/* Define the mutually exclusive semaphore type */
|
||||
#define SEMAPHORE_T unsigned int *
|
||||
/* Define a handle to a DLL */
|
||||
#define DLL_HANDLE_T unsigned int *
|
||||
|
||||
#endif
|
||||
|
|
@ -1,358 +0,0 @@
|
|||
/* BSDI osd_util.h,v 1.8 1998/06/03 19:14:58 karels Exp */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-1999 Distributed Processing Technology Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source form, with or without modification, are
|
||||
* permitted provided that redistributions of source code must retain the
|
||||
* above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* This software is provided `as is' by Distributed Processing Technology 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 Distributed Processing Technology 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
|
||||
* interruptions) 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 driver software, even if advised
|
||||
* of the possibility of such damage.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OSD_UTIL_H
|
||||
#define __OSD_UTIL_H
|
||||
|
||||
/*File - OSD_UTIL.H
|
||||
****************************************************************************
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This file contains defines and function prototypes that are
|
||||
*operating system dependent. The resources defined in this file
|
||||
*are not specific to any particular application.
|
||||
*
|
||||
*Copyright Distributed Processing Technology, Corp.
|
||||
* 140 Candace Dr.
|
||||
* Maitland, Fl. 32751 USA
|
||||
* Phone: (407) 830-5522 Fax: (407) 260-5366
|
||||
* All Rights Reserved
|
||||
*
|
||||
*Author: Doug Anderson
|
||||
*Date: 1/7/94
|
||||
*
|
||||
*Editors:
|
||||
*
|
||||
*Remarks:
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/*Definitions - Defines & Constants ----------------------------------------- */
|
||||
|
||||
/*----------------------------- */
|
||||
/* Operating system selections: */
|
||||
/*----------------------------- */
|
||||
|
||||
/*#define _DPT_MSDOS */
|
||||
/*#define _DPT_WIN_3X */
|
||||
/*#define _DPT_WIN_4X */
|
||||
/*#define _DPT_WIN_NT */
|
||||
/*#define _DPT_NETWARE */
|
||||
/*#define _DPT_OS2 */
|
||||
/*#define _DPT_SCO */
|
||||
/*#define _DPT_UNIXWARE */
|
||||
/*#define _DPT_SOLARIS */
|
||||
/*#define _DPT_NEXTSTEP */
|
||||
/*#define _DPT_BANYAN */
|
||||
|
||||
/*-------------------------------- */
|
||||
/* Include the OS specific defines */
|
||||
/*-------------------------------- */
|
||||
|
||||
/*#define OS_SELECTION From Above List */
|
||||
/*#define SEMAPHORE_T ??? */
|
||||
/*#define DLL_HANDLE_T ??? */
|
||||
|
||||
#if (defined(KERNEL) && (defined(__FreeBSD__) || defined(__bsdi__)))
|
||||
# include "i386/isa/dpt_osd_defs.h"
|
||||
#else
|
||||
# include "osd_defs.h"
|
||||
#endif
|
||||
|
||||
#ifndef DPT_UNALIGNED
|
||||
#define DPT_UNALIGNED
|
||||
#endif
|
||||
|
||||
#ifndef DPT_EXPORT
|
||||
#define DPT_EXPORT
|
||||
#endif
|
||||
|
||||
#ifndef DPT_IMPORT
|
||||
#define DPT_IMPORT
|
||||
#endif
|
||||
|
||||
#ifndef DPT_RUNTIME_IMPORT
|
||||
#define DPT_RUNTIME_IMPORT DPT_IMPORT
|
||||
#endif
|
||||
|
||||
/*--------------------- */
|
||||
/* OS dependent defines */
|
||||
/*--------------------- */
|
||||
|
||||
#if defined (_DPT_MSDOS) || defined (_DPT_WIN_3X)
|
||||
#define _DPT_16_BIT
|
||||
#else
|
||||
#define _DPT_32_BIT
|
||||
#endif
|
||||
|
||||
#if defined (_DPT_SCO) || defined (_DPT_UNIXWARE) || defined (_DPT_SOLARIS) || defined (_DPT_AIX) || defined (SNI_MIPS) || defined (_DPT_BSDI) || defined (_DPT_FREE_BSD) || defined(_DPT_LINUX)
|
||||
#define _DPT_UNIX
|
||||
#endif
|
||||
|
||||
#if defined (_DPT_WIN_3x) || defined (_DPT_WIN_4X) || defined (_DPT_WIN_NT) \
|
||||
|| defined (_DPT_OS2)
|
||||
#define _DPT_DLL_SUPPORT
|
||||
#endif
|
||||
|
||||
#if !defined (_DPT_MSDOS) && !defined (_DPT_WIN_3X) && !defined (_DPT_NETWARE)
|
||||
#define _DPT_PREEMPTIVE
|
||||
#endif
|
||||
|
||||
#if !defined (_DPT_MSDOS) && !defined (_DPT_WIN_3X)
|
||||
#define _DPT_MULTI_THREADED
|
||||
#endif
|
||||
|
||||
#if !defined (_DPT_MSDOS)
|
||||
#define _DPT_MULTI_TASKING
|
||||
#endif
|
||||
|
||||
/* These exist for platforms that */
|
||||
/* chunk when accessing mis-aligned */
|
||||
/* data */
|
||||
#if defined (SNI_MIPS) || defined (_DPT_SOLARIS)
|
||||
#if defined (_DPT_BIG_ENDIAN)
|
||||
#if !defined (_DPT_STRICT_ALIGN)
|
||||
#define _DPT_STRICT_ALIGN
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Determine if in C or C++ mode */
|
||||
#ifdef __cplusplus
|
||||
#define _DPT_CPP
|
||||
#else
|
||||
#define _DPT_C
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* Under Solaris the compiler refuses to accept code like: */
|
||||
/* { {"DPT"}, 0, NULL .... }, */
|
||||
/* and complains about the {"DPT"} part by saying "cannot use { } */
|
||||
/* to initialize char*". */
|
||||
/* */
|
||||
/* By defining these ugly macros we can get around this and also */
|
||||
/* not have to copy and #ifdef large sections of code. I know that */
|
||||
/* these macros are *really* ugly, but they should help reduce */
|
||||
/* maintenance in the long run. */
|
||||
/* */
|
||||
/*-------------------------------------------------------------------*/
|
||||
#if !defined (DPTSQO)
|
||||
#if defined (_DPT_SOLARIS)
|
||||
#define DPTSQO
|
||||
#define DPTSQC
|
||||
#else
|
||||
#define DPTSQO {
|
||||
#define DPTSQC }
|
||||
#endif /* solaris */
|
||||
#endif /* DPTSQO */
|
||||
|
||||
|
||||
/*---------------------- */
|
||||
/* OS dependent typedefs */
|
||||
/*---------------------- */
|
||||
|
||||
#if defined (_DPT_MSDOS) || defined (_DPT_SCO)
|
||||
#define BYTE unsigned char
|
||||
#define WORD unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef _DPT_TYPEDEFS
|
||||
#define _DPT_TYPEDEFS
|
||||
typedef unsigned char uCHAR;
|
||||
typedef unsigned short uSHORT;
|
||||
typedef unsigned int uINT;
|
||||
typedef unsigned long uLONG;
|
||||
|
||||
typedef union {
|
||||
uCHAR u8[4];
|
||||
uSHORT u16[2];
|
||||
uLONG u32;
|
||||
} access_U;
|
||||
#endif
|
||||
|
||||
#if !defined (NULL)
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
/*Prototypes - function ----------------------------------------------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Declare all these functions as "C" functions */
|
||||
#endif
|
||||
|
||||
/*------------------------ */
|
||||
/* Byte reversal functions */
|
||||
/*------------------------ */
|
||||
|
||||
/* Reverses the byte ordering of a 2 byte variable */
|
||||
#if (!defined(osdSwap2))
|
||||
uSHORT osdSwap2(DPT_UNALIGNED uSHORT *);
|
||||
#endif // !osdSwap2
|
||||
|
||||
/* Reverses the byte ordering of a 4 byte variable and shifts left 8 bits */
|
||||
#if (!defined(osdSwap3))
|
||||
uLONG osdSwap3(DPT_UNALIGNED uLONG *);
|
||||
#endif // !osdSwap3
|
||||
|
||||
|
||||
#ifdef _DPT_NETWARE
|
||||
#include "novpass.h" /* For DPT_Bswapl() prototype */
|
||||
/* Inline the byte swap */
|
||||
#ifdef __cplusplus
|
||||
inline uLONG osdSwap4(uLONG *inLong) {
|
||||
return *inLong = DPT_Bswapl(*inLong);
|
||||
}
|
||||
#else
|
||||
#define osdSwap4(inLong) DPT_Bswapl(inLong)
|
||||
#endif // cplusplus
|
||||
#else
|
||||
/* Reverses the byte ordering of a 4 byte variable */
|
||||
# if (!defined(osdSwap4))
|
||||
uLONG osdSwap4(DPT_UNALIGNED uLONG *);
|
||||
# endif // !osdSwap4
|
||||
|
||||
/* The following functions ALWAYS swap regardless of the *
|
||||
* presence of DPT_BIG_ENDIAN */
|
||||
|
||||
uSHORT trueSwap2(DPT_UNALIGNED uSHORT *);
|
||||
uLONG trueSwap4(DPT_UNALIGNED uLONG *);
|
||||
|
||||
#endif // netware
|
||||
|
||||
|
||||
/*-------------------------------------*
|
||||
* Network order swap functions *
|
||||
* *
|
||||
* These functions/macros will be used *
|
||||
* by the structure insert()/extract() *
|
||||
* functions. *
|
||||
*
|
||||
* We will enclose all structure *
|
||||
* portability modifications inside *
|
||||
* #ifdefs. When we are ready, we *
|
||||
* will #define DPT_PORTABLE to begin *
|
||||
* using the modifications. *
|
||||
*-------------------------------------*/
|
||||
uLONG netSwap4(uLONG val);
|
||||
|
||||
#if defined (_DPT_BIG_ENDIAN)
|
||||
|
||||
// for big-endian we need to swap
|
||||
|
||||
#ifndef NET_SWAP_2
|
||||
#define NET_SWAP_2(x) (((x) >> 8) | ((x) << 8))
|
||||
#endif // NET_SWAP_2
|
||||
|
||||
#ifndef NET_SWAP_4
|
||||
#define NET_SWAP_4(x) netSwap4((x))
|
||||
#endif // NET_SWAP_4
|
||||
|
||||
#else
|
||||
|
||||
// for little-endian we don't need to do anything
|
||||
|
||||
#ifndef NET_SWAP_2
|
||||
#define NET_SWAP_2(x) (x)
|
||||
#endif // NET_SWAP_2
|
||||
|
||||
#ifndef NET_SWAP_4
|
||||
#define NET_SWAP_4(x) (x)
|
||||
#endif // NET_SWAP_4
|
||||
|
||||
#endif // big endian
|
||||
|
||||
|
||||
|
||||
/*----------------------------------- */
|
||||
/* Run-time loadable module functions */
|
||||
/*----------------------------------- */
|
||||
|
||||
/* Loads the specified run-time loadable DLL */
|
||||
DLL_HANDLE_T osdLoadModule(uCHAR *);
|
||||
/* Unloads the specified run-time loadable DLL */
|
||||
uSHORT osdUnloadModule(DLL_HANDLE_T);
|
||||
/* Returns a pointer to a function inside a run-time loadable DLL */
|
||||
void * osdGetFnAddr(DLL_HANDLE_T,uCHAR *);
|
||||
|
||||
/*--------------------------------------- */
|
||||
/* Mutually exclusive semaphore functions */
|
||||
/*--------------------------------------- */
|
||||
|
||||
/* Create a named semaphore */
|
||||
SEMAPHORE_T osdCreateNamedSemaphore(char *);
|
||||
/* Create a mutually exlusive semaphore */
|
||||
SEMAPHORE_T osdCreateSemaphore(void);
|
||||
/* create an event semaphore */
|
||||
SEMAPHORE_T osdCreateEventSemaphore(void);
|
||||
/* create a named event semaphore */
|
||||
SEMAPHORE_T osdCreateNamedEventSemaphore(char *);
|
||||
|
||||
/* Destroy the specified mutually exclusive semaphore object */
|
||||
uSHORT osdDestroySemaphore(SEMAPHORE_T);
|
||||
/* Request access to the specified mutually exclusive semaphore */
|
||||
uLONG osdRequestSemaphore(SEMAPHORE_T,uLONG);
|
||||
/* Release access to the specified mutually exclusive semaphore */
|
||||
uSHORT osdReleaseSemaphore(SEMAPHORE_T);
|
||||
/* wait for a event to happen */
|
||||
uLONG osdWaitForEventSemaphore(SEMAPHORE_T, uLONG);
|
||||
/* signal an event */
|
||||
uLONG osdSignalEventSemaphore(SEMAPHORE_T);
|
||||
/* reset the event */
|
||||
uLONG osdResetEventSemaphore(SEMAPHORE_T);
|
||||
|
||||
/*----------------- */
|
||||
/* Thread functions */
|
||||
/*----------------- */
|
||||
|
||||
/* Releases control to the task switcher in non-preemptive */
|
||||
/* multitasking operating systems. */
|
||||
void osdSwitchThreads(void);
|
||||
|
||||
/* Starts a thread function */
|
||||
uLONG osdStartThread(void *,void *);
|
||||
|
||||
/* what is my thread id */
|
||||
uLONG osdGetThreadID(void);
|
||||
|
||||
/* wakes up the specifed thread */
|
||||
void osdWakeThread(uLONG);
|
||||
|
||||
/* osd sleep for x milliseconds */
|
||||
void osdSleep(uLONG);
|
||||
|
||||
#define DPT_THREAD_PRIORITY_LOWEST 0x00
|
||||
#define DPT_THREAD_PRIORITY_NORMAL 0x01
|
||||
#define DPT_THREAD_PRIORITY_HIGHEST 0x02
|
||||
|
||||
uCHAR osdSetThreadPriority(uLONG tid, uCHAR priority);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end the xtern "C" declaration */
|
||||
#endif
|
||||
|
||||
#endif /* osd_util_h */
|
||||
|
|
@ -1,417 +0,0 @@
|
|||
/* BSDI sys_info.h,v 1.6 1998/06/03 19:14:59 karels Exp */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-1999 Distributed Processing Technology Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source form, with or without modification, are
|
||||
* permitted provided that redistributions of source code must retain the
|
||||
* above copyright notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* This software is provided `as is' by Distributed Processing Technology 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 Distributed Processing Technology 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
|
||||
* interruptions) 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 driver software, even if advised
|
||||
* of the possibility of such damage.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SYS_INFO_H
|
||||
#define __SYS_INFO_H
|
||||
|
||||
/*File - SYS_INFO.H
|
||||
****************************************************************************
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This file contains structure definitions for the OS dependent
|
||||
*layer system information buffers.
|
||||
*
|
||||
*Copyright Distributed Processing Technology, Corp.
|
||||
* 140 Candace Dr.
|
||||
* Maitland, Fl. 32751 USA
|
||||
* Phone: (407) 830-5522 Fax: (407) 260-5366
|
||||
* All Rights Reserved
|
||||
*
|
||||
*Author: Don Kemper
|
||||
*Date: 5/10/94
|
||||
*
|
||||
*Editors:
|
||||
*
|
||||
*Remarks:
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/*Include Files ------------------------------------------------------------- */
|
||||
|
||||
#include "osd_util.h"
|
||||
|
||||
#ifndef NO_PACK
|
||||
#if defined (_DPT_AIX)
|
||||
#pragma options align=packed
|
||||
#else
|
||||
#pragma pack(1)
|
||||
#endif /* aix */
|
||||
#endif // no unpack
|
||||
|
||||
|
||||
/*struct - driveParam_S - start
|
||||
*===========================================================================
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This structure defines the drive parameters seen during
|
||||
*booting.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct driveParam_S {
|
||||
#else
|
||||
typedef struct {
|
||||
#endif
|
||||
|
||||
uSHORT cylinders; /* Up to 1024 */
|
||||
uCHAR heads; /* Up to 255 */
|
||||
uCHAR sectors; /* Up to 63 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//---------- Portability Additions ----------- in sp_sinfo.cpp
|
||||
#ifdef DPT_PORTABLE
|
||||
uSHORT netInsert(dptBuffer_S *buffer);
|
||||
uSHORT netExtract(dptBuffer_S *buffer);
|
||||
#endif // DPT PORTABLE
|
||||
//--------------------------------------------
|
||||
|
||||
};
|
||||
#else
|
||||
} driveParam_S;
|
||||
#endif
|
||||
/*driveParam_S - end */
|
||||
|
||||
|
||||
/*struct - sysInfo_S - start
|
||||
*===========================================================================
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This structure defines the command system information that
|
||||
*should be returned by every OS dependent layer.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/*flags - bit definitions */
|
||||
#define SI_CMOS_Valid 0x0001
|
||||
#define SI_NumDrivesValid 0x0002
|
||||
#define SI_ProcessorValid 0x0004
|
||||
#define SI_MemorySizeValid 0x0008
|
||||
#define SI_DriveParamsValid 0x0010
|
||||
#define SI_SmartROMverValid 0x0020
|
||||
#define SI_OSversionValid 0x0040
|
||||
#define SI_OSspecificValid 0x0080 /* 1 if OS structure returned */
|
||||
#define SI_BusTypeValid 0x0100
|
||||
|
||||
#define SI_ALL_VALID 0x0FFF /* All Std SysInfo is valid */
|
||||
#define SI_NO_SmartROM 0x8000
|
||||
|
||||
/*busType - definitions */
|
||||
#define SI_ISA_BUS 0x00
|
||||
#define SI_MCA_BUS 0x01
|
||||
#define SI_EISA_BUS 0x02
|
||||
#define SI_PCI_BUS 0x04
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct sysInfo_S {
|
||||
#else
|
||||
typedef struct {
|
||||
#endif
|
||||
|
||||
uCHAR drive0CMOS; /* CMOS Drive 0 Type */
|
||||
uCHAR drive1CMOS; /* CMOS Drive 1 Type */
|
||||
uCHAR numDrives; /* 0040:0075 contents */
|
||||
uCHAR processorFamily; /* Same as DPTSIG's definition */
|
||||
uCHAR processorType; /* Same as DPTSIG's definition */
|
||||
uCHAR smartROMMajorVersion;
|
||||
uCHAR smartROMMinorVersion; /* SmartROM version */
|
||||
uCHAR smartROMRevision;
|
||||
uSHORT flags; /* See bit definitions above */
|
||||
uSHORT conventionalMemSize; /* in KB */
|
||||
uINT extendedMemSize; /* in KB */
|
||||
uINT osType; /* Same as DPTSIG's definition */
|
||||
uCHAR osMajorVersion;
|
||||
uCHAR osMinorVersion; /* The OS version */
|
||||
uCHAR osRevision;
|
||||
#ifdef _SINIX_ADDON
|
||||
uCHAR busType; /* See defininitions above */
|
||||
uSHORT osSubRevision;
|
||||
uCHAR pad[2]; /* For alignment */
|
||||
#else
|
||||
uCHAR osSubRevision;
|
||||
uCHAR busType; /* See defininitions above */
|
||||
uCHAR pad[3]; /* For alignment */
|
||||
#endif
|
||||
driveParam_S drives[16]; /* SmartROM Logical Drives */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//---------- Portability Additions ----------- in sp_sinfo.cpp
|
||||
#ifdef DPT_PORTABLE
|
||||
uSHORT netInsert(dptBuffer_S *buffer);
|
||||
uSHORT netExtract(dptBuffer_S *buffer);
|
||||
#endif // DPT PORTABLE
|
||||
//--------------------------------------------
|
||||
|
||||
};
|
||||
#else
|
||||
} sysInfo_S;
|
||||
#endif
|
||||
/*sysInfo_S - end */
|
||||
|
||||
|
||||
/*struct - DOS_Info_S - start
|
||||
*===========================================================================
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This structure defines the system information specific to a
|
||||
*DOS workstation.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/*flags - bit definitions */
|
||||
#define DI_DOS_HIGH 0x01 /* DOS is loaded high */
|
||||
#define DI_DPMI_VALID 0x02 /* DPMI version is valid */
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct DOS_Info_S {
|
||||
#else
|
||||
typedef struct {
|
||||
#endif
|
||||
|
||||
uCHAR flags; /* See bit definitions above */
|
||||
uSHORT driverLocation; /* SmartROM BIOS address */
|
||||
uSHORT DOS_version;
|
||||
uSHORT DPMI_version;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//---------- Portability Additions ----------- in sp_sinfo.cpp
|
||||
#ifdef DPT_PORTABLE
|
||||
uSHORT netInsert(dptBuffer_S *buffer);
|
||||
uSHORT netExtract(dptBuffer_S *buffer);
|
||||
#endif // DPT PORTABLE
|
||||
//--------------------------------------------
|
||||
|
||||
};
|
||||
#else
|
||||
} DOS_Info_S;
|
||||
#endif
|
||||
/*DOS_Info_S - end */
|
||||
|
||||
|
||||
/*struct - Netware_Info_S - start
|
||||
*===========================================================================
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This structure defines the system information specific to a
|
||||
*Netware machine.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct Netware_Info_S {
|
||||
#else
|
||||
typedef struct {
|
||||
#endif
|
||||
|
||||
uCHAR driverName[13]; /* ie PM12NW31.DSK */
|
||||
uCHAR serverName[48];
|
||||
uCHAR netwareVersion; /* The Netware OS version */
|
||||
uCHAR netwareSubVersion;
|
||||
uCHAR netwareRevision;
|
||||
uSHORT maxConnections; /* Probably 250 or 1000 */
|
||||
uSHORT connectionsInUse;
|
||||
uSHORT maxVolumes;
|
||||
uCHAR unused;
|
||||
uCHAR SFTlevel;
|
||||
uCHAR TTSlevel;
|
||||
|
||||
uCHAR clibMajorVersion; /* The CLIB.NLM version */
|
||||
uCHAR clibMinorVersion;
|
||||
uCHAR clibRevision;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//---------- Portability Additions ----------- in sp_sinfo.cpp
|
||||
#ifdef DPT_PORTABLE
|
||||
uSHORT netInsert(dptBuffer_S *buffer);
|
||||
uSHORT netExtract(dptBuffer_S *buffer);
|
||||
#endif // DPT PORTABLE
|
||||
//--------------------------------------------
|
||||
|
||||
};
|
||||
#else
|
||||
} Netware_Info_S;
|
||||
#endif
|
||||
/*Netware_Info_S - end */
|
||||
|
||||
|
||||
/*struct - OS2_Info_S - start
|
||||
*===========================================================================
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This structure defines the system information specific to an
|
||||
*OS/2 machine.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct OS2_Info_S {
|
||||
#else
|
||||
typedef struct {
|
||||
#endif
|
||||
|
||||
uCHAR something;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//---------- Portability Additions ----------- in sp_sinfo.cpp
|
||||
#ifdef DPT_PORTABLE
|
||||
uSHORT netInsert(dptBuffer_S *buffer);
|
||||
uSHORT netExtract(dptBuffer_S *buffer);
|
||||
#endif // DPT PORTABLE
|
||||
//--------------------------------------------
|
||||
|
||||
};
|
||||
#else
|
||||
} OS2_Info_S;
|
||||
#endif
|
||||
/*OS2_Info_S - end */
|
||||
|
||||
|
||||
/*struct - WinNT_Info_S - start
|
||||
*===========================================================================
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This structure defines the system information specific to a
|
||||
*Windows NT machine.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct WinNT_Info_S {
|
||||
#else
|
||||
typedef struct {
|
||||
#endif
|
||||
|
||||
uCHAR something;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//---------- Portability Additions ----------- in sp_sinfo.cpp
|
||||
#ifdef DPT_PORTABLE
|
||||
uSHORT netInsert(dptBuffer_S *buffer);
|
||||
uSHORT netExtract(dptBuffer_S *buffer);
|
||||
#endif // DPT PORTABLE
|
||||
//--------------------------------------------
|
||||
|
||||
};
|
||||
#else
|
||||
} WinNT_Info_S;
|
||||
#endif
|
||||
/*WinNT_Info_S - end */
|
||||
|
||||
|
||||
/*struct - SCO_Info_S - start
|
||||
*===========================================================================
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This structure defines the system information specific to an
|
||||
*SCO UNIX machine.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct SCO_Info_S {
|
||||
#else
|
||||
typedef struct {
|
||||
#endif
|
||||
|
||||
uCHAR something;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//---------- Portability Additions ----------- in sp_sinfo.cpp
|
||||
#ifdef DPT_PORTABLE
|
||||
uSHORT netInsert(dptBuffer_S *buffer);
|
||||
uSHORT netExtract(dptBuffer_S *buffer);
|
||||
#endif // DPT PORTABLE
|
||||
//--------------------------------------------
|
||||
|
||||
};
|
||||
#else
|
||||
} SCO_Info_S;
|
||||
#endif
|
||||
/*SCO_Info_S - end */
|
||||
|
||||
|
||||
/*struct - USL_Info_S - start
|
||||
*===========================================================================
|
||||
*
|
||||
*Description:
|
||||
*
|
||||
* This structure defines the system information specific to a
|
||||
*USL UNIX machine.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct USL_Info_S {
|
||||
#else
|
||||
typedef struct {
|
||||
#endif
|
||||
|
||||
uCHAR something;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
//---------- Portability Additions ----------- in sp_sinfo.cpp
|
||||
#ifdef DPT_PORTABLE
|
||||
uSHORT netInsert(dptBuffer_S *buffer);
|
||||
uSHORT netExtract(dptBuffer_S *buffer);
|
||||
#endif // DPT PORTABLE
|
||||
//--------------------------------------------
|
||||
|
||||
};
|
||||
#else
|
||||
} USL_Info_S;
|
||||
#endif
|
||||
/*USL_Info_S - end */
|
||||
|
||||
|
||||
/* Restore default structure packing */
|
||||
#ifndef NO_UNPACK
|
||||
#if defined (_DPT_AIX)
|
||||
#pragma options align=reset
|
||||
#elif defined (UNPACK_FOUR)
|
||||
#pragma pack(4)
|
||||
#else
|
||||
#pragma pack()
|
||||
#endif /* aix */
|
||||
#endif // no unpack
|
||||
|
||||
#endif // __SYS_INFO_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,331 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/***************************************************************************
|
||||
dpti.h - description
|
||||
-------------------
|
||||
begin : Thu Sep 7 2000
|
||||
copyright : (C) 2001 by Adaptec
|
||||
|
||||
See Documentation/scsi/dpti.rst for history, notes, license info
|
||||
and credits
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _DPT_H
|
||||
#define _DPT_H
|
||||
|
||||
#define MAX_TO_IOP_MESSAGES (255)
|
||||
#define MAX_FROM_IOP_MESSAGES (255)
|
||||
|
||||
|
||||
/*
|
||||
* SCSI interface function Prototypes
|
||||
*/
|
||||
|
||||
static int adpt_detect(struct scsi_host_template * sht);
|
||||
static int adpt_queue(struct Scsi_Host *h, struct scsi_cmnd * cmd);
|
||||
static int adpt_abort(struct scsi_cmnd * cmd);
|
||||
static int adpt_reset(struct scsi_cmnd* cmd);
|
||||
static int adpt_slave_configure(struct scsi_device *);
|
||||
|
||||
static const char *adpt_info(struct Scsi_Host *pSHost);
|
||||
static int adpt_bios_param(struct scsi_device * sdev, struct block_device *dev,
|
||||
sector_t, int geom[]);
|
||||
|
||||
static int adpt_bus_reset(struct scsi_cmnd* cmd);
|
||||
static int adpt_device_reset(struct scsi_cmnd* cmd);
|
||||
|
||||
|
||||
/*
|
||||
* struct scsi_host_template (see scsi/scsi_host.h)
|
||||
*/
|
||||
|
||||
#define DPT_DRIVER_NAME "Adaptec I2O RAID"
|
||||
|
||||
#ifndef HOSTS_C
|
||||
|
||||
#include "dpt/sys_info.h"
|
||||
#include <linux/wait.h>
|
||||
#include "dpt/dpti_i2o.h"
|
||||
#include "dpt/dpti_ioctl.h"
|
||||
|
||||
#define DPT_I2O_VERSION "2.4 Build 5go"
|
||||
#define DPT_VERSION 2
|
||||
#define DPT_REVISION '4'
|
||||
#define DPT_SUBREVISION '5'
|
||||
#define DPT_BETA ""
|
||||
#define DPT_MONTH 8
|
||||
#define DPT_DAY 7
|
||||
#define DPT_YEAR (2001-1980)
|
||||
|
||||
#define DPT_DRIVER "dpt_i2o"
|
||||
#define DPTI_I2O_MAJOR (151)
|
||||
#define DPT_ORGANIZATION_ID (0x1B) /* For Private Messages */
|
||||
#define DPTI_MAX_HBA (16)
|
||||
#define MAX_CHANNEL (5) // Maximum Channel # Supported
|
||||
#define MAX_ID (128) // Maximum Target ID Supported
|
||||
|
||||
/* Sizes in 4 byte words */
|
||||
#define REPLY_FRAME_SIZE (17)
|
||||
#define MAX_MESSAGE_SIZE (128)
|
||||
#define SG_LIST_ELEMENTS (56)
|
||||
|
||||
#define EMPTY_QUEUE 0xffffffff
|
||||
#define I2O_INTERRUPT_PENDING_B (0x08)
|
||||
|
||||
#define PCI_DPT_VENDOR_ID (0x1044) // DPT PCI Vendor ID
|
||||
#define PCI_DPT_DEVICE_ID (0xA501) // DPT PCI I2O Device ID
|
||||
#define PCI_DPT_RAPTOR_DEVICE_ID (0xA511)
|
||||
|
||||
/* Debugging macro from Linux Device Drivers - Rubini */
|
||||
#undef PDEBUG
|
||||
#ifdef DEBUG
|
||||
//TODO add debug level switch
|
||||
# define PDEBUG(fmt, args...) printk(KERN_DEBUG "dpti: " fmt, ##args)
|
||||
# define PDEBUGV(fmt, args...) printk(KERN_DEBUG "dpti: " fmt, ##args)
|
||||
#else
|
||||
# define PDEBUG(fmt, args...) /* not debugging: nothing */
|
||||
# define PDEBUGV(fmt, args...) /* not debugging: nothing */
|
||||
#endif
|
||||
|
||||
#define PERROR(fmt, args...) printk(KERN_ERR fmt, ##args)
|
||||
#define PWARN(fmt, args...) printk(KERN_WARNING fmt, ##args)
|
||||
#define PINFO(fmt, args...) printk(KERN_INFO fmt, ##args)
|
||||
#define PCRIT(fmt, args...) printk(KERN_CRIT fmt, ##args)
|
||||
|
||||
#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
|
||||
|
||||
// Command timeouts
|
||||
#define FOREVER (0)
|
||||
#define TMOUT_INQUIRY (20)
|
||||
#define TMOUT_FLUSH (360/45)
|
||||
#define TMOUT_ABORT (30)
|
||||
#define TMOUT_SCSI (300)
|
||||
#define TMOUT_IOPRESET (360)
|
||||
#define TMOUT_GETSTATUS (15)
|
||||
#define TMOUT_INITOUTBOUND (15)
|
||||
#define TMOUT_LCT (360)
|
||||
|
||||
|
||||
#define I2O_SCSI_DEVICE_DSC_MASK 0x00FF
|
||||
|
||||
#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x000A
|
||||
|
||||
#define I2O_SCSI_DSC_MASK 0xFF00
|
||||
#define I2O_SCSI_DSC_SUCCESS 0x0000
|
||||
#define I2O_SCSI_DSC_REQUEST_ABORTED 0x0200
|
||||
#define I2O_SCSI_DSC_UNABLE_TO_ABORT 0x0300
|
||||
#define I2O_SCSI_DSC_COMPLETE_WITH_ERROR 0x0400
|
||||
#define I2O_SCSI_DSC_ADAPTER_BUSY 0x0500
|
||||
#define I2O_SCSI_DSC_REQUEST_INVALID 0x0600
|
||||
#define I2O_SCSI_DSC_PATH_INVALID 0x0700
|
||||
#define I2O_SCSI_DSC_DEVICE_NOT_PRESENT 0x0800
|
||||
#define I2O_SCSI_DSC_UNABLE_TO_TERMINATE 0x0900
|
||||
#define I2O_SCSI_DSC_SELECTION_TIMEOUT 0x0A00
|
||||
#define I2O_SCSI_DSC_COMMAND_TIMEOUT 0x0B00
|
||||
#define I2O_SCSI_DSC_MR_MESSAGE_RECEIVED 0x0D00
|
||||
#define I2O_SCSI_DSC_SCSI_BUS_RESET 0x0E00
|
||||
#define I2O_SCSI_DSC_PARITY_ERROR_FAILURE 0x0F00
|
||||
#define I2O_SCSI_DSC_AUTOSENSE_FAILED 0x1000
|
||||
#define I2O_SCSI_DSC_NO_ADAPTER 0x1100
|
||||
#define I2O_SCSI_DSC_DATA_OVERRUN 0x1200
|
||||
#define I2O_SCSI_DSC_UNEXPECTED_BUS_FREE 0x1300
|
||||
#define I2O_SCSI_DSC_SEQUENCE_FAILURE 0x1400
|
||||
#define I2O_SCSI_DSC_REQUEST_LENGTH_ERROR 0x1500
|
||||
#define I2O_SCSI_DSC_PROVIDE_FAILURE 0x1600
|
||||
#define I2O_SCSI_DSC_BDR_MESSAGE_SENT 0x1700
|
||||
#define I2O_SCSI_DSC_REQUEST_TERMINATED 0x1800
|
||||
#define I2O_SCSI_DSC_IDE_MESSAGE_SENT 0x3300
|
||||
#define I2O_SCSI_DSC_RESOURCE_UNAVAILABLE 0x3400
|
||||
#define I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT 0x3500
|
||||
#define I2O_SCSI_DSC_MESSAGE_RECEIVED 0x3600
|
||||
#define I2O_SCSI_DSC_INVALID_CDB 0x3700
|
||||
#define I2O_SCSI_DSC_LUN_INVALID 0x3800
|
||||
#define I2O_SCSI_DSC_SCSI_TID_INVALID 0x3900
|
||||
#define I2O_SCSI_DSC_FUNCTION_UNAVAILABLE 0x3A00
|
||||
#define I2O_SCSI_DSC_NO_NEXUS 0x3B00
|
||||
#define I2O_SCSI_DSC_SCSI_IID_INVALID 0x3C00
|
||||
#define I2O_SCSI_DSC_CDB_RECEIVED 0x3D00
|
||||
#define I2O_SCSI_DSC_LUN_ALREADY_ENABLED 0x3E00
|
||||
#define I2O_SCSI_DSC_BUS_BUSY 0x3F00
|
||||
#define I2O_SCSI_DSC_QUEUE_FROZEN 0x4000
|
||||
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define HBA_FLAGS_INSTALLED_B 0x00000001 // Adapter Was Installed
|
||||
#define HBA_FLAGS_BLINKLED_B 0x00000002 // Adapter In Blink LED State
|
||||
#define HBA_FLAGS_IN_RESET 0x00000040 /* in reset */
|
||||
#define HBA_HOSTRESET_FAILED 0x00000080 /* adpt_resethost failed */
|
||||
|
||||
|
||||
// Device state flags
|
||||
#define DPTI_DEV_ONLINE 0x00
|
||||
#define DPTI_DEV_UNSCANNED 0x01
|
||||
#define DPTI_DEV_RESET 0x02
|
||||
#define DPTI_DEV_OFFLINE 0x04
|
||||
|
||||
|
||||
struct adpt_device {
|
||||
struct adpt_device* next_lun;
|
||||
u32 flags;
|
||||
u32 type;
|
||||
u32 capacity;
|
||||
u32 block_size;
|
||||
u8 scsi_channel;
|
||||
u8 scsi_id;
|
||||
u64 scsi_lun;
|
||||
u8 state;
|
||||
u16 tid;
|
||||
struct i2o_device* pI2o_dev;
|
||||
struct scsi_device *pScsi_dev;
|
||||
};
|
||||
|
||||
struct adpt_channel {
|
||||
struct adpt_device* device[MAX_ID]; /* used as an array of 128 scsi ids */
|
||||
u8 scsi_id;
|
||||
u8 type;
|
||||
u16 tid;
|
||||
u32 state;
|
||||
struct i2o_device* pI2o_dev;
|
||||
};
|
||||
|
||||
// HBA state flags
|
||||
#define DPTI_STATE_RESET (0x01)
|
||||
|
||||
typedef struct _adpt_hba {
|
||||
struct _adpt_hba *next;
|
||||
struct pci_dev *pDev;
|
||||
struct Scsi_Host *host;
|
||||
u32 state;
|
||||
spinlock_t state_lock;
|
||||
int unit;
|
||||
int host_no; /* SCSI host number */
|
||||
u8 initialized;
|
||||
u8 in_use; /* is the management node open*/
|
||||
|
||||
char name[32];
|
||||
char detail[55];
|
||||
|
||||
void __iomem *base_addr_virt;
|
||||
void __iomem *msg_addr_virt;
|
||||
ulong base_addr_phys;
|
||||
void __iomem *post_port;
|
||||
void __iomem *reply_port;
|
||||
void __iomem *irq_mask;
|
||||
u16 post_count;
|
||||
u32 post_fifo_size;
|
||||
u32 reply_fifo_size;
|
||||
u32* reply_pool;
|
||||
dma_addr_t reply_pool_pa;
|
||||
u32 sg_tablesize; // Scatter/Gather List Size.
|
||||
u8 top_scsi_channel;
|
||||
u8 top_scsi_id;
|
||||
u64 top_scsi_lun;
|
||||
u8 dma64;
|
||||
|
||||
i2o_status_block* status_block;
|
||||
dma_addr_t status_block_pa;
|
||||
i2o_hrt* hrt;
|
||||
dma_addr_t hrt_pa;
|
||||
i2o_lct* lct;
|
||||
dma_addr_t lct_pa;
|
||||
uint lct_size;
|
||||
struct i2o_device* devices;
|
||||
struct adpt_channel channel[MAX_CHANNEL];
|
||||
struct proc_dir_entry* proc_entry; /* /proc dir */
|
||||
|
||||
void __iomem *FwDebugBuffer_P; // Virtual Address Of FW Debug Buffer
|
||||
u32 FwDebugBufferSize; // FW Debug Buffer Size In Bytes
|
||||
void __iomem *FwDebugStrLength_P;// Virtual Addr Of FW Debug String Len
|
||||
void __iomem *FwDebugFlags_P; // Virtual Address Of FW Debug Flags
|
||||
void __iomem *FwDebugBLEDflag_P;// Virtual Addr Of FW Debug BLED
|
||||
void __iomem *FwDebugBLEDvalue_P;// Virtual Addr Of FW Debug BLED
|
||||
u32 FwDebugFlags;
|
||||
u32 *ioctl_reply_context[4];
|
||||
} adpt_hba;
|
||||
|
||||
struct sg_simple_element {
|
||||
u32 flag_count;
|
||||
u32 addr_bus;
|
||||
};
|
||||
|
||||
/*
|
||||
* Function Prototypes
|
||||
*/
|
||||
|
||||
static void adpt_i2o_sys_shutdown(void);
|
||||
static int adpt_init(void);
|
||||
static int adpt_i2o_build_sys_table(void);
|
||||
static irqreturn_t adpt_isr(int irq, void *dev_id);
|
||||
|
||||
static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d);
|
||||
static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid,
|
||||
int group, int field, void *buf, int buflen);
|
||||
#ifdef DEBUG
|
||||
static const char *adpt_i2o_get_class_name(int class);
|
||||
#endif
|
||||
static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid,
|
||||
void *opblk, dma_addr_t opblk_pa, int oplen,
|
||||
void *resblk, dma_addr_t resblk_pa, int reslen);
|
||||
static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout);
|
||||
static int adpt_i2o_lct_get(adpt_hba* pHba);
|
||||
static int adpt_i2o_parse_lct(adpt_hba* pHba);
|
||||
static int adpt_i2o_activate_hba(adpt_hba* pHba);
|
||||
static int adpt_i2o_enable_hba(adpt_hba* pHba);
|
||||
static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d);
|
||||
static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len);
|
||||
static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba);
|
||||
static s32 adpt_i2o_status_get(adpt_hba* pHba);
|
||||
static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba);
|
||||
static s32 adpt_i2o_hrt_get(adpt_hba* pHba);
|
||||
static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice);
|
||||
static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd);
|
||||
static s32 adpt_scsi_host_alloc(adpt_hba* pHba,struct scsi_host_template * sht);
|
||||
static s32 adpt_hba_reset(adpt_hba* pHba);
|
||||
static s32 adpt_i2o_reset_hba(adpt_hba* pHba);
|
||||
static s32 adpt_rescan(adpt_hba* pHba);
|
||||
static s32 adpt_i2o_reparse_lct(adpt_hba* pHba);
|
||||
static s32 adpt_send_nop(adpt_hba*pHba,u32 m);
|
||||
static void adpt_i2o_delete_hba(adpt_hba* pHba);
|
||||
static void adpt_inquiry(adpt_hba* pHba);
|
||||
static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun);
|
||||
static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ;
|
||||
static int adpt_i2o_online_hba(adpt_hba* pHba);
|
||||
static void adpt_i2o_post_wait_complete(u32, int);
|
||||
static int adpt_i2o_systab_send(adpt_hba* pHba);
|
||||
|
||||
static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg);
|
||||
static int adpt_open(struct inode *inode, struct file *file);
|
||||
static int adpt_close(struct inode *inode, struct file *file);
|
||||
|
||||
|
||||
#ifdef UARTDELAY
|
||||
static void adpt_delay(int millisec);
|
||||
#endif
|
||||
|
||||
#define PRINT_BUFFER_SIZE 512
|
||||
|
||||
#define HBA_FLAGS_DBG_FLAGS_MASK 0xffff0000 // Mask for debug flags
|
||||
#define HBA_FLAGS_DBG_KERNEL_PRINT_B 0x00010000 // Kernel Debugger Print
|
||||
#define HBA_FLAGS_DBG_FW_PRINT_B 0x00020000 // Firmware Debugger Print
|
||||
#define HBA_FLAGS_DBG_FUNCTION_ENTRY_B 0x00040000 // Function Entry Point
|
||||
#define HBA_FLAGS_DBG_FUNCTION_EXIT_B 0x00080000 // Function Exit
|
||||
#define HBA_FLAGS_DBG_ERROR_B 0x00100000 // Error Conditions
|
||||
#define HBA_FLAGS_DBG_INIT_B 0x00200000 // Init Prints
|
||||
#define HBA_FLAGS_DBG_OS_COMMANDS_B 0x00400000 // OS Command Info
|
||||
#define HBA_FLAGS_DBG_SCAN_B 0x00800000 // Device Scan
|
||||
|
||||
#define FW_DEBUG_STR_LENGTH_OFFSET 0
|
||||
#define FW_DEBUG_FLAGS_OFFSET 4
|
||||
#define FW_DEBUG_BLED_OFFSET 8
|
||||
|
||||
#define FW_DEBUG_FLAGS_NO_HEADERS_B 0x01
|
||||
#endif /* !HOSTS_C */
|
||||
#endif /* _DPT_H */
|
||||
|
|
@ -1488,7 +1488,6 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
|
|||
|
||||
fh = fc_frame_header_get(fp);
|
||||
skb = fp_skb(fp);
|
||||
wlen = skb->len / FCOE_WORD_TO_BYTE;
|
||||
|
||||
if (!lport->link_up) {
|
||||
kfree_skb(skb);
|
||||
|
|
|
|||
|
|
@ -544,6 +544,39 @@ static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id)
|
|||
vnic_dev_set_default_vlan(fnic->vdev, vlan_id);
|
||||
}
|
||||
|
||||
static int fnic_scsi_drv_init(struct fnic *fnic)
|
||||
{
|
||||
struct Scsi_Host *host = fnic->lport->host;
|
||||
|
||||
/* Configure maximum outstanding IO reqs*/
|
||||
if (fnic->config.io_throttle_count != FNIC_UCSM_DFLT_THROTTLE_CNT_BLD)
|
||||
host->can_queue = min_t(u32, FNIC_MAX_IO_REQ,
|
||||
max_t(u32, FNIC_MIN_IO_REQ,
|
||||
fnic->config.io_throttle_count));
|
||||
|
||||
fnic->fnic_max_tag_id = host->can_queue;
|
||||
host->max_lun = fnic->config.luns_per_tgt;
|
||||
host->max_id = FNIC_MAX_FCP_TARGET;
|
||||
host->max_cmd_len = FCOE_MAX_CMD_LEN;
|
||||
|
||||
host->nr_hw_queues = fnic->wq_copy_count;
|
||||
if (host->nr_hw_queues > 1)
|
||||
shost_printk(KERN_ERR, host,
|
||||
"fnic: blk-mq is not supported");
|
||||
|
||||
host->nr_hw_queues = fnic->wq_copy_count = 1;
|
||||
|
||||
shost_printk(KERN_INFO, host,
|
||||
"fnic: can_queue: %d max_lun: %llu",
|
||||
host->can_queue, host->max_lun);
|
||||
|
||||
shost_printk(KERN_INFO, host,
|
||||
"fnic: max_id: %d max_cmd_len: %d nr_hw_queues: %d",
|
||||
host->max_id, host->max_cmd_len, host->nr_hw_queues);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct Scsi_Host *host;
|
||||
|
|
@ -684,17 +717,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
goto err_out_dev_close;
|
||||
}
|
||||
|
||||
/* Configure Maximum Outstanding IO reqs*/
|
||||
if (fnic->config.io_throttle_count != FNIC_UCSM_DFLT_THROTTLE_CNT_BLD) {
|
||||
host->can_queue = min_t(u32, FNIC_MAX_IO_REQ,
|
||||
max_t(u32, FNIC_MIN_IO_REQ,
|
||||
fnic->config.io_throttle_count));
|
||||
}
|
||||
fnic->fnic_max_tag_id = host->can_queue;
|
||||
|
||||
host->max_lun = fnic->config.luns_per_tgt;
|
||||
host->max_id = FNIC_MAX_FCP_TARGET;
|
||||
host->max_cmd_len = FCOE_MAX_CMD_LEN;
|
||||
fnic_scsi_drv_init(fnic);
|
||||
|
||||
fnic_get_res_counts(fnic);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,12 @@
|
|||
struct gvp11_hostdata {
|
||||
struct WD33C93_hostdata wh;
|
||||
struct gvp11_scsiregs *regs;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
#define DMA_DIR(d) ((d == DATA_OUT_DIR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE)
|
||||
#define TO_DMA_MASK(m) (~((unsigned long long)m & 0xffffffff))
|
||||
|
||||
static irqreturn_t gvp11_intr(int irq, void *data)
|
||||
{
|
||||
struct Scsi_Host *instance = data;
|
||||
|
|
@ -54,17 +58,33 @@ void gvp11_setup(char *str, int *ints)
|
|||
static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
||||
{
|
||||
struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
|
||||
unsigned long len = scsi_pointer->this_residual;
|
||||
struct Scsi_Host *instance = cmd->device->host;
|
||||
struct gvp11_hostdata *hdata = shost_priv(instance);
|
||||
struct WD33C93_hostdata *wh = &hdata->wh;
|
||||
struct gvp11_scsiregs *regs = hdata->regs;
|
||||
unsigned short cntr = GVP11_DMAC_INT_ENABLE;
|
||||
unsigned long addr = virt_to_bus(scsi_pointer->ptr);
|
||||
dma_addr_t addr;
|
||||
int bank_mask;
|
||||
static int scsi_alloc_out_of_range = 0;
|
||||
|
||||
addr = dma_map_single(hdata->dev, scsi_pointer->ptr,
|
||||
len, DMA_DIR(dir_in));
|
||||
if (dma_mapping_error(hdata->dev, addr)) {
|
||||
dev_warn(hdata->dev, "cannot map SCSI data block %p\n",
|
||||
scsi_pointer->ptr);
|
||||
return 1;
|
||||
}
|
||||
scsi_pointer->dma_handle = addr;
|
||||
|
||||
/* use bounce buffer if the physical address is bad */
|
||||
if (addr & wh->dma_xfer_mask) {
|
||||
/* drop useless mapping */
|
||||
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
|
||||
scsi_pointer->this_residual,
|
||||
DMA_DIR(dir_in));
|
||||
scsi_pointer->dma_handle = (dma_addr_t) NULL;
|
||||
|
||||
wh->dma_bounce_len = (scsi_pointer->this_residual + 511) & ~0x1ff;
|
||||
|
||||
if (!scsi_alloc_out_of_range) {
|
||||
|
|
@ -87,10 +107,32 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
|
||||
}
|
||||
|
||||
/* check if the address of the bounce buffer is OK */
|
||||
addr = virt_to_bus(wh->dma_bounce_buffer);
|
||||
if (!dir_in) {
|
||||
/* copy to bounce buffer for a write */
|
||||
memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
|
||||
scsi_pointer->this_residual);
|
||||
}
|
||||
|
||||
if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) {
|
||||
/* will flush/invalidate cache for us */
|
||||
addr = dma_map_single(hdata->dev,
|
||||
wh->dma_bounce_buffer,
|
||||
wh->dma_bounce_len,
|
||||
DMA_DIR(dir_in));
|
||||
/* can't map buffer; use PIO */
|
||||
if (dma_mapping_error(hdata->dev, addr)) {
|
||||
dev_warn(hdata->dev,
|
||||
"cannot map bounce buffer %p\n",
|
||||
wh->dma_bounce_buffer);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr & wh->dma_xfer_mask) {
|
||||
/* drop useless mapping */
|
||||
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
|
||||
scsi_pointer->this_residual,
|
||||
DMA_DIR(dir_in));
|
||||
/* fall back to Chip RAM if address out of range */
|
||||
if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) {
|
||||
kfree(wh->dma_bounce_buffer);
|
||||
|
|
@ -108,15 +150,19 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
return 1;
|
||||
}
|
||||
|
||||
addr = virt_to_bus(wh->dma_bounce_buffer);
|
||||
if (!dir_in) {
|
||||
/* copy to bounce buffer for a write */
|
||||
memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
|
||||
scsi_pointer->this_residual);
|
||||
}
|
||||
/* chip RAM can be mapped to phys. address directly */
|
||||
addr = virt_to_phys(wh->dma_bounce_buffer);
|
||||
/* no need to flush/invalidate cache */
|
||||
wh->dma_buffer_pool = BUF_CHIP_ALLOCED;
|
||||
}
|
||||
/* finally, have OK mapping (punted for PIO else) */
|
||||
scsi_pointer->dma_handle = addr;
|
||||
|
||||
if (!dir_in) {
|
||||
/* copy to bounce buffer for a write */
|
||||
memcpy(wh->dma_bounce_buffer, scsi_pointer->ptr,
|
||||
scsi_pointer->this_residual);
|
||||
}
|
||||
}
|
||||
|
||||
/* setup dma direction */
|
||||
|
|
@ -129,13 +175,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
|
|||
/* setup DMA *physical* address */
|
||||
regs->ACR = addr;
|
||||
|
||||
if (dir_in) {
|
||||
/* invalidate any cache */
|
||||
cache_clear(addr, scsi_pointer->this_residual);
|
||||
} else {
|
||||
/* push any dirty cache */
|
||||
cache_push(addr, scsi_pointer->this_residual);
|
||||
}
|
||||
/* no more cache flush here - dma_map_single() takes care */
|
||||
|
||||
bank_mask = (~wh->dma_xfer_mask >> 18) & 0x01c0;
|
||||
if (bank_mask)
|
||||
|
|
@ -161,6 +201,11 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
|
|||
/* remove write bit from CONTROL bits */
|
||||
regs->CNTR = GVP11_DMAC_INT_ENABLE;
|
||||
|
||||
if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED)
|
||||
dma_unmap_single(hdata->dev, scsi_pointer->dma_handle,
|
||||
scsi_pointer->this_residual,
|
||||
DMA_DIR(wh->dma_dir));
|
||||
|
||||
/* copy from a bounce buffer, if necessary */
|
||||
if (status && wh->dma_bounce_buffer) {
|
||||
if (wh->dma_dir && SCpnt)
|
||||
|
|
@ -287,6 +332,13 @@ static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
|
|||
|
||||
default_dma_xfer_mask = ent->driver_data;
|
||||
|
||||
if (dma_set_mask_and_coherent(&z->dev,
|
||||
TO_DMA_MASK(default_dma_xfer_mask))) {
|
||||
dev_warn(&z->dev, "cannot use DMA mask %llx\n",
|
||||
TO_DMA_MASK(default_dma_xfer_mask));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rumors state that some GVP ram boards use the same product
|
||||
* code as the SCSI controllers. Therefore if the board-size
|
||||
|
|
@ -327,9 +379,16 @@ static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
|
|||
wdregs.SCMD = ®s->SCMD;
|
||||
|
||||
hdata = shost_priv(instance);
|
||||
if (gvp11_xfer_mask)
|
||||
if (gvp11_xfer_mask) {
|
||||
hdata->wh.dma_xfer_mask = gvp11_xfer_mask;
|
||||
else
|
||||
if (dma_set_mask_and_coherent(&z->dev,
|
||||
TO_DMA_MASK(gvp11_xfer_mask))) {
|
||||
dev_warn(&z->dev, "cannot use DMA mask %llx\n",
|
||||
TO_DMA_MASK(gvp11_xfer_mask));
|
||||
error = -ENODEV;
|
||||
goto fail_check_or_alloc;
|
||||
}
|
||||
} else
|
||||
hdata->wh.dma_xfer_mask = default_dma_xfer_mask;
|
||||
|
||||
hdata->wh.no_sync = 0xff;
|
||||
|
|
|
|||
|
|
@ -219,10 +219,15 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
|
|||
task->lldd_task = NULL;
|
||||
|
||||
if (!sas_protocol_ata(task->task_proto)) {
|
||||
if (slot->n_elem)
|
||||
dma_unmap_sg(dev, task->scatter,
|
||||
task->num_scatter,
|
||||
task->data_dir);
|
||||
if (slot->n_elem) {
|
||||
if (task->task_proto & SAS_PROTOCOL_SSP)
|
||||
dma_unmap_sg(dev, task->scatter,
|
||||
task->num_scatter,
|
||||
task->data_dir);
|
||||
else
|
||||
dma_unmap_sg(dev, &task->smp_task.smp_req,
|
||||
1, DMA_TO_DEVICE);
|
||||
}
|
||||
if (slot->n_elem_dif) {
|
||||
struct sas_ssp_task *ssp_task = &task->ssp_task;
|
||||
struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
|
||||
|
|
@ -269,28 +274,23 @@ static void hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba,
|
|||
}
|
||||
|
||||
static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba,
|
||||
struct sas_task *task, int n_elem,
|
||||
int n_elem_req)
|
||||
struct sas_task *task, int n_elem)
|
||||
{
|
||||
struct device *dev = hisi_hba->dev;
|
||||
|
||||
if (!sas_protocol_ata(task->task_proto)) {
|
||||
if (!sas_protocol_ata(task->task_proto) && n_elem) {
|
||||
if (task->num_scatter) {
|
||||
if (n_elem)
|
||||
dma_unmap_sg(dev, task->scatter,
|
||||
task->num_scatter,
|
||||
task->data_dir);
|
||||
dma_unmap_sg(dev, task->scatter, task->num_scatter,
|
||||
task->data_dir);
|
||||
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
|
||||
if (n_elem_req)
|
||||
dma_unmap_sg(dev, &task->smp_task.smp_req,
|
||||
1, DMA_TO_DEVICE);
|
||||
dma_unmap_sg(dev, &task->smp_task.smp_req,
|
||||
1, DMA_TO_DEVICE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int hisi_sas_dma_map(struct hisi_hba *hisi_hba,
|
||||
struct sas_task *task, int *n_elem,
|
||||
int *n_elem_req)
|
||||
struct sas_task *task, int *n_elem)
|
||||
{
|
||||
struct device *dev = hisi_hba->dev;
|
||||
int rc;
|
||||
|
|
@ -308,9 +308,9 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba,
|
|||
goto prep_out;
|
||||
}
|
||||
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
|
||||
*n_elem_req = dma_map_sg(dev, &task->smp_task.smp_req,
|
||||
1, DMA_TO_DEVICE);
|
||||
if (!*n_elem_req) {
|
||||
*n_elem = dma_map_sg(dev, &task->smp_task.smp_req,
|
||||
1, DMA_TO_DEVICE);
|
||||
if (!*n_elem) {
|
||||
rc = -ENOMEM;
|
||||
goto prep_out;
|
||||
}
|
||||
|
|
@ -332,8 +332,7 @@ static int hisi_sas_dma_map(struct hisi_hba *hisi_hba,
|
|||
|
||||
err_out_dma_unmap:
|
||||
/* It would be better to call dma_unmap_sg() here, but it's messy */
|
||||
hisi_sas_dma_unmap(hisi_hba, task, *n_elem,
|
||||
*n_elem_req);
|
||||
hisi_sas_dma_unmap(hisi_hba, task, *n_elem);
|
||||
prep_out:
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -457,7 +456,7 @@ void hisi_sas_task_deliver(struct hisi_hba *hisi_hba,
|
|||
|
||||
static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
|
||||
{
|
||||
int n_elem = 0, n_elem_dif = 0, n_elem_req = 0;
|
||||
int n_elem = 0, n_elem_dif = 0;
|
||||
struct domain_device *device = task->dev;
|
||||
struct asd_sas_port *sas_port = device->port;
|
||||
struct hisi_sas_device *sas_dev = device->lldd_dev;
|
||||
|
|
@ -568,8 +567,7 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = hisi_sas_dma_map(hisi_hba, task, &n_elem,
|
||||
&n_elem_req);
|
||||
rc = hisi_sas_dma_map(hisi_hba, task, &n_elem);
|
||||
if (rc < 0)
|
||||
goto prep_out;
|
||||
|
||||
|
|
@ -605,8 +603,7 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
|
|||
if (!sas_protocol_ata(task->task_proto))
|
||||
hisi_sas_dif_dma_unmap(hisi_hba, task, n_elem_dif);
|
||||
err_out_dma_unmap:
|
||||
hisi_sas_dma_unmap(hisi_hba, task, n_elem,
|
||||
n_elem_req);
|
||||
hisi_sas_dma_unmap(hisi_hba, task, n_elem);
|
||||
prep_out:
|
||||
dev_err(dev, "task exec: failed[%d]!\n", rc);
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -1282,8 +1282,6 @@ static void slot_complete_v1_hw(struct hisi_hba *hisi_hba,
|
|||
|
||||
ts->stat = SAS_SAM_STAT_GOOD;
|
||||
|
||||
dma_unmap_sg(dev, &task->smp_task.smp_req, 1,
|
||||
DMA_TO_DEVICE);
|
||||
memcpy(to + sg_resp->offset,
|
||||
hisi_sas_status_buf_addr_mem(slot) +
|
||||
sizeof(struct hisi_sas_err_record),
|
||||
|
|
|
|||
|
|
@ -805,8 +805,8 @@ slot_index_alloc_quirk_v2_hw(struct hisi_hba *hisi_hba,
|
|||
return -SAS_QUEUE_FULL;
|
||||
}
|
||||
/*
|
||||
* SAS IPTT bit0 should be 1, and SATA IPTT bit0 should be 0.
|
||||
*/
|
||||
* SAS IPTT bit0 should be 1, and SATA IPTT bit0 should be 0.
|
||||
*/
|
||||
if (sata_dev ^ (start & 1))
|
||||
break;
|
||||
start++;
|
||||
|
|
@ -2428,8 +2428,6 @@ static void slot_complete_v2_hw(struct hisi_hba *hisi_hba,
|
|||
|
||||
ts->stat = SAS_SAM_STAT_GOOD;
|
||||
|
||||
dma_unmap_sg(dev, &task->smp_task.smp_req, 1,
|
||||
DMA_TO_DEVICE);
|
||||
memcpy(to + sg_resp->offset,
|
||||
hisi_sas_status_buf_addr_mem(slot) +
|
||||
sizeof(struct hisi_sas_err_record),
|
||||
|
|
|
|||
|
|
@ -481,6 +481,9 @@ struct hisi_sas_err_record_v3 {
|
|||
#define RX_DATA_LEN_UNDERFLOW_OFF 6
|
||||
#define RX_DATA_LEN_UNDERFLOW_MSK (1 << RX_DATA_LEN_UNDERFLOW_OFF)
|
||||
|
||||
#define RX_FIS_STATUS_ERR_OFF 0
|
||||
#define RX_FIS_STATUS_ERR_MSK (1 << RX_FIS_STATUS_ERR_OFF)
|
||||
|
||||
#define HISI_SAS_COMMAND_ENTRIES_V3_HW 4096
|
||||
#define HISI_SAS_MSI_COUNT_V3_HW 32
|
||||
|
||||
|
|
@ -2161,6 +2164,7 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
|
|||
hisi_sas_status_buf_addr_mem(slot);
|
||||
u32 dma_rx_err_type = le32_to_cpu(record->dma_rx_err_type);
|
||||
u32 trans_tx_fail_type = le32_to_cpu(record->trans_tx_fail_type);
|
||||
u16 sipc_rx_err_type = le16_to_cpu(record->sipc_rx_err_type);
|
||||
u32 dw3 = le32_to_cpu(complete_hdr->dw3);
|
||||
|
||||
switch (task->task_proto) {
|
||||
|
|
@ -2188,7 +2192,10 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
|
|||
case SAS_PROTOCOL_SATA:
|
||||
case SAS_PROTOCOL_STP:
|
||||
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
|
||||
if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
|
||||
if ((complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
|
||||
(sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) {
|
||||
ts->stat = SAS_PROTO_RESPONSE;
|
||||
} else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
|
||||
ts->residual = trans_tx_fail_type;
|
||||
ts->stat = SAS_DATA_UNDERRUN;
|
||||
} else if (dw3 & CMPLT_HDR_IO_IN_TARGET_MSK) {
|
||||
|
|
@ -2311,8 +2318,6 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba,
|
|||
|
||||
ts->stat = SAS_SAM_STAT_GOOD;
|
||||
|
||||
dma_unmap_sg(dev, &task->smp_task.smp_req, 1,
|
||||
DMA_TO_DEVICE);
|
||||
memcpy(to + sg_resp->offset,
|
||||
hisi_sas_status_buf_addr_mem(slot) +
|
||||
sizeof(struct hisi_sas_err_record),
|
||||
|
|
@ -2778,16 +2783,13 @@ static DEVICE_ATTR_RW(intr_coal_count_v3_hw);
|
|||
static int slave_configure_v3_hw(struct scsi_device *sdev)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev);
|
||||
struct domain_device *ddev = sdev_to_domain_dev(sdev);
|
||||
struct hisi_hba *hisi_hba = shost_priv(shost);
|
||||
int ret = hisi_sas_slave_configure(sdev);
|
||||
struct device *dev = hisi_hba->dev;
|
||||
int ret = sas_slave_configure(sdev);
|
||||
unsigned int max_sectors;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!dev_is_sata(ddev))
|
||||
sas_change_queue_depth(sdev, 64);
|
||||
|
||||
if (sdev->type == TYPE_ENCLOSURE)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ static void scsi_host_dev_release(struct device *dev)
|
|||
|
||||
kfree(shost->shost_data);
|
||||
|
||||
ida_simple_remove(&host_index_ida, shost->host_no);
|
||||
ida_free(&host_index_ida, shost->host_no);
|
||||
|
||||
if (shost->shost_state != SHOST_CREATED)
|
||||
put_device(parent);
|
||||
|
|
@ -395,7 +395,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
|
|||
init_waitqueue_head(&shost->host_wait);
|
||||
mutex_init(&shost->scan_mutex);
|
||||
|
||||
index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL);
|
||||
index = ida_alloc(&host_index_ida, GFP_KERNEL);
|
||||
if (index < 0) {
|
||||
kfree(shost);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ static struct iscsi_transport iscsi_sw_tcp_transport;
|
|||
static unsigned int iscsi_max_lun = ~0;
|
||||
module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
|
||||
|
||||
static bool iscsi_recv_from_iscsi_q;
|
||||
module_param_named(recv_from_iscsi_q, iscsi_recv_from_iscsi_q, bool, 0644);
|
||||
MODULE_PARM_DESC(recv_from_iscsi_q, "Set to true to read iSCSI data/headers from the iscsi_q workqueue. The default is false which will perform reads from the network softirq context.");
|
||||
|
||||
static int iscsi_sw_tcp_dbg;
|
||||
module_param_named(debug_iscsi_tcp, iscsi_sw_tcp_dbg, int,
|
||||
S_IRUGO | S_IWUSR);
|
||||
|
|
@ -122,20 +126,13 @@ static inline int iscsi_sw_sk_state_check(struct sock *sk)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void iscsi_sw_tcp_data_ready(struct sock *sk)
|
||||
static void iscsi_sw_tcp_recv_data(struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_conn *conn;
|
||||
struct iscsi_tcp_conn *tcp_conn;
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
|
||||
struct sock *sk = tcp_sw_conn->sock->sk;
|
||||
read_descriptor_t rd_desc;
|
||||
|
||||
read_lock_bh(&sk->sk_callback_lock);
|
||||
conn = sk->sk_user_data;
|
||||
if (!conn) {
|
||||
read_unlock_bh(&sk->sk_callback_lock);
|
||||
return;
|
||||
}
|
||||
tcp_conn = conn->dd_data;
|
||||
|
||||
/*
|
||||
* Use rd_desc to pass 'conn' to iscsi_tcp_recv.
|
||||
* We set count to 1 because we want the network layer to
|
||||
|
|
@ -144,13 +141,48 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk)
|
|||
*/
|
||||
rd_desc.arg.data = conn;
|
||||
rd_desc.count = 1;
|
||||
tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv);
|
||||
|
||||
iscsi_sw_sk_state_check(sk);
|
||||
tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv);
|
||||
|
||||
/* If we had to (atomically) map a highmem page,
|
||||
* unmap it now. */
|
||||
iscsi_tcp_segment_unmap(&tcp_conn->in.segment);
|
||||
|
||||
iscsi_sw_sk_state_check(sk);
|
||||
}
|
||||
|
||||
static void iscsi_sw_tcp_recv_data_work(struct work_struct *work)
|
||||
{
|
||||
struct iscsi_conn *conn = container_of(work, struct iscsi_conn,
|
||||
recvwork);
|
||||
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
|
||||
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
|
||||
struct sock *sk = tcp_sw_conn->sock->sk;
|
||||
|
||||
lock_sock(sk);
|
||||
iscsi_sw_tcp_recv_data(conn);
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
static void iscsi_sw_tcp_data_ready(struct sock *sk)
|
||||
{
|
||||
struct iscsi_sw_tcp_conn *tcp_sw_conn;
|
||||
struct iscsi_tcp_conn *tcp_conn;
|
||||
struct iscsi_conn *conn;
|
||||
|
||||
read_lock_bh(&sk->sk_callback_lock);
|
||||
conn = sk->sk_user_data;
|
||||
if (!conn) {
|
||||
read_unlock_bh(&sk->sk_callback_lock);
|
||||
return;
|
||||
}
|
||||
tcp_conn = conn->dd_data;
|
||||
tcp_sw_conn = tcp_conn->dd_data;
|
||||
|
||||
if (tcp_sw_conn->queue_recv)
|
||||
iscsi_conn_queue_recv(conn);
|
||||
else
|
||||
iscsi_sw_tcp_recv_data(conn);
|
||||
read_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +237,7 @@ static void iscsi_sw_tcp_write_space(struct sock *sk)
|
|||
old_write_space(sk);
|
||||
|
||||
ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
|
||||
iscsi_conn_queue_work(conn);
|
||||
iscsi_conn_queue_xmit(conn);
|
||||
}
|
||||
|
||||
static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn)
|
||||
|
|
@ -274,7 +306,10 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn,
|
|||
copy = segment->size - offset;
|
||||
|
||||
if (segment->total_copied + segment->size < segment->total_size)
|
||||
flags |= MSG_MORE;
|
||||
flags |= MSG_MORE | MSG_SENDPAGE_NOTLAST;
|
||||
|
||||
if (tcp_sw_conn->queue_recv)
|
||||
flags |= MSG_DONTWAIT;
|
||||
|
||||
/* Use sendpage if we can; else fall back to sendmsg */
|
||||
if (!segment->data) {
|
||||
|
|
@ -557,6 +592,8 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,
|
|||
conn = cls_conn->dd_data;
|
||||
tcp_conn = conn->dd_data;
|
||||
tcp_sw_conn = tcp_conn->dd_data;
|
||||
INIT_WORK(&conn->recvwork, iscsi_sw_tcp_recv_data_work);
|
||||
tcp_sw_conn->queue_recv = iscsi_recv_from_iscsi_q;
|
||||
|
||||
tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm))
|
||||
|
|
@ -610,6 +647,8 @@ static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn)
|
|||
iscsi_sw_tcp_conn_restore_callbacks(conn);
|
||||
sock_put(sock->sk);
|
||||
|
||||
iscsi_suspend_rx(conn);
|
||||
|
||||
spin_lock_bh(&session->frwd_lock);
|
||||
tcp_sw_conn->sock = NULL;
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
|
|
@ -898,7 +937,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
|
|||
remove_session:
|
||||
iscsi_session_teardown(cls_session);
|
||||
remove_host:
|
||||
iscsi_host_remove(shost);
|
||||
iscsi_host_remove(shost, false);
|
||||
free_host:
|
||||
iscsi_host_free(shost);
|
||||
return NULL;
|
||||
|
|
@ -915,7 +954,7 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
|
|||
iscsi_tcp_r2tpool_free(cls_session->dd_data);
|
||||
iscsi_session_teardown(cls_session);
|
||||
|
||||
iscsi_host_remove(shost);
|
||||
iscsi_host_remove(shost, false);
|
||||
iscsi_host_free(shost);
|
||||
}
|
||||
|
||||
|
|
@ -1003,7 +1042,6 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
|
|||
.eh_target_reset_handler = iscsi_eh_recover_target,
|
||||
.dma_boundary = PAGE_SIZE - 1,
|
||||
.slave_configure = iscsi_sw_tcp_slave_configure,
|
||||
.target_alloc = iscsi_target_alloc,
|
||||
.proc_name = "iscsi_tcp",
|
||||
.this_id = -1,
|
||||
.track_queue_depth = 1,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ struct iscsi_sw_tcp_send {
|
|||
|
||||
struct iscsi_sw_tcp_conn {
|
||||
struct socket *sock;
|
||||
struct work_struct recvwork;
|
||||
bool queue_recv;
|
||||
|
||||
struct iscsi_sw_tcp_send out;
|
||||
/* old values for socket callbacks */
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ MODULE_PARM_DESC(debug_libiscsi_eh,
|
|||
"%s " dbg_fmt, __func__, ##arg); \
|
||||
} while (0);
|
||||
|
||||
inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
|
||||
#define ISCSI_CMD_COMPL_WAIT 5
|
||||
|
||||
inline void iscsi_conn_queue_xmit(struct iscsi_conn *conn)
|
||||
{
|
||||
struct Scsi_Host *shost = conn->session->host;
|
||||
struct iscsi_host *ihost = shost_priv(shost);
|
||||
|
|
@ -91,7 +93,17 @@ inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
|
|||
if (ihost->workq)
|
||||
queue_work(ihost->workq, &conn->xmitwork);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_conn_queue_work);
|
||||
EXPORT_SYMBOL_GPL(iscsi_conn_queue_xmit);
|
||||
|
||||
inline void iscsi_conn_queue_recv(struct iscsi_conn *conn)
|
||||
{
|
||||
struct Scsi_Host *shost = conn->session->host;
|
||||
struct iscsi_host *ihost = shost_priv(shost);
|
||||
|
||||
if (ihost->workq && !test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))
|
||||
queue_work(ihost->workq, &conn->recvwork);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_conn_queue_recv);
|
||||
|
||||
static void __iscsi_update_cmdsn(struct iscsi_session *session,
|
||||
uint32_t exp_cmdsn, uint32_t max_cmdsn)
|
||||
|
|
@ -472,12 +484,18 @@ static void iscsi_free_task(struct iscsi_task *task)
|
|||
}
|
||||
}
|
||||
|
||||
void __iscsi_get_task(struct iscsi_task *task)
|
||||
bool iscsi_get_task(struct iscsi_task *task)
|
||||
{
|
||||
refcount_inc(&task->refcount);
|
||||
return refcount_inc_not_zero(&task->refcount);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__iscsi_get_task);
|
||||
EXPORT_SYMBOL_GPL(iscsi_get_task);
|
||||
|
||||
/**
|
||||
* __iscsi_put_task - drop the refcount on a task
|
||||
* @task: iscsi_task to drop the refcount on
|
||||
*
|
||||
* The back_lock must be held when calling in case it frees the task.
|
||||
*/
|
||||
void __iscsi_put_task(struct iscsi_task *task)
|
||||
{
|
||||
if (refcount_dec_and_test(&task->refcount))
|
||||
|
|
@ -489,10 +507,11 @@ void iscsi_put_task(struct iscsi_task *task)
|
|||
{
|
||||
struct iscsi_session *session = task->conn->session;
|
||||
|
||||
/* regular RX path uses back_lock */
|
||||
spin_lock_bh(&session->back_lock);
|
||||
__iscsi_put_task(task);
|
||||
spin_unlock_bh(&session->back_lock);
|
||||
if (refcount_dec_and_test(&task->refcount)) {
|
||||
spin_lock_bh(&session->back_lock);
|
||||
iscsi_free_task(task);
|
||||
spin_unlock_bh(&session->back_lock);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_put_task);
|
||||
|
||||
|
|
@ -557,16 +576,19 @@ static bool cleanup_queued_task(struct iscsi_task *task)
|
|||
struct iscsi_conn *conn = task->conn;
|
||||
bool early_complete = false;
|
||||
|
||||
/* Bad target might have completed task while it was still running */
|
||||
/*
|
||||
* We might have raced where we handled a R2T early and got a response
|
||||
* but have not yet taken the task off the requeue list, then a TMF or
|
||||
* recovery happened and so we can still see it here.
|
||||
*/
|
||||
if (task->state == ISCSI_TASK_COMPLETED)
|
||||
early_complete = true;
|
||||
|
||||
if (!list_empty(&task->running)) {
|
||||
list_del_init(&task->running);
|
||||
/*
|
||||
* If it's on a list but still running, this could be from
|
||||
* a bad target sending a rsp early, cleanup from a TMF, or
|
||||
* session recovery.
|
||||
* If it's on a list but still running this could be cleanup
|
||||
* from a TMF or session recovery.
|
||||
*/
|
||||
if (task->state == ISCSI_TASK_RUNNING ||
|
||||
task->state == ISCSI_TASK_COMPLETED)
|
||||
|
|
@ -587,20 +609,17 @@ static bool cleanup_queued_task(struct iscsi_task *task)
|
|||
}
|
||||
|
||||
/*
|
||||
* session frwd lock must be held and if not called for a task that is still
|
||||
* pending or from the xmit thread, then xmit thread must be suspended
|
||||
* session back and frwd lock must be held and if not called for a task that
|
||||
* is still pending or from the xmit thread, then xmit thread must be suspended
|
||||
*/
|
||||
static void fail_scsi_task(struct iscsi_task *task, int err)
|
||||
static void __fail_scsi_task(struct iscsi_task *task, int err)
|
||||
{
|
||||
struct iscsi_conn *conn = task->conn;
|
||||
struct scsi_cmnd *sc;
|
||||
int state;
|
||||
|
||||
spin_lock_bh(&conn->session->back_lock);
|
||||
if (cleanup_queued_task(task)) {
|
||||
spin_unlock_bh(&conn->session->back_lock);
|
||||
if (cleanup_queued_task(task))
|
||||
return;
|
||||
}
|
||||
|
||||
if (task->state == ISCSI_TASK_PENDING) {
|
||||
/*
|
||||
|
|
@ -619,7 +638,15 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
|
|||
sc->result = err << 16;
|
||||
scsi_set_resid(sc, scsi_bufflen(sc));
|
||||
iscsi_complete_task(task, state);
|
||||
spin_unlock_bh(&conn->session->back_lock);
|
||||
}
|
||||
|
||||
static void fail_scsi_task(struct iscsi_task *task, int err)
|
||||
{
|
||||
struct iscsi_session *session = task->conn->session;
|
||||
|
||||
spin_lock_bh(&session->back_lock);
|
||||
__fail_scsi_task(task, err);
|
||||
spin_unlock_bh(&session->back_lock);
|
||||
}
|
||||
|
||||
static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
|
||||
|
|
@ -668,12 +695,18 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iscsi_alloc_mgmt_task - allocate and setup a mgmt task.
|
||||
* @conn: iscsi conn that the task will be sent on.
|
||||
* @hdr: iscsi pdu that will be sent.
|
||||
* @data: buffer for data segment if needed.
|
||||
* @data_size: length of data in bytes.
|
||||
*/
|
||||
static struct iscsi_task *
|
||||
__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
iscsi_alloc_mgmt_task(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
char *data, uint32_t data_size)
|
||||
{
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct iscsi_host *ihost = shost_priv(session->host);
|
||||
uint8_t opcode = hdr->opcode & ISCSI_OPCODE_MASK;
|
||||
struct iscsi_task *task;
|
||||
itt_t itt;
|
||||
|
|
@ -754,30 +787,59 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
|||
task->conn->session->age);
|
||||
}
|
||||
|
||||
if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK))
|
||||
WRITE_ONCE(conn->ping_task, task);
|
||||
|
||||
if (!ihost->workq) {
|
||||
if (iscsi_prep_mgmt_task(conn, task))
|
||||
goto free_task;
|
||||
|
||||
if (session->tt->xmit_task(task))
|
||||
goto free_task;
|
||||
} else {
|
||||
list_add_tail(&task->running, &conn->mgmtqueue);
|
||||
iscsi_conn_queue_work(conn);
|
||||
}
|
||||
|
||||
return task;
|
||||
|
||||
free_task:
|
||||
/* regular RX path uses back_lock */
|
||||
spin_lock(&session->back_lock);
|
||||
__iscsi_put_task(task);
|
||||
spin_unlock(&session->back_lock);
|
||||
iscsi_put_task(task);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* iscsi_send_mgmt_task - Send task created with iscsi_alloc_mgmt_task.
|
||||
* @task: iscsi task to send.
|
||||
*
|
||||
* On failure this returns a non-zero error code, and the driver must free
|
||||
* the task with iscsi_put_task;
|
||||
*/
|
||||
static int iscsi_send_mgmt_task(struct iscsi_task *task)
|
||||
{
|
||||
struct iscsi_conn *conn = task->conn;
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct iscsi_host *ihost = shost_priv(conn->session->host);
|
||||
int rc = 0;
|
||||
|
||||
if (!ihost->workq) {
|
||||
rc = iscsi_prep_mgmt_task(conn, task);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = session->tt->xmit_task(task);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else {
|
||||
list_add_tail(&task->running, &conn->mgmtqueue);
|
||||
iscsi_conn_queue_xmit(conn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
char *data, uint32_t data_size)
|
||||
{
|
||||
struct iscsi_task *task;
|
||||
int rc;
|
||||
|
||||
task = iscsi_alloc_mgmt_task(conn, hdr, data, data_size);
|
||||
if (!task)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = iscsi_send_mgmt_task(task);
|
||||
if (rc)
|
||||
iscsi_put_task(task);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
|
||||
char *data, uint32_t data_size)
|
||||
{
|
||||
|
|
@ -786,7 +848,7 @@ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
|
|||
int err = 0;
|
||||
|
||||
spin_lock_bh(&session->frwd_lock);
|
||||
if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
|
||||
if (__iscsi_conn_send_pdu(conn, hdr, data, data_size))
|
||||
err = -EPERM;
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
return err;
|
||||
|
|
@ -959,7 +1021,6 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
|
|||
if (!rhdr) {
|
||||
if (READ_ONCE(conn->ping_task))
|
||||
return -EINVAL;
|
||||
WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK);
|
||||
}
|
||||
|
||||
memset(&hdr, 0, sizeof(struct iscsi_nopout));
|
||||
|
|
@ -973,10 +1034,18 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
|
|||
} else
|
||||
hdr.ttt = RESERVED_ITT;
|
||||
|
||||
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
|
||||
if (!task) {
|
||||
task = iscsi_alloc_mgmt_task(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
|
||||
if (!task)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!rhdr)
|
||||
WRITE_ONCE(conn->ping_task, task);
|
||||
|
||||
if (iscsi_send_mgmt_task(task)) {
|
||||
if (!rhdr)
|
||||
WRITE_ONCE(conn->ping_task, NULL);
|
||||
iscsi_put_task(task);
|
||||
|
||||
iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
|
||||
return -EIO;
|
||||
} else if (!rhdr) {
|
||||
|
|
@ -1434,11 +1503,17 @@ static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task,
|
|||
{
|
||||
int rc;
|
||||
|
||||
spin_lock_bh(&conn->session->back_lock);
|
||||
|
||||
if (!conn->task) {
|
||||
/* Take a ref so we can access it after xmit_task() */
|
||||
__iscsi_get_task(task);
|
||||
/*
|
||||
* Take a ref so we can access it after xmit_task().
|
||||
*
|
||||
* This should never fail because the failure paths will have
|
||||
* stopped the xmit thread.
|
||||
*/
|
||||
if (!iscsi_get_task(task)) {
|
||||
WARN_ON_ONCE(1);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Already have a ref from when we failed to send it last call */
|
||||
conn->task = NULL;
|
||||
|
|
@ -1449,7 +1524,7 @@ static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task,
|
|||
* case a bad target sends a cmd rsp before we have handled the task.
|
||||
*/
|
||||
if (was_requeue)
|
||||
__iscsi_put_task(task);
|
||||
iscsi_put_task(task);
|
||||
|
||||
/*
|
||||
* Do this after dropping the extra ref because if this was a requeue
|
||||
|
|
@ -1461,10 +1536,8 @@ static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task,
|
|||
* task and get woken up again.
|
||||
*/
|
||||
conn->task = task;
|
||||
spin_unlock_bh(&conn->session->back_lock);
|
||||
return -ENODATA;
|
||||
}
|
||||
spin_unlock_bh(&conn->session->back_lock);
|
||||
|
||||
spin_unlock_bh(&conn->session->frwd_lock);
|
||||
rc = conn->session->tt->xmit_task(task);
|
||||
|
|
@ -1472,20 +1545,16 @@ static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task,
|
|||
if (!rc) {
|
||||
/* done with this task */
|
||||
task->last_xfer = jiffies;
|
||||
}
|
||||
/* regular RX path uses back_lock */
|
||||
spin_lock(&conn->session->back_lock);
|
||||
if (rc && task->state == ISCSI_TASK_RUNNING) {
|
||||
} else {
|
||||
/*
|
||||
* get an extra ref that is released next time we access it
|
||||
* as conn->task above.
|
||||
*/
|
||||
__iscsi_get_task(task);
|
||||
iscsi_get_task(task);
|
||||
conn->task = task;
|
||||
}
|
||||
|
||||
__iscsi_put_task(task);
|
||||
spin_unlock(&conn->session->back_lock);
|
||||
iscsi_put_task(task);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -1513,7 +1582,7 @@ void iscsi_requeue_task(struct iscsi_task *task)
|
|||
*/
|
||||
iscsi_put_task(task);
|
||||
}
|
||||
iscsi_conn_queue_work(conn);
|
||||
iscsi_conn_queue_xmit(conn);
|
||||
spin_unlock_bh(&conn->session->frwd_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_requeue_task);
|
||||
|
|
@ -1567,6 +1636,28 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
|
|||
goto done;
|
||||
}
|
||||
|
||||
check_requeue:
|
||||
while (!list_empty(&conn->requeue)) {
|
||||
/*
|
||||
* we always do fastlogout - conn stop code will clean up.
|
||||
*/
|
||||
if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
|
||||
break;
|
||||
|
||||
task = list_entry(conn->requeue.next, struct iscsi_task,
|
||||
running);
|
||||
|
||||
if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
|
||||
break;
|
||||
|
||||
list_del_init(&task->running);
|
||||
rc = iscsi_xmit_task(conn, task, true);
|
||||
if (rc)
|
||||
goto done;
|
||||
if (!list_empty(&conn->mgmtqueue))
|
||||
goto check_mgmt;
|
||||
}
|
||||
|
||||
/* process pending command queue */
|
||||
while (!list_empty(&conn->cmdqueue)) {
|
||||
task = list_entry(conn->cmdqueue.next, struct iscsi_task,
|
||||
|
|
@ -1594,28 +1685,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
|
|||
*/
|
||||
if (!list_empty(&conn->mgmtqueue))
|
||||
goto check_mgmt;
|
||||
if (!list_empty(&conn->requeue))
|
||||
goto check_requeue;
|
||||
}
|
||||
|
||||
while (!list_empty(&conn->requeue)) {
|
||||
/*
|
||||
* we always do fastlogout - conn stop code will clean up.
|
||||
*/
|
||||
if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
|
||||
break;
|
||||
|
||||
task = list_entry(conn->requeue.next, struct iscsi_task,
|
||||
running);
|
||||
|
||||
if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
|
||||
break;
|
||||
|
||||
list_del_init(&task->running);
|
||||
rc = iscsi_xmit_task(conn, task, true);
|
||||
if (rc)
|
||||
goto done;
|
||||
if (!list_empty(&conn->mgmtqueue))
|
||||
goto check_mgmt;
|
||||
}
|
||||
spin_unlock_bh(&conn->session->frwd_lock);
|
||||
return -ENODATA;
|
||||
|
||||
|
|
@ -1782,7 +1855,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
|
|||
}
|
||||
} else {
|
||||
list_add_tail(&task->running, &conn->cmdqueue);
|
||||
iscsi_conn_queue_work(conn);
|
||||
iscsi_conn_queue_xmit(conn);
|
||||
}
|
||||
|
||||
session->queued_cmdsn++;
|
||||
|
|
@ -1843,11 +1916,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
|
|||
__must_hold(&session->frwd_lock)
|
||||
{
|
||||
struct iscsi_session *session = conn->session;
|
||||
struct iscsi_task *task;
|
||||
|
||||
task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr,
|
||||
NULL, 0);
|
||||
if (!task) {
|
||||
if (__iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0)) {
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
iscsi_conn_printk(KERN_ERR, conn, "Could not send TMF.\n");
|
||||
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
|
||||
|
|
@ -1895,6 +1965,7 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error)
|
|||
struct iscsi_task *task;
|
||||
int i;
|
||||
|
||||
restart_cmd_loop:
|
||||
spin_lock_bh(&session->back_lock);
|
||||
for (i = 0; i < session->cmds_max; i++) {
|
||||
task = session->cmds[i];
|
||||
|
|
@ -1903,22 +1974,25 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error)
|
|||
|
||||
if (lun != -1 && lun != task->sc->device->lun)
|
||||
continue;
|
||||
|
||||
__iscsi_get_task(task);
|
||||
spin_unlock_bh(&session->back_lock);
|
||||
/*
|
||||
* The cmd is completing but if this is called from an eh
|
||||
* callout path then when we return scsi-ml owns the cmd. Wait
|
||||
* for the completion path to finish freeing the cmd.
|
||||
*/
|
||||
if (!iscsi_get_task(task)) {
|
||||
spin_unlock_bh(&session->back_lock);
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
udelay(ISCSI_CMD_COMPL_WAIT);
|
||||
spin_lock_bh(&session->frwd_lock);
|
||||
goto restart_cmd_loop;
|
||||
}
|
||||
|
||||
ISCSI_DBG_SESSION(session,
|
||||
"failing sc %p itt 0x%x state %d\n",
|
||||
task->sc, task->itt, task->state);
|
||||
fail_scsi_task(task, error);
|
||||
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
iscsi_put_task(task);
|
||||
spin_lock_bh(&session->frwd_lock);
|
||||
|
||||
spin_lock_bh(&session->back_lock);
|
||||
__fail_scsi_task(task, error);
|
||||
__iscsi_put_task(task);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&session->back_lock);
|
||||
}
|
||||
|
||||
|
|
@ -1943,7 +2017,7 @@ EXPORT_SYMBOL_GPL(iscsi_suspend_queue);
|
|||
|
||||
/**
|
||||
* iscsi_suspend_tx - suspend iscsi_data_xmit
|
||||
* @conn: iscsi conn tp stop processing IO on.
|
||||
* @conn: iscsi conn to stop processing IO on.
|
||||
*
|
||||
* This function sets the suspend bit to prevent iscsi_data_xmit
|
||||
* from sending new IO, and if work is queued on the xmit thread
|
||||
|
|
@ -1956,16 +2030,31 @@ void iscsi_suspend_tx(struct iscsi_conn *conn)
|
|||
|
||||
set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
|
||||
if (ihost->workq)
|
||||
flush_workqueue(ihost->workq);
|
||||
flush_work(&conn->xmitwork);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
|
||||
|
||||
static void iscsi_start_tx(struct iscsi_conn *conn)
|
||||
{
|
||||
clear_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags);
|
||||
iscsi_conn_queue_work(conn);
|
||||
iscsi_conn_queue_xmit(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* iscsi_suspend_rx - Prevent recvwork from running again.
|
||||
* @conn: iscsi conn to stop.
|
||||
*/
|
||||
void iscsi_suspend_rx(struct iscsi_conn *conn)
|
||||
{
|
||||
struct Scsi_Host *shost = conn->session->host;
|
||||
struct iscsi_host *ihost = shost_priv(shost);
|
||||
|
||||
set_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags);
|
||||
if (ihost->workq)
|
||||
flush_work(&conn->recvwork);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_suspend_rx);
|
||||
|
||||
/*
|
||||
* We want to make sure a ping is in flight. It has timed out.
|
||||
* And we are not busy processing a pdu that is making
|
||||
|
|
@ -2008,7 +2097,16 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
|
|||
spin_unlock(&session->back_lock);
|
||||
goto done;
|
||||
}
|
||||
__iscsi_get_task(task);
|
||||
if (!iscsi_get_task(task)) {
|
||||
/*
|
||||
* Racing with the completion path right now, so give it more
|
||||
* time so that path can complete it like normal.
|
||||
*/
|
||||
rc = BLK_EH_RESET_TIMER;
|
||||
task = NULL;
|
||||
spin_unlock(&session->back_lock);
|
||||
goto done;
|
||||
}
|
||||
spin_unlock(&session->back_lock);
|
||||
|
||||
if (session->state != ISCSI_STATE_LOGGED_IN) {
|
||||
|
|
@ -2257,6 +2355,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
|
|||
|
||||
ISCSI_DBG_EH(session, "aborting sc %p\n", sc);
|
||||
|
||||
completion_check:
|
||||
mutex_lock(&session->eh_mutex);
|
||||
spin_lock_bh(&session->frwd_lock);
|
||||
/*
|
||||
|
|
@ -2296,13 +2395,20 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (!iscsi_get_task(task)) {
|
||||
spin_unlock(&session->back_lock);
|
||||
spin_unlock_bh(&session->frwd_lock);
|
||||
mutex_unlock(&session->eh_mutex);
|
||||
/* We are just about to call iscsi_free_task so wait for it. */
|
||||
udelay(ISCSI_CMD_COMPL_WAIT);
|
||||
goto completion_check;
|
||||
}
|
||||
|
||||
ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", sc, task->itt);
|
||||
conn = session->leadconn;
|
||||
iscsi_get_conn(conn->cls_conn);
|
||||
conn->eh_abort_cnt++;
|
||||
age = session->age;
|
||||
|
||||
ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", sc, task->itt);
|
||||
__iscsi_get_task(task);
|
||||
spin_unlock(&session->back_lock);
|
||||
|
||||
if (task->state == ISCSI_TASK_PENDING) {
|
||||
|
|
@ -2828,11 +2934,12 @@ static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session)
|
|||
/**
|
||||
* iscsi_host_remove - remove host and sessions
|
||||
* @shost: scsi host
|
||||
* @is_shutdown: true if called from a driver shutdown callout
|
||||
*
|
||||
* If there are any sessions left, this will initiate the removal and wait
|
||||
* for the completion.
|
||||
*/
|
||||
void iscsi_host_remove(struct Scsi_Host *shost)
|
||||
void iscsi_host_remove(struct Scsi_Host *shost, bool is_shutdown)
|
||||
{
|
||||
struct iscsi_host *ihost = shost_priv(shost);
|
||||
unsigned long flags;
|
||||
|
|
@ -2841,7 +2948,11 @@ void iscsi_host_remove(struct Scsi_Host *shost)
|
|||
ihost->state = ISCSI_HOST_REMOVED;
|
||||
spin_unlock_irqrestore(&ihost->lock, flags);
|
||||
|
||||
iscsi_host_for_each_session(shost, iscsi_notify_host_removed);
|
||||
if (!is_shutdown)
|
||||
iscsi_host_for_each_session(shost, iscsi_notify_host_removed);
|
||||
else
|
||||
iscsi_host_for_each_session(shost, iscsi_force_destroy_session);
|
||||
|
||||
wait_event_interruptible(ihost->session_removal_wq,
|
||||
ihost->num_sessions == 0);
|
||||
if (signal_pending(current))
|
||||
|
|
|
|||
|
|
@ -558,7 +558,11 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
|
|||
return 0;
|
||||
}
|
||||
task->last_xfer = jiffies;
|
||||
__iscsi_get_task(task);
|
||||
if (!iscsi_get_task(task)) {
|
||||
spin_unlock(&session->back_lock);
|
||||
/* Let the path that got the early rsp complete it */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tcp_conn = conn->dd_data;
|
||||
rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
|
||||
|
|
|
|||
|
|
@ -175,13 +175,13 @@ static enum sas_device_type to_dev_type(struct discover_resp *dr)
|
|||
return dr->attached_dev_type;
|
||||
}
|
||||
|
||||
static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
|
||||
static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
|
||||
struct smp_disc_resp *disc_resp)
|
||||
{
|
||||
enum sas_device_type dev_type;
|
||||
enum sas_linkrate linkrate;
|
||||
u8 sas_addr[SAS_ADDR_SIZE];
|
||||
struct smp_resp *resp = rsp;
|
||||
struct discover_resp *dr = &resp->disc;
|
||||
struct discover_resp *dr = &disc_resp->disc;
|
||||
struct sas_ha_struct *ha = dev->port->ha;
|
||||
struct expander_device *ex = &dev->ex_dev;
|
||||
struct ex_phy *phy = &ex->ex_phy[phy_id];
|
||||
|
|
@ -198,7 +198,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
|
|||
BUG_ON(!phy->phy);
|
||||
}
|
||||
|
||||
switch (resp->result) {
|
||||
switch (disc_resp->result) {
|
||||
case SMP_RESP_PHY_VACANT:
|
||||
phy->phy_state = PHY_VACANT;
|
||||
break;
|
||||
|
|
@ -347,12 +347,13 @@ struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id)
|
|||
}
|
||||
|
||||
#define DISCOVER_REQ_SIZE 16
|
||||
#define DISCOVER_RESP_SIZE 56
|
||||
#define DISCOVER_RESP_SIZE sizeof(struct smp_disc_resp)
|
||||
|
||||
static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
|
||||
u8 *disc_resp, int single)
|
||||
struct smp_disc_resp *disc_resp,
|
||||
int single)
|
||||
{
|
||||
struct discover_resp *dr;
|
||||
struct discover_resp *dr = &disc_resp->disc;
|
||||
int res;
|
||||
|
||||
disc_req[9] = single;
|
||||
|
|
@ -361,7 +362,6 @@ static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
|
|||
disc_resp, DISCOVER_RESP_SIZE);
|
||||
if (res)
|
||||
return res;
|
||||
dr = &((struct smp_resp *)disc_resp)->disc;
|
||||
if (memcmp(dev->sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE) == 0) {
|
||||
pr_notice("Found loopback topology, just ignore it!\n");
|
||||
return 0;
|
||||
|
|
@ -375,7 +375,7 @@ int sas_ex_phy_discover(struct domain_device *dev, int single)
|
|||
struct expander_device *ex = &dev->ex_dev;
|
||||
int res = 0;
|
||||
u8 *disc_req;
|
||||
u8 *disc_resp;
|
||||
struct smp_disc_resp *disc_resp;
|
||||
|
||||
disc_req = alloc_smp_req(DISCOVER_REQ_SIZE);
|
||||
if (!disc_req)
|
||||
|
|
@ -429,27 +429,14 @@ static int sas_expander_discover(struct domain_device *dev)
|
|||
|
||||
#define MAX_EXPANDER_PHYS 128
|
||||
|
||||
static void ex_assign_report_general(struct domain_device *dev,
|
||||
struct smp_resp *resp)
|
||||
{
|
||||
struct report_general_resp *rg = &resp->rg;
|
||||
|
||||
dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
|
||||
dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
|
||||
dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
|
||||
dev->ex_dev.t2t_supp = rg->t2t_supp;
|
||||
dev->ex_dev.conf_route_table = rg->conf_route_table;
|
||||
dev->ex_dev.configuring = rg->configuring;
|
||||
memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8);
|
||||
}
|
||||
|
||||
#define RG_REQ_SIZE 8
|
||||
#define RG_RESP_SIZE 32
|
||||
#define RG_RESP_SIZE sizeof(struct smp_rg_resp)
|
||||
|
||||
static int sas_ex_general(struct domain_device *dev)
|
||||
{
|
||||
u8 *rg_req;
|
||||
struct smp_resp *rg_resp;
|
||||
struct smp_rg_resp *rg_resp;
|
||||
struct report_general_resp *rg;
|
||||
int res;
|
||||
int i;
|
||||
|
||||
|
|
@ -480,7 +467,15 @@ static int sas_ex_general(struct domain_device *dev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ex_assign_report_general(dev, rg_resp);
|
||||
rg = &rg_resp->rg;
|
||||
dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
|
||||
dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
|
||||
dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
|
||||
dev->ex_dev.t2t_supp = rg->t2t_supp;
|
||||
dev->ex_dev.conf_route_table = rg->conf_route_table;
|
||||
dev->ex_dev.configuring = rg->configuring;
|
||||
memcpy(dev->ex_dev.enclosure_logical_id,
|
||||
rg->enclosure_logical_id, 8);
|
||||
|
||||
if (dev->ex_dev.configuring) {
|
||||
pr_debug("RG: ex %016llx self-configuring...\n",
|
||||
|
|
@ -681,10 +676,10 @@ int sas_smp_get_phy_events(struct sas_phy *phy)
|
|||
#ifdef CONFIG_SCSI_SAS_ATA
|
||||
|
||||
#define RPS_REQ_SIZE 16
|
||||
#define RPS_RESP_SIZE 60
|
||||
#define RPS_RESP_SIZE sizeof(struct smp_rps_resp)
|
||||
|
||||
int sas_get_report_phy_sata(struct domain_device *dev, int phy_id,
|
||||
struct smp_resp *rps_resp)
|
||||
struct smp_rps_resp *rps_resp)
|
||||
{
|
||||
int res;
|
||||
u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE);
|
||||
|
|
@ -1657,7 +1652,7 @@ int sas_discover_root_expander(struct domain_device *dev)
|
|||
/* ---------- Domain revalidation ---------- */
|
||||
|
||||
static int sas_get_phy_discover(struct domain_device *dev,
|
||||
int phy_id, struct smp_resp *disc_resp)
|
||||
int phy_id, struct smp_disc_resp *disc_resp)
|
||||
{
|
||||
int res;
|
||||
u8 *disc_req;
|
||||
|
|
@ -1673,10 +1668,8 @@ static int sas_get_phy_discover(struct domain_device *dev,
|
|||
disc_resp, DISCOVER_RESP_SIZE);
|
||||
if (res)
|
||||
goto out;
|
||||
else if (disc_resp->result != SMP_RESP_FUNC_ACC) {
|
||||
if (disc_resp->result != SMP_RESP_FUNC_ACC)
|
||||
res = disc_resp->result;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
kfree(disc_req);
|
||||
return res;
|
||||
|
|
@ -1686,7 +1679,7 @@ static int sas_get_phy_change_count(struct domain_device *dev,
|
|||
int phy_id, int *pcc)
|
||||
{
|
||||
int res;
|
||||
struct smp_resp *disc_resp;
|
||||
struct smp_disc_resp *disc_resp;
|
||||
|
||||
disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
|
||||
if (!disc_resp)
|
||||
|
|
@ -1704,19 +1697,17 @@ static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
|
|||
u8 *sas_addr, enum sas_device_type *type)
|
||||
{
|
||||
int res;
|
||||
struct smp_resp *disc_resp;
|
||||
struct discover_resp *dr;
|
||||
struct smp_disc_resp *disc_resp;
|
||||
|
||||
disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
|
||||
if (!disc_resp)
|
||||
return -ENOMEM;
|
||||
dr = &disc_resp->disc;
|
||||
|
||||
res = sas_get_phy_discover(dev, phy_id, disc_resp);
|
||||
if (res == 0) {
|
||||
memcpy(sas_addr, disc_resp->disc.attached_sas_addr,
|
||||
SAS_ADDR_SIZE);
|
||||
*type = to_dev_type(dr);
|
||||
*type = to_dev_type(&disc_resp->disc);
|
||||
if (*type == 0)
|
||||
memset(sas_addr, 0, SAS_ADDR_SIZE);
|
||||
}
|
||||
|
|
@ -1760,7 +1751,7 @@ static int sas_get_ex_change_count(struct domain_device *dev, int *ecc)
|
|||
{
|
||||
int res;
|
||||
u8 *rg_req;
|
||||
struct smp_resp *rg_resp;
|
||||
struct smp_rg_resp *rg_resp;
|
||||
|
||||
rg_req = alloc_smp_req(RG_REQ_SIZE);
|
||||
if (!rg_req)
|
||||
|
|
|
|||
|
|
@ -531,6 +531,7 @@ static int queue_phy_reset(struct sas_phy *phy, int hard_reset)
|
|||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
pm_runtime_get_sync(ha->dev);
|
||||
/* libsas workqueue coordinates ata-eh reset with discovery */
|
||||
mutex_lock(&d->event_lock);
|
||||
d->reset_result = 0;
|
||||
|
|
@ -544,6 +545,7 @@ static int queue_phy_reset(struct sas_phy *phy, int hard_reset)
|
|||
if (rc == 0)
|
||||
rc = d->reset_result;
|
||||
mutex_unlock(&d->event_lock);
|
||||
pm_runtime_put_sync(ha->dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -558,6 +560,7 @@ static int queue_phy_enable(struct sas_phy *phy, int enable)
|
|||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
pm_runtime_get_sync(ha->dev);
|
||||
/* libsas workqueue coordinates ata-eh reset with discovery */
|
||||
mutex_lock(&d->event_lock);
|
||||
d->enable_result = 0;
|
||||
|
|
@ -571,6 +574,7 @@ static int queue_phy_enable(struct sas_phy *phy, int enable)
|
|||
if (rc == 0)
|
||||
rc = d->enable_result;
|
||||
mutex_unlock(&d->event_lock);
|
||||
pm_runtime_put_sync(ha->dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
|
|||
struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
|
||||
int sas_ex_phy_discover(struct domain_device *dev, int single);
|
||||
int sas_get_report_phy_sata(struct domain_device *dev, int phy_id,
|
||||
struct smp_resp *rps_resp);
|
||||
struct smp_rps_resp *rps_resp);
|
||||
int sas_try_ata_reset(struct asd_sas_phy *phy);
|
||||
void sas_hae_reset(struct work_struct *work);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,9 +48,6 @@ struct lpfc_sli2_slim;
|
|||
the NameServer before giving up. */
|
||||
#define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */
|
||||
#define LPFC_DEFAULT_SG_SEG_CNT 64 /* sg element count per scsi cmnd */
|
||||
#define LPFC_DEFAULT_MENLO_SG_SEG_CNT 128 /* sg element count per scsi
|
||||
cmnd for menlo needs nearly twice as for firmware
|
||||
downloads using bsg */
|
||||
|
||||
#define LPFC_DEFAULT_XPSGL_SIZE 256
|
||||
#define LPFC_MAX_SG_TABLESIZE 0xffff
|
||||
|
|
@ -604,7 +601,6 @@ struct lpfc_vport {
|
|||
#define FC_VFI_REGISTERED 0x800000 /* VFI is registered */
|
||||
#define FC_FDISC_COMPLETED 0x1000000/* FDISC completed */
|
||||
#define FC_DISC_DELAYED 0x2000000/* Delay NPort discovery */
|
||||
#define FC_RSCN_MEMENTO 0x4000000/* RSCN cmd processed */
|
||||
|
||||
uint32_t ct_flags;
|
||||
#define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */
|
||||
|
|
@ -987,7 +983,8 @@ struct lpfc_hba {
|
|||
u8 last_seq, u8 cr_cx_cmd);
|
||||
void (*__lpfc_sli_prep_abort_xri)(struct lpfc_iocbq *cmdiocbq,
|
||||
u16 ulp_context, u16 iotag,
|
||||
u8 ulp_class, u16 cqid, bool ia);
|
||||
u8 ulp_class, u16 cqid, bool ia,
|
||||
bool wqec);
|
||||
|
||||
/* expedite pool */
|
||||
struct lpfc_epd_pool epd_pool;
|
||||
|
|
@ -1439,8 +1436,6 @@ struct lpfc_hba {
|
|||
*/
|
||||
#define QUE_BUFTAG_BIT (1<<31)
|
||||
uint32_t buffer_tag_count;
|
||||
int wait_4_mlo_maint_flg;
|
||||
wait_queue_head_t wait_4_mlo_m_q;
|
||||
/* data structure used for latency data collection */
|
||||
#define LPFC_NO_BUCKET 0
|
||||
#define LPFC_LINEAR_BUCKET 1
|
||||
|
|
@ -1475,8 +1470,6 @@ struct lpfc_hba {
|
|||
/* RAS Support */
|
||||
struct lpfc_ras_fwlog ras_fwlog;
|
||||
|
||||
uint8_t menlo_flag; /* menlo generic flags */
|
||||
#define HBA_MENLO_SUPPORT 0x1 /* HBA supports menlo commands */
|
||||
uint32_t iocb_cnt;
|
||||
uint32_t iocb_max;
|
||||
atomic_t sdev_cnt;
|
||||
|
|
|
|||
|
|
@ -921,25 +921,6 @@ lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
|
|||
return scnprintf(buf, PAGE_SIZE, "%s\n", phba->ProgramType);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_mlomgmt_show - Return the Menlo Maintenance sli flag
|
||||
* @dev: class converted to a Scsi_host structure.
|
||||
* @attr: device attribute, not used.
|
||||
* @buf: on return contains the Menlo Maintenance sli flag.
|
||||
*
|
||||
* Returns: size of formatted string.
|
||||
**/
|
||||
static ssize_t
|
||||
lpfc_mlomgmt_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
(phba->sli.sli_flag & LPFC_MENLO_MAINT));
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_vportnum_show - Return the port number in ascii of the hba
|
||||
* @dev: class converted to a Scsi_host structure.
|
||||
|
|
@ -1109,10 +1090,7 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
|
|||
"Unknown\n");
|
||||
break;
|
||||
}
|
||||
if (phba->sli.sli_flag & LPFC_MENLO_MAINT)
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
" Menlo Maint Mode\n");
|
||||
else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
|
||||
if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
|
||||
if (vport->fc_flag & FC_PUBLIC_LOOP)
|
||||
len += scnprintf(buf + len, PAGE_SIZE-len,
|
||||
" Public Loop\n");
|
||||
|
|
@ -2827,7 +2805,6 @@ static DEVICE_ATTR(option_rom_version, S_IRUGO,
|
|||
lpfc_option_rom_version_show, NULL);
|
||||
static DEVICE_ATTR(num_discovered_ports, S_IRUGO,
|
||||
lpfc_num_discovered_ports_show, NULL);
|
||||
static DEVICE_ATTR(menlo_mgmt_mode, S_IRUGO, lpfc_mlomgmt_show, NULL);
|
||||
static DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL);
|
||||
static DEVICE_ATTR_RO(lpfc_drvr_version);
|
||||
static DEVICE_ATTR_RO(lpfc_enable_fip);
|
||||
|
|
@ -6220,7 +6197,6 @@ static struct attribute *lpfc_hba_attrs[] = {
|
|||
&dev_attr_option_rom_version.attr,
|
||||
&dev_attr_link_state.attr,
|
||||
&dev_attr_num_discovered_ports.attr,
|
||||
&dev_attr_menlo_mgmt_mode.attr,
|
||||
&dev_attr_lpfc_drvr_version.attr,
|
||||
&dev_attr_lpfc_enable_fip.attr,
|
||||
&dev_attr_lpfc_temp_sensor.attr,
|
||||
|
|
@ -7396,7 +7372,6 @@ lpfc_get_hba_function_mode(struct lpfc_hba *phba)
|
|||
case PCI_DEVICE_ID_LANCER_FCOE:
|
||||
case PCI_DEVICE_ID_LANCER_FCOE_VF:
|
||||
case PCI_DEVICE_ID_ZEPHYR_DCSP:
|
||||
case PCI_DEVICE_ID_HORNET:
|
||||
case PCI_DEVICE_ID_TIGERSHARK:
|
||||
case PCI_DEVICE_ID_TOMCAT:
|
||||
phba->hba_flag |= HBA_FCOE_MODE;
|
||||
|
|
|
|||
|
|
@ -88,17 +88,9 @@ struct lpfc_bsg_mbox {
|
|||
uint32_t outExtWLen; /* from app */
|
||||
};
|
||||
|
||||
#define MENLO_DID 0x0000FC0E
|
||||
|
||||
struct lpfc_bsg_menlo {
|
||||
struct lpfc_iocbq *cmdiocbq;
|
||||
struct lpfc_dmabuf *rmp;
|
||||
};
|
||||
|
||||
#define TYPE_EVT 1
|
||||
#define TYPE_IOCB 2
|
||||
#define TYPE_MBOX 3
|
||||
#define TYPE_MENLO 4
|
||||
struct bsg_job_data {
|
||||
uint32_t type;
|
||||
struct bsg_job *set_job; /* job waiting for this iocb to finish */
|
||||
|
|
@ -106,7 +98,6 @@ struct bsg_job_data {
|
|||
struct lpfc_bsg_event *evt;
|
||||
struct lpfc_bsg_iocb iocb;
|
||||
struct lpfc_bsg_mbox mbox;
|
||||
struct lpfc_bsg_menlo menlo;
|
||||
} context_un;
|
||||
};
|
||||
|
||||
|
|
@ -3502,15 +3493,6 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba,
|
|||
"1226 mbox: set_variable 0x%x, 0x%x\n",
|
||||
mb->un.varWords[0],
|
||||
mb->un.varWords[1]);
|
||||
if ((mb->un.varWords[0] == SETVAR_MLOMNT)
|
||||
&& (mb->un.varWords[1] == 1)) {
|
||||
phba->wait_4_mlo_maint_flg = 1;
|
||||
} else if (mb->un.varWords[0] == SETVAR_MLORST) {
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
phba->link_flag &= ~LS_LOOPBACK_MODE;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
phba->fc_topology = LPFC_TOPOLOGY_PT_PT;
|
||||
}
|
||||
break;
|
||||
case MBX_READ_SPARM64:
|
||||
case MBX_REG_LOGIN:
|
||||
|
|
@ -4992,283 +4974,6 @@ lpfc_bsg_mbox_cmd(struct bsg_job *job)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_bsg_menlo_cmd_cmp - lpfc_menlo_cmd completion handler
|
||||
* @phba: Pointer to HBA context object.
|
||||
* @cmdiocbq: Pointer to command iocb.
|
||||
* @rspiocbq: Pointer to response iocb.
|
||||
*
|
||||
* This function is the completion handler for iocbs issued using
|
||||
* lpfc_menlo_cmd function. This function is called by the
|
||||
* ring event handler function without any lock held. This function
|
||||
* can be called from both worker thread context and interrupt
|
||||
* context. This function also can be called from another thread which
|
||||
* cleans up the SLI layer objects.
|
||||
* This function copies the contents of the response iocb to the
|
||||
* response iocb memory object provided by the caller of
|
||||
* lpfc_sli_issue_iocb_wait and then wakes up the thread which
|
||||
* sleeps for the iocb completion.
|
||||
**/
|
||||
static void
|
||||
lpfc_bsg_menlo_cmd_cmp(struct lpfc_hba *phba,
|
||||
struct lpfc_iocbq *cmdiocbq,
|
||||
struct lpfc_iocbq *rspiocbq)
|
||||
{
|
||||
struct bsg_job_data *dd_data;
|
||||
struct bsg_job *job;
|
||||
struct fc_bsg_reply *bsg_reply;
|
||||
IOCB_t *rsp;
|
||||
struct lpfc_dmabuf *bmp, *cmp, *rmp;
|
||||
struct lpfc_bsg_menlo *menlo;
|
||||
unsigned long flags;
|
||||
struct menlo_response *menlo_resp;
|
||||
unsigned int rsp_size;
|
||||
int rc = 0;
|
||||
|
||||
dd_data = cmdiocbq->context_un.dd_data;
|
||||
cmp = cmdiocbq->cmd_dmabuf;
|
||||
bmp = cmdiocbq->bpl_dmabuf;
|
||||
menlo = &dd_data->context_un.menlo;
|
||||
rmp = menlo->rmp;
|
||||
rsp = &rspiocbq->iocb;
|
||||
|
||||
/* Determine if job has been aborted */
|
||||
spin_lock_irqsave(&phba->ct_ev_lock, flags);
|
||||
job = dd_data->set_job;
|
||||
if (job) {
|
||||
bsg_reply = job->reply;
|
||||
/* Prevent timeout handling from trying to abort job */
|
||||
job->dd_data = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
|
||||
|
||||
/* Copy the job data or set the failing status for the job */
|
||||
|
||||
if (job) {
|
||||
/* always return the xri, this would be used in the case
|
||||
* of a menlo download to allow the data to be sent as a
|
||||
* continuation of the exchange.
|
||||
*/
|
||||
|
||||
menlo_resp = (struct menlo_response *)
|
||||
bsg_reply->reply_data.vendor_reply.vendor_rsp;
|
||||
menlo_resp->xri = rsp->ulpContext;
|
||||
if (rsp->ulpStatus) {
|
||||
if (rsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
|
||||
switch (rsp->un.ulpWord[4] & IOERR_PARAM_MASK) {
|
||||
case IOERR_SEQUENCE_TIMEOUT:
|
||||
rc = -ETIMEDOUT;
|
||||
break;
|
||||
case IOERR_INVALID_RPI:
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
default:
|
||||
rc = -EACCES;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
rc = -EACCES;
|
||||
}
|
||||
} else {
|
||||
rsp_size = rsp->un.genreq64.bdl.bdeSize;
|
||||
bsg_reply->reply_payload_rcv_len =
|
||||
lpfc_bsg_copy_data(rmp, &job->reply_payload,
|
||||
rsp_size, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lpfc_sli_release_iocbq(phba, cmdiocbq);
|
||||
lpfc_free_bsg_buffers(phba, cmp);
|
||||
lpfc_free_bsg_buffers(phba, rmp);
|
||||
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
|
||||
kfree(bmp);
|
||||
kfree(dd_data);
|
||||
|
||||
/* Complete the job if active */
|
||||
|
||||
if (job) {
|
||||
bsg_reply->result = rc;
|
||||
bsg_job_done(job, bsg_reply->result,
|
||||
bsg_reply->reply_payload_rcv_len);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_menlo_cmd - send an ioctl for menlo hardware
|
||||
* @job: fc_bsg_job to handle
|
||||
*
|
||||
* This function issues a gen request 64 CR ioctl for all menlo cmd requests,
|
||||
* all the command completions will return the xri for the command.
|
||||
* For menlo data requests a gen request 64 CX is used to continue the exchange
|
||||
* supplied in the menlo request header xri field.
|
||||
**/
|
||||
static int
|
||||
lpfc_menlo_cmd(struct bsg_job *job)
|
||||
{
|
||||
struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
|
||||
struct fc_bsg_request *bsg_request = job->request;
|
||||
struct fc_bsg_reply *bsg_reply = job->reply;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_iocbq *cmdiocbq;
|
||||
IOCB_t *cmd;
|
||||
int rc = 0;
|
||||
struct menlo_command *menlo_cmd;
|
||||
struct lpfc_dmabuf *bmp = NULL, *cmp = NULL, *rmp = NULL;
|
||||
int request_nseg;
|
||||
int reply_nseg;
|
||||
struct bsg_job_data *dd_data;
|
||||
struct ulp_bde64 *bpl = NULL;
|
||||
|
||||
/* in case no data is returned return just the return code */
|
||||
bsg_reply->reply_payload_rcv_len = 0;
|
||||
|
||||
if (job->request_len <
|
||||
sizeof(struct fc_bsg_request) +
|
||||
sizeof(struct menlo_command)) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
|
||||
"2784 Received MENLO_CMD request below "
|
||||
"minimum size\n");
|
||||
rc = -ERANGE;
|
||||
goto no_dd_data;
|
||||
}
|
||||
|
||||
if (job->reply_len < sizeof(*bsg_reply) +
|
||||
sizeof(struct menlo_response)) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
|
||||
"2785 Received MENLO_CMD reply below "
|
||||
"minimum size\n");
|
||||
rc = -ERANGE;
|
||||
goto no_dd_data;
|
||||
}
|
||||
|
||||
if (!(phba->menlo_flag & HBA_MENLO_SUPPORT)) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
|
||||
"2786 Adapter does not support menlo "
|
||||
"commands\n");
|
||||
rc = -EPERM;
|
||||
goto no_dd_data;
|
||||
}
|
||||
|
||||
menlo_cmd = (struct menlo_command *)
|
||||
bsg_request->rqst_data.h_vendor.vendor_cmd;
|
||||
|
||||
/* allocate our bsg tracking structure */
|
||||
dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
|
||||
if (!dd_data) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
|
||||
"2787 Failed allocation of dd_data\n");
|
||||
rc = -ENOMEM;
|
||||
goto no_dd_data;
|
||||
}
|
||||
|
||||
bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
|
||||
if (!bmp) {
|
||||
rc = -ENOMEM;
|
||||
goto free_dd;
|
||||
}
|
||||
|
||||
bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys);
|
||||
if (!bmp->virt) {
|
||||
rc = -ENOMEM;
|
||||
goto free_bmp;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&bmp->list);
|
||||
|
||||
bpl = (struct ulp_bde64 *)bmp->virt;
|
||||
request_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64);
|
||||
cmp = lpfc_alloc_bsg_buffers(phba, job->request_payload.payload_len,
|
||||
1, bpl, &request_nseg);
|
||||
if (!cmp) {
|
||||
rc = -ENOMEM;
|
||||
goto free_bmp;
|
||||
}
|
||||
lpfc_bsg_copy_data(cmp, &job->request_payload,
|
||||
job->request_payload.payload_len, 1);
|
||||
|
||||
bpl += request_nseg;
|
||||
reply_nseg = LPFC_BPL_SIZE/sizeof(struct ulp_bde64) - request_nseg;
|
||||
rmp = lpfc_alloc_bsg_buffers(phba, job->reply_payload.payload_len, 0,
|
||||
bpl, &reply_nseg);
|
||||
if (!rmp) {
|
||||
rc = -ENOMEM;
|
||||
goto free_cmp;
|
||||
}
|
||||
|
||||
cmdiocbq = lpfc_sli_get_iocbq(phba);
|
||||
if (!cmdiocbq) {
|
||||
rc = -ENOMEM;
|
||||
goto free_rmp;
|
||||
}
|
||||
|
||||
cmd = &cmdiocbq->iocb;
|
||||
cmd->un.genreq64.bdl.ulpIoTag32 = 0;
|
||||
cmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
|
||||
cmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
|
||||
cmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
|
||||
cmd->un.genreq64.bdl.bdeSize =
|
||||
(request_nseg + reply_nseg) * sizeof(struct ulp_bde64);
|
||||
cmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
|
||||
cmd->un.genreq64.w5.hcsw.Dfctl = 0;
|
||||
cmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CMD;
|
||||
cmd->un.genreq64.w5.hcsw.Type = MENLO_TRANSPORT_TYPE; /* 0xfe */
|
||||
cmd->ulpBdeCount = 1;
|
||||
cmd->ulpClass = CLASS3;
|
||||
cmd->ulpOwner = OWN_CHIP;
|
||||
cmd->ulpLe = 1; /* Limited Edition */
|
||||
cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
|
||||
cmdiocbq->vport = phba->pport;
|
||||
/* We want the firmware to timeout before we do */
|
||||
cmd->ulpTimeout = MENLO_TIMEOUT - 5;
|
||||
cmdiocbq->cmd_cmpl = lpfc_bsg_menlo_cmd_cmp;
|
||||
cmdiocbq->context_un.dd_data = dd_data;
|
||||
cmdiocbq->cmd_dmabuf = cmp;
|
||||
cmdiocbq->bpl_dmabuf = bmp;
|
||||
if (menlo_cmd->cmd == LPFC_BSG_VENDOR_MENLO_CMD) {
|
||||
cmd->ulpCommand = CMD_GEN_REQUEST64_CR;
|
||||
cmd->ulpPU = MENLO_PU; /* 3 */
|
||||
cmd->un.ulpWord[4] = MENLO_DID; /* 0x0000FC0E */
|
||||
cmd->ulpContext = MENLO_CONTEXT; /* 0 */
|
||||
} else {
|
||||
cmd->ulpCommand = CMD_GEN_REQUEST64_CX;
|
||||
cmd->ulpPU = 1;
|
||||
cmd->un.ulpWord[4] = 0;
|
||||
cmd->ulpContext = menlo_cmd->xri;
|
||||
}
|
||||
|
||||
dd_data->type = TYPE_MENLO;
|
||||
dd_data->set_job = job;
|
||||
dd_data->context_un.menlo.cmdiocbq = cmdiocbq;
|
||||
dd_data->context_un.menlo.rmp = rmp;
|
||||
job->dd_data = dd_data;
|
||||
|
||||
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq,
|
||||
MENLO_TIMEOUT - 5);
|
||||
if (rc == IOCB_SUCCESS)
|
||||
return 0; /* done for now */
|
||||
|
||||
lpfc_sli_release_iocbq(phba, cmdiocbq);
|
||||
|
||||
free_rmp:
|
||||
lpfc_free_bsg_buffers(phba, rmp);
|
||||
free_cmp:
|
||||
lpfc_free_bsg_buffers(phba, cmp);
|
||||
free_bmp:
|
||||
if (bmp->virt)
|
||||
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
|
||||
kfree(bmp);
|
||||
free_dd:
|
||||
kfree(dd_data);
|
||||
no_dd_data:
|
||||
/* make error code available to userspace */
|
||||
bsg_reply->result = rc;
|
||||
job->dd_data = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_forced_link_speed(struct bsg_job *job)
|
||||
{
|
||||
|
|
@ -5823,10 +5528,6 @@ lpfc_bsg_hst_vendor(struct bsg_job *job)
|
|||
case LPFC_BSG_VENDOR_MBOX:
|
||||
rc = lpfc_bsg_mbox_cmd(job);
|
||||
break;
|
||||
case LPFC_BSG_VENDOR_MENLO_CMD:
|
||||
case LPFC_BSG_VENDOR_MENLO_DATA:
|
||||
rc = lpfc_menlo_cmd(job);
|
||||
break;
|
||||
case LPFC_BSG_VENDOR_FORCED_LINK_SPEED:
|
||||
rc = lpfc_forced_link_speed(job);
|
||||
break;
|
||||
|
|
@ -5979,31 +5680,6 @@ lpfc_bsg_timeout(struct bsg_job *job)
|
|||
phba->mbox_ext_buf_ctx.state = LPFC_BSG_MBOX_ABTS;
|
||||
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
|
||||
break;
|
||||
case TYPE_MENLO:
|
||||
/* Check to see if IOCB was issued to the port or not. If not,
|
||||
* remove it from the txq queue and call cancel iocbs.
|
||||
* Otherwise, call abort iotag.
|
||||
*/
|
||||
cmdiocb = dd_data->context_un.menlo.cmdiocbq;
|
||||
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, flags);
|
||||
list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq,
|
||||
list) {
|
||||
if (check_iocb == cmdiocb) {
|
||||
list_move_tail(&check_iocb->list, &completions);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (list_empty(&completions))
|
||||
lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb, NULL);
|
||||
spin_unlock_irqrestore(&phba->hbalock, flags);
|
||||
if (!list_empty(&completions)) {
|
||||
lpfc_sli_cancel_iocbs(phba, &completions,
|
||||
IOSTAT_LOCAL_REJECT,
|
||||
IOERR_SLI_ABORTED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2010-2015 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
|
@ -33,8 +33,6 @@
|
|||
#define LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK 5
|
||||
#define LPFC_BSG_VENDOR_GET_MGMT_REV 6
|
||||
#define LPFC_BSG_VENDOR_MBOX 7
|
||||
#define LPFC_BSG_VENDOR_MENLO_CMD 8
|
||||
#define LPFC_BSG_VENDOR_MENLO_DATA 9
|
||||
#define LPFC_BSG_VENDOR_DIAG_MODE_END 10
|
||||
#define LPFC_BSG_VENDOR_LINK_DIAG_TEST 11
|
||||
#define LPFC_BSG_VENDOR_FORCED_LINK_SPEED 14
|
||||
|
|
@ -131,16 +129,6 @@ struct dfc_mbox_req {
|
|||
uint32_t extSeqNum;
|
||||
};
|
||||
|
||||
/* Used for menlo command or menlo data. The xri is only used for menlo data */
|
||||
struct menlo_command {
|
||||
uint32_t cmd;
|
||||
uint32_t xri;
|
||||
};
|
||||
|
||||
struct menlo_response {
|
||||
uint32_t xri; /* return the xri of the iocb exchange */
|
||||
};
|
||||
|
||||
/*
|
||||
* macros and data structures for handling sli-config mailbox command
|
||||
* pass-through support, this header file is shared between user and
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@ void lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba,
|
|||
u8 cr_cx_cmd);
|
||||
void lpfc_sli_prep_abort_xri(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
|
||||
u16 ulp_context, u16 iotag, u8 ulp_class, u16 cqid,
|
||||
bool ia);
|
||||
bool ia, bool wqec);
|
||||
struct lpfc_sglq *__lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xri);
|
||||
struct lpfc_sglq *__lpfc_sli_get_nvmet_sglq(struct lpfc_hba *phba,
|
||||
struct lpfc_iocbq *piocbq);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2007-2015 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
|
@ -2607,8 +2607,8 @@ lpfc_debugfs_multixripools_write(struct file *file, const char __user *buf,
|
|||
struct lpfc_sli4_hdw_queue *qp;
|
||||
struct lpfc_multixri_pool *multixri_pool;
|
||||
|
||||
if (nbytes > 64)
|
||||
nbytes = 64;
|
||||
if (nbytes > sizeof(mybuf) - 1)
|
||||
nbytes = sizeof(mybuf) - 1;
|
||||
|
||||
memset(mybuf, 0, sizeof(mybuf));
|
||||
|
||||
|
|
@ -2688,8 +2688,8 @@ lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf,
|
|||
if (!phba->targetport)
|
||||
return -ENXIO;
|
||||
|
||||
if (nbytes > 64)
|
||||
nbytes = 64;
|
||||
if (nbytes > sizeof(mybuf) - 1)
|
||||
nbytes = sizeof(mybuf) - 1;
|
||||
|
||||
memset(mybuf, 0, sizeof(mybuf));
|
||||
|
||||
|
|
@ -2826,8 +2826,8 @@ lpfc_debugfs_ioktime_write(struct file *file, const char __user *buf,
|
|||
char mybuf[64];
|
||||
char *pbuf;
|
||||
|
||||
if (nbytes > 64)
|
||||
nbytes = 64;
|
||||
if (nbytes > sizeof(mybuf) - 1)
|
||||
nbytes = sizeof(mybuf) - 1;
|
||||
|
||||
memset(mybuf, 0, sizeof(mybuf));
|
||||
|
||||
|
|
@ -2954,8 +2954,8 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf,
|
|||
char mybuf[64];
|
||||
char *pbuf;
|
||||
|
||||
if (nbytes > 63)
|
||||
nbytes = 63;
|
||||
if (nbytes > sizeof(mybuf) - 1)
|
||||
nbytes = sizeof(mybuf) - 1;
|
||||
|
||||
memset(mybuf, 0, sizeof(mybuf));
|
||||
|
||||
|
|
@ -3060,8 +3060,8 @@ lpfc_debugfs_hdwqstat_write(struct file *file, const char __user *buf,
|
|||
char *pbuf;
|
||||
int i;
|
||||
|
||||
if (nbytes > 64)
|
||||
nbytes = 64;
|
||||
if (nbytes > sizeof(mybuf) - 1)
|
||||
nbytes = sizeof(mybuf) - 1;
|
||||
|
||||
memset(mybuf, 0, sizeof(mybuf));
|
||||
|
||||
|
|
|
|||
|
|
@ -1790,18 +1790,20 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
|
|||
|
||||
/* Move this back to NPR state */
|
||||
if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
|
||||
/* The new_ndlp is replacing ndlp totally, so we need
|
||||
* to put ndlp on UNUSED list and try to free it.
|
||||
/* The ndlp doesn't have a portname yet, but does have an
|
||||
* NPort ID. The new_ndlp portname matches the Rport's
|
||||
* portname. Reinstantiate the new_ndlp and reset the ndlp.
|
||||
*/
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
|
||||
"3179 PLOGI confirm NEW: %x %x\n",
|
||||
new_ndlp->nlp_DID, keepDID);
|
||||
|
||||
/* Two ndlps cannot have the same did on the nodelist.
|
||||
* Note: for this case, ndlp has a NULL WWPN so setting
|
||||
* the nlp_fc4_type isn't required.
|
||||
* The KeepDID and keep_nlp_fc4_type need to be swapped
|
||||
* because ndlp is inflight with no WWPN.
|
||||
*/
|
||||
ndlp->nlp_DID = keepDID;
|
||||
ndlp->nlp_fc4_type = keep_nlp_fc4_type;
|
||||
lpfc_nlp_set_state(vport, ndlp, keep_nlp_state);
|
||||
if (phba->sli_rev == LPFC_SLI_REV4 &&
|
||||
active_rrqs_xri_bitmap)
|
||||
|
|
@ -1816,9 +1818,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
|
|||
|
||||
lpfc_unreg_rpi(vport, ndlp);
|
||||
|
||||
/* Two ndlps cannot have the same did and the fc4
|
||||
* type must be transferred because the ndlp is in
|
||||
* flight.
|
||||
/* The ndlp and new_ndlp both have WWPNs but are swapping
|
||||
* NPort Ids and attributes.
|
||||
*/
|
||||
ndlp->nlp_DID = keepDID;
|
||||
ndlp->nlp_fc4_type = keep_nlp_fc4_type;
|
||||
|
|
@ -1886,7 +1887,6 @@ lpfc_end_rscn(struct lpfc_vport *vport)
|
|||
else {
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vport->fc_flag &= ~FC_RSCN_MODE;
|
||||
vport->fc_flag |= FC_RSCN_MEMENTO;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
}
|
||||
}
|
||||
|
|
@ -2434,14 +2434,13 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
|||
u32 local_nlp_type, elscmd;
|
||||
|
||||
/*
|
||||
* If discovery was kicked off from RSCN mode,
|
||||
* the FC4 types supported from a
|
||||
* If we are in RSCN mode, the FC4 types supported from a
|
||||
* previous GFT_ID command may not be accurate. So, if we
|
||||
* are a NVME Initiator, always look for the possibility of
|
||||
* the remote NPort beng a NVME Target.
|
||||
*/
|
||||
if (phba->sli_rev == LPFC_SLI_REV4 &&
|
||||
vport->fc_flag & (FC_RSCN_MODE | FC_RSCN_MEMENTO) &&
|
||||
vport->fc_flag & FC_RSCN_MODE &&
|
||||
vport->nvmei_support)
|
||||
ndlp->nlp_fc4_type |= NLP_FC4_NVME;
|
||||
local_nlp_type = ndlp->nlp_fc4_type;
|
||||
|
|
@ -4571,15 +4570,6 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
case IOSTAT_LOCAL_REJECT:
|
||||
switch ((ulp_word4 & IOERR_PARAM_MASK)) {
|
||||
case IOERR_LOOP_OPEN_FAILURE:
|
||||
if (cmd == ELS_CMD_FLOGI) {
|
||||
if (PCI_DEVICE_ID_HORNET ==
|
||||
phba->pcidev->device) {
|
||||
phba->fc_topology = LPFC_TOPOLOGY_LOOP;
|
||||
phba->pport->fc_myDID = 0;
|
||||
phba->alpa_map[0] = 0;
|
||||
phba->alpa_map[1] = 0;
|
||||
}
|
||||
}
|
||||
if (cmd == ELS_CMD_PLOGI && cmdiocb->retry == 0)
|
||||
delay = 1000;
|
||||
retry = 1;
|
||||
|
|
@ -7915,7 +7905,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|||
if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
|
||||
!(vport->fc_flag & FC_RSCN_DISCOVERY)) {
|
||||
vport->fc_flag |= FC_RSCN_MODE;
|
||||
vport->fc_flag &= ~FC_RSCN_MEMENTO;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
if (rscn_cnt) {
|
||||
cmd = vport->fc_rscn_id_list[rscn_cnt-1]->virt;
|
||||
|
|
@ -7965,7 +7954,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vport->fc_flag |= FC_RSCN_MODE;
|
||||
vport->fc_flag &= ~FC_RSCN_MEMENTO;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd;
|
||||
/* Indicate we are done walking fc_rscn_id_list on this vport */
|
||||
|
|
|
|||
|
|
@ -1354,8 +1354,7 @@ lpfc_linkup_port(struct lpfc_vport *vport)
|
|||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY |
|
||||
FC_RSCN_MEMENTO | FC_RSCN_MODE |
|
||||
FC_NLP_MORE | FC_RSCN_DISCOVERY);
|
||||
FC_RSCN_MODE | FC_NLP_MORE | FC_RSCN_DISCOVERY);
|
||||
vport->fc_flag |= FC_NDISC_ACTIVE;
|
||||
vport->fc_ns_retry = 0;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
|
@ -3763,18 +3762,8 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|||
}
|
||||
|
||||
phba->fc_eventTag = la->eventTag;
|
||||
if (phba->sli_rev < LPFC_SLI_REV4) {
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
if (bf_get(lpfc_mbx_read_top_mm, la))
|
||||
phba->sli.sli_flag |= LPFC_MENLO_MAINT;
|
||||
else
|
||||
phba->sli.sli_flag &= ~LPFC_MENLO_MAINT;
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||
}
|
||||
|
||||
phba->link_events++;
|
||||
if ((attn_type == LPFC_ATT_LINK_UP) &&
|
||||
!(phba->sli.sli_flag & LPFC_MENLO_MAINT)) {
|
||||
if (attn_type == LPFC_ATT_LINK_UP) {
|
||||
phba->fc_stat.LinkUp++;
|
||||
if (phba->link_flag & LS_LOOPBACK_MODE) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
|
|
@ -3788,15 +3777,13 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|||
} else {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
"1303 Link Up Event x%x received "
|
||||
"Data: x%x x%x x%x x%x x%x x%x %d\n",
|
||||
"Data: x%x x%x x%x x%x x%x\n",
|
||||
la->eventTag, phba->fc_eventTag,
|
||||
bf_get(lpfc_mbx_read_top_alpa_granted,
|
||||
la),
|
||||
bf_get(lpfc_mbx_read_top_link_spd, la),
|
||||
phba->alpa_map[0],
|
||||
bf_get(lpfc_mbx_read_top_mm, la),
|
||||
bf_get(lpfc_mbx_read_top_fa, la),
|
||||
phba->wait_4_mlo_maint_flg);
|
||||
bf_get(lpfc_mbx_read_top_fa, la));
|
||||
}
|
||||
lpfc_mbx_process_link_up(phba, la);
|
||||
|
||||
|
|
@ -3816,58 +3803,25 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|||
else if (attn_type == LPFC_ATT_UNEXP_WWPN)
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
"1313 Link Down Unexpected FA WWPN Event x%x "
|
||||
"received Data: x%x x%x x%x x%x x%x\n",
|
||||
"received Data: x%x x%x x%x x%x\n",
|
||||
la->eventTag, phba->fc_eventTag,
|
||||
phba->pport->port_state, vport->fc_flag,
|
||||
bf_get(lpfc_mbx_read_top_mm, la),
|
||||
bf_get(lpfc_mbx_read_top_fa, la));
|
||||
else
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
"1305 Link Down Event x%x received "
|
||||
"Data: x%x x%x x%x x%x x%x\n",
|
||||
"Data: x%x x%x x%x x%x\n",
|
||||
la->eventTag, phba->fc_eventTag,
|
||||
phba->pport->port_state, vport->fc_flag,
|
||||
bf_get(lpfc_mbx_read_top_mm, la),
|
||||
bf_get(lpfc_mbx_read_top_fa, la));
|
||||
lpfc_mbx_issue_link_down(phba);
|
||||
}
|
||||
if (phba->sli.sli_flag & LPFC_MENLO_MAINT &&
|
||||
attn_type == LPFC_ATT_LINK_UP) {
|
||||
if (phba->link_state != LPFC_LINK_DOWN) {
|
||||
phba->fc_stat.LinkDown++;
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
"1312 Link Down Event x%x received "
|
||||
"Data: x%x x%x x%x\n",
|
||||
la->eventTag, phba->fc_eventTag,
|
||||
phba->pport->port_state, vport->fc_flag);
|
||||
lpfc_mbx_issue_link_down(phba);
|
||||
} else
|
||||
lpfc_enable_la(phba);
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
|
||||
"1310 Menlo Maint Mode Link up Event x%x rcvd "
|
||||
"Data: x%x x%x x%x\n",
|
||||
la->eventTag, phba->fc_eventTag,
|
||||
phba->pport->port_state, vport->fc_flag);
|
||||
/*
|
||||
* The cmnd that triggered this will be waiting for this
|
||||
* signal.
|
||||
*/
|
||||
/* WAKEUP for MENLO_SET_MODE or MENLO_RESET command. */
|
||||
if (phba->wait_4_mlo_maint_flg) {
|
||||
phba->wait_4_mlo_maint_flg = 0;
|
||||
wake_up_interruptible(&phba->wait_4_mlo_m_q);
|
||||
}
|
||||
}
|
||||
|
||||
if ((phba->sli_rev < LPFC_SLI_REV4) &&
|
||||
bf_get(lpfc_mbx_read_top_fa, la)) {
|
||||
if (phba->sli.sli_flag & LPFC_MENLO_MAINT)
|
||||
lpfc_issue_clear_la(phba, vport);
|
||||
bf_get(lpfc_mbx_read_top_fa, la))
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
|
||||
"1311 fa %d\n",
|
||||
bf_get(lpfc_mbx_read_top_fa, la));
|
||||
}
|
||||
|
||||
lpfc_mbx_cmpl_read_topology_free_mbuf:
|
||||
lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
|
||||
|
|
|
|||
|
|
@ -1728,7 +1728,6 @@ struct lpfc_fdmi_reg_portattr {
|
|||
#define PCI_DEVICE_ID_HELIOS_SCSP 0xfd11
|
||||
#define PCI_DEVICE_ID_HELIOS_DCSP 0xfd12
|
||||
#define PCI_DEVICE_ID_ZEPHYR 0xfe00
|
||||
#define PCI_DEVICE_ID_HORNET 0xfe05
|
||||
#define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11
|
||||
#define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12
|
||||
#define PCI_VENDOR_ID_SERVERENGINE 0x19a2
|
||||
|
|
@ -1773,7 +1772,6 @@ struct lpfc_fdmi_reg_portattr {
|
|||
#define ZEPHYR_JEDEC_ID 0x0577
|
||||
#define VIPER_JEDEC_ID 0x4838
|
||||
#define SATURN_JEDEC_ID 0x1004
|
||||
#define HORNET_JDEC_ID 0x2057706D
|
||||
|
||||
#define JEDEC_ID_MASK 0x0FFFF000
|
||||
#define JEDEC_ID_SHIFT 12
|
||||
|
|
@ -3074,7 +3072,6 @@ struct lpfc_mbx_read_top {
|
|||
#define lpfc_mbx_read_top_topology_WORD word3
|
||||
#define LPFC_TOPOLOGY_PT_PT 0x01 /* Topology is pt-pt / pt-fabric */
|
||||
#define LPFC_TOPOLOGY_LOOP 0x02 /* Topology is FC-AL */
|
||||
#define LPFC_TOPOLOGY_MM 0x05 /* maint mode zephtr to menlo */
|
||||
/* store the LILP AL_PA position map into */
|
||||
struct ulp_bde64 lilpBde64;
|
||||
#define LPFC_ALPA_MAP_SIZE 128
|
||||
|
|
@ -4423,11 +4420,4 @@ lpfc_error_lost_link(u32 ulp_status, u32 ulp_word4)
|
|||
ulp_word4 == IOERR_SLI_DOWN));
|
||||
}
|
||||
|
||||
#define MENLO_TRANSPORT_TYPE 0xfe
|
||||
#define MENLO_CONTEXT 0
|
||||
#define MENLO_PU 3
|
||||
#define MENLO_TIMEOUT 30
|
||||
#define SETVAR_MLOMNT 0x103107
|
||||
#define SETVAR_MLORST 0x103007
|
||||
|
||||
#define BPL_ALIGN_SZ 8 /* 8 byte alignment for bpl and mbufs */
|
||||
|
|
|
|||
|
|
@ -4736,7 +4736,6 @@ struct create_xri_wqe {
|
|||
uint32_t rsvd_12_15[4]; /* word 12-15 */
|
||||
};
|
||||
|
||||
#define INHIBIT_ABORT 1
|
||||
#define T_REQUEST_TAG 3
|
||||
#define T_XRI_TAG 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
|
||||
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
|
||||
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
|
|
@ -60,8 +60,6 @@ const struct pci_device_id lpfc_id_table[] = {
|
|||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HORNET,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP,
|
||||
|
|
|
|||
|
|
@ -375,6 +375,9 @@ lpfc_update_vport_wwn(struct lpfc_vport *vport)
|
|||
if (phba->sli_rev == LPFC_SLI_REV4 &&
|
||||
vport->port_type == LPFC_PHYSICAL_PORT &&
|
||||
phba->sli4_hba.fawwpn_flag & LPFC_FAWWPN_FABRIC) {
|
||||
if (!(phba->sli4_hba.fawwpn_flag & LPFC_FAWWPN_CONFIG))
|
||||
phba->sli4_hba.fawwpn_flag &=
|
||||
~LPFC_FAWWPN_FABRIC;
|
||||
lpfc_printf_log(phba, KERN_INFO,
|
||||
LOG_SLI | LOG_DISCOVERY | LOG_ELS,
|
||||
"2701 FA-PWWN change WWPN from %llx to "
|
||||
|
|
@ -2682,11 +2685,6 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
|
|||
case PCI_DEVICE_ID_SAT_S:
|
||||
m = (typeof(m)){"LPe12000-S", "PCIe", "Fibre Channel Adapter"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_HORNET:
|
||||
m = (typeof(m)){"LP21000", "PCIe",
|
||||
"Obsolete, Unsupported FCoE Adapter"};
|
||||
GE = 1;
|
||||
break;
|
||||
case PCI_DEVICE_ID_PROTEUS_VF:
|
||||
m = (typeof(m)){"LPev12000", "PCIe IOV",
|
||||
"Obsolete, Unsupported Fibre Channel Adapter"};
|
||||
|
|
@ -7692,7 +7690,6 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
|
|||
INIT_LIST_HEAD(&phba->port_list);
|
||||
|
||||
INIT_LIST_HEAD(&phba->work_list);
|
||||
init_waitqueue_head(&phba->wait_4_mlo_m_q);
|
||||
|
||||
/* Initialize the wait queue head for the kernel thread */
|
||||
init_waitqueue_head(&phba->work_waitq);
|
||||
|
|
@ -7776,13 +7773,6 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
|
|||
if (rc)
|
||||
return -ENODEV;
|
||||
|
||||
if (phba->pcidev->device == PCI_DEVICE_ID_HORNET) {
|
||||
phba->menlo_flag |= HBA_MENLO_SUPPORT;
|
||||
/* check for menlo minimum sg count */
|
||||
if (phba->cfg_sg_seg_cnt < LPFC_DEFAULT_MENLO_SG_SEG_CNT)
|
||||
phba->cfg_sg_seg_cnt = LPFC_DEFAULT_MENLO_SG_SEG_CNT;
|
||||
}
|
||||
|
||||
if (!phba->sli.sli3_ring)
|
||||
phba->sli.sli3_ring = kcalloc(LPFC_SLI3_MAX_RING,
|
||||
sizeof(struct lpfc_sli_ring),
|
||||
|
|
@ -9975,7 +9965,8 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
|
|||
"configured on\n");
|
||||
phba->sli4_hba.fawwpn_flag |= LPFC_FAWWPN_CONFIG;
|
||||
} else {
|
||||
phba->sli4_hba.fawwpn_flag = 0;
|
||||
/* Clear FW configured flag, preserve driver flag */
|
||||
phba->sli4_hba.fawwpn_flag &= ~LPFC_FAWWPN_CONFIG;
|
||||
}
|
||||
|
||||
phba->sli4_hba.conf_trunk =
|
||||
|
|
|
|||
|
|
@ -2824,6 +2824,7 @@ lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
|
|||
wcqep->word0 = 0;
|
||||
bf_set(lpfc_wcqe_c_status, wcqep, stat);
|
||||
wcqep->parameter = param;
|
||||
wcqep->total_data_placed = 0;
|
||||
wcqep->word3 = 0; /* xb is 0 */
|
||||
|
||||
/* Call release with XB=1 to queue the IO into the abort list. */
|
||||
|
|
|
|||
|
|
@ -722,7 +722,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
|
|||
struct lpfc_nvmet_tgtport *tgtp;
|
||||
struct nvmefc_tgt_fcp_req *rsp;
|
||||
struct lpfc_async_xchg_ctx *ctxp;
|
||||
uint32_t status, result, op, start_clean, logerr;
|
||||
uint32_t status, result, op, logerr;
|
||||
struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
int id;
|
||||
|
|
@ -820,9 +820,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
|
|||
/* lpfc_nvmet_xmt_fcp_release() will recycle the context */
|
||||
} else {
|
||||
ctxp->entry_cnt++;
|
||||
start_clean = offsetof(struct lpfc_iocbq, cmd_flag);
|
||||
memset(((char *)cmdwqe) + start_clean, 0,
|
||||
(sizeof(struct lpfc_iocbq) - start_clean));
|
||||
memset_startat(cmdwqe, 0, cmd_flag);
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
if (ctxp->ts_cmd_nvme) {
|
||||
ctxp->ts_isr_data = cmdwqe->isr_timestamp;
|
||||
|
|
@ -3337,46 +3335,6 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_nvmet_prep_abort_wqe - set up 'abort' work queue entry.
|
||||
* @pwqeq: Pointer to command iocb.
|
||||
* @xritag: Tag that uniqely identifies the local exchange resource.
|
||||
* @opt: Option bits -
|
||||
* bit 0 = inhibit sending abts on the link
|
||||
*
|
||||
* This function is called with hbalock held.
|
||||
**/
|
||||
static void
|
||||
lpfc_nvmet_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt)
|
||||
{
|
||||
union lpfc_wqe128 *wqe = &pwqeq->wqe;
|
||||
|
||||
/* WQEs are reused. Clear stale data and set key fields to
|
||||
* zero like ia, iaab, iaar, xri_tag, and ctxt_tag.
|
||||
*/
|
||||
memset(wqe, 0, sizeof(*wqe));
|
||||
|
||||
if (opt & INHIBIT_ABORT)
|
||||
bf_set(abort_cmd_ia, &wqe->abort_cmd, 1);
|
||||
/* Abort specified xri tag, with the mask deliberately zeroed */
|
||||
bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG);
|
||||
|
||||
bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
|
||||
|
||||
/* Abort the I/O associated with this outstanding exchange ID. */
|
||||
wqe->abort_cmd.wqe_com.abort_tag = xritag;
|
||||
|
||||
/* iotag for the wqe completion. */
|
||||
bf_set(wqe_reqtag, &wqe->abort_cmd.wqe_com, pwqeq->iotag);
|
||||
|
||||
bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1);
|
||||
bf_set(wqe_lenloc, &wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
|
||||
|
||||
bf_set(wqe_cmd_type, &wqe->abort_cmd.wqe_com, OTHER_COMMAND);
|
||||
bf_set(wqe_wqec, &wqe->abort_cmd.wqe_com, 1);
|
||||
bf_set(wqe_cqid, &wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
|
||||
struct lpfc_async_xchg_ctx *ctxp,
|
||||
|
|
@ -3386,7 +3344,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
|
|||
struct lpfc_iocbq *abts_wqeq;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
unsigned long flags;
|
||||
u8 opt;
|
||||
bool ia;
|
||||
int rc;
|
||||
|
||||
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
|
||||
|
|
@ -3426,7 +3384,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
|
|||
}
|
||||
abts_wqeq = ctxp->abort_wqeq;
|
||||
ctxp->state = LPFC_NVME_STE_ABORT;
|
||||
opt = (ctxp->flag & LPFC_NVME_ABTS_RCV) ? INHIBIT_ABORT : 0;
|
||||
ia = (ctxp->flag & LPFC_NVME_ABTS_RCV) ? true : false;
|
||||
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
|
||||
|
||||
/* Announce entry to new IO submit field. */
|
||||
|
|
@ -3472,7 +3430,9 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
|
|||
/* Ready - mark outstanding as aborted by driver. */
|
||||
abts_wqeq->cmd_flag |= LPFC_DRIVER_ABORTED;
|
||||
|
||||
lpfc_nvmet_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt);
|
||||
lpfc_sli_prep_abort_xri(phba, abts_wqeq, ctxp->wqeq->sli4_xritag,
|
||||
abts_wqeq->iotag, CLASS3,
|
||||
LPFC_WQE_CQ_ID_DEFAULT, ia, true);
|
||||
|
||||
/* ABTS WQE must go to the same WQ as the WQE to be aborted */
|
||||
abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx;
|
||||
|
|
|
|||
|
|
@ -5456,7 +5456,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
|
|||
cur_iocbq->cmd_flag |= LPFC_IO_VMID;
|
||||
}
|
||||
}
|
||||
atomic_inc(&ndlp->cmd_pending);
|
||||
|
||||
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
||||
if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
|
||||
|
|
|
|||
|
|
@ -2003,10 +2003,12 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
|
|||
|
||||
sync_buf->cmd_flag |= LPFC_IO_CMF;
|
||||
ret_val = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], sync_buf);
|
||||
if (ret_val)
|
||||
if (ret_val) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
|
||||
"6214 Cannot issue CMF_SYNC_WQE: x%x\n",
|
||||
ret_val);
|
||||
__lpfc_sli_release_iocbq(phba, sync_buf);
|
||||
}
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||
return ret_val;
|
||||
|
|
@ -5263,7 +5265,8 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
|
|||
phba->pport->stopped = 0;
|
||||
phba->link_state = LPFC_INIT_START;
|
||||
phba->hba_flag = 0;
|
||||
phba->sli4_hba.fawwpn_flag = 0;
|
||||
/* Preserve FA-PWWN expectation */
|
||||
phba->sli4_hba.fawwpn_flag &= LPFC_FAWWPN_FABRIC;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
||||
memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
|
||||
|
|
@ -6052,6 +6055,10 @@ lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba)
|
|||
/* obtain link type and link number via READ_CONFIG */
|
||||
phba->sli4_hba.lnk_info.lnk_dv = LPFC_LNK_DAT_INVAL;
|
||||
lpfc_sli4_read_config(phba);
|
||||
|
||||
if (phba->sli4_hba.fawwpn_flag & LPFC_FAWWPN_CONFIG)
|
||||
phba->sli4_hba.fawwpn_flag |= LPFC_FAWWPN_FABRIC;
|
||||
|
||||
if (phba->sli4_hba.lnk_info.lnk_dv == LPFC_LNK_DAT_VAL)
|
||||
goto retrieve_ppname;
|
||||
|
||||
|
|
@ -10216,16 +10223,6 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number,
|
|||
* can be issued if the link is not up.
|
||||
*/
|
||||
switch (piocb->iocb.ulpCommand) {
|
||||
case CMD_GEN_REQUEST64_CR:
|
||||
case CMD_GEN_REQUEST64_CX:
|
||||
if (!(phba->sli.sli_flag & LPFC_MENLO_MAINT) ||
|
||||
(piocb->iocb.un.genreq64.w5.hcsw.Rctl !=
|
||||
FC_RCTL_DD_UNSOL_CMD) ||
|
||||
(piocb->iocb.un.genreq64.w5.hcsw.Type !=
|
||||
MENLO_TRANSPORT_TYPE))
|
||||
|
||||
goto iocb_busy;
|
||||
break;
|
||||
case CMD_QUE_RING_BUF_CN:
|
||||
case CMD_QUE_RING_BUF64_CN:
|
||||
/*
|
||||
|
|
@ -10549,6 +10546,7 @@ __lpfc_sli_prep_els_req_rsp_s3(struct lpfc_iocbq *cmdiocbq,
|
|||
cmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64);
|
||||
cmd->un.genreq64.xmit_els_remoteID = did; /* DID */
|
||||
cmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
|
||||
cmd->ulpPU = PARM_NPIV_DID;
|
||||
}
|
||||
cmd->ulpBdeCount = 1;
|
||||
cmd->ulpLe = 1;
|
||||
|
|
@ -10855,7 +10853,8 @@ lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
|
|||
|
||||
static void
|
||||
__lpfc_sli_prep_abort_xri_s3(struct lpfc_iocbq *cmdiocbq, u16 ulp_context,
|
||||
u16 iotag, u8 ulp_class, u16 cqid, bool ia)
|
||||
u16 iotag, u8 ulp_class, u16 cqid, bool ia,
|
||||
bool wqec)
|
||||
{
|
||||
IOCB_t *icmd = NULL;
|
||||
|
||||
|
|
@ -10884,7 +10883,8 @@ __lpfc_sli_prep_abort_xri_s3(struct lpfc_iocbq *cmdiocbq, u16 ulp_context,
|
|||
|
||||
static void
|
||||
__lpfc_sli_prep_abort_xri_s4(struct lpfc_iocbq *cmdiocbq, u16 ulp_context,
|
||||
u16 iotag, u8 ulp_class, u16 cqid, bool ia)
|
||||
u16 iotag, u8 ulp_class, u16 cqid, bool ia,
|
||||
bool wqec)
|
||||
{
|
||||
union lpfc_wqe128 *wqe;
|
||||
|
||||
|
|
@ -10911,6 +10911,8 @@ __lpfc_sli_prep_abort_xri_s4(struct lpfc_iocbq *cmdiocbq, u16 ulp_context,
|
|||
bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1);
|
||||
|
||||
/* Word 11 */
|
||||
if (wqec)
|
||||
bf_set(wqe_wqec, &wqe->abort_cmd.wqe_com, 1);
|
||||
bf_set(wqe_cqid, &wqe->abort_cmd.wqe_com, cqid);
|
||||
bf_set(wqe_cmd_type, &wqe->abort_cmd.wqe_com, OTHER_COMMAND);
|
||||
}
|
||||
|
|
@ -10918,10 +10920,10 @@ __lpfc_sli_prep_abort_xri_s4(struct lpfc_iocbq *cmdiocbq, u16 ulp_context,
|
|||
void
|
||||
lpfc_sli_prep_abort_xri(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
|
||||
u16 ulp_context, u16 iotag, u8 ulp_class, u16 cqid,
|
||||
bool ia)
|
||||
bool ia, bool wqec)
|
||||
{
|
||||
phba->__lpfc_sli_prep_abort_xri(cmdiocbq, ulp_context, iotag, ulp_class,
|
||||
cqid, ia);
|
||||
cqid, ia, wqec);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -12199,7 +12201,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
|
||||
lpfc_sli_prep_abort_xri(phba, abtsiocbp, ulp_context, iotag,
|
||||
cmdiocb->iocb.ulpClass,
|
||||
LPFC_WQE_CQ_ID_DEFAULT, ia);
|
||||
LPFC_WQE_CQ_ID_DEFAULT, ia, false);
|
||||
|
||||
abtsiocbp->vport = vport;
|
||||
|
||||
|
|
@ -12659,7 +12661,7 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
|
|||
|
||||
lpfc_sli_prep_abort_xri(phba, abtsiocbq, ulp_context, iotag,
|
||||
iocbq->iocb.ulpClass, cqid,
|
||||
ia);
|
||||
ia, false);
|
||||
|
||||
abtsiocbq->vport = vport;
|
||||
|
||||
|
|
|
|||
|
|
@ -355,7 +355,6 @@ struct lpfc_sli {
|
|||
#define LPFC_SLI_ACTIVE 0x200 /* SLI in firmware is active */
|
||||
#define LPFC_PROCESS_LA 0x400 /* Able to process link attention */
|
||||
#define LPFC_BLOCK_MGMT_IO 0x800 /* Don't allow mgmt mbx or iocb cmds */
|
||||
#define LPFC_MENLO_MAINT 0x1000 /* need for menl fw download */
|
||||
#define LPFC_SLI_ASYNC_MBX_BLK 0x2000 /* Async mailbox is blocked */
|
||||
#define LPFC_SLI_SUPPRESS_RSP 0x4000 /* Suppress RSP feature is supported */
|
||||
#define LPFC_SLI_USE_EQDR 0x8000 /* EQ Delay Register is supported */
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "14.2.0.4"
|
||||
#define LPFC_DRIVER_VERSION "14.2.0.5"
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ MODULE_PARM_DESC(cmd_per_lun,
|
|||
* This would result in non-disk devices being skipped during driver load
|
||||
* time. These can be later added though, using /proc/scsi/scsi
|
||||
*/
|
||||
static unsigned int megaraid_fast_load = 0;
|
||||
static unsigned int megaraid_fast_load;
|
||||
module_param_named(fast_load, megaraid_fast_load, int, 0);
|
||||
MODULE_PARM_DESC(fast_load,
|
||||
"Faster loading of the driver, skips physical devices! (default=0)");
|
||||
|
|
|
|||
|
|
@ -3950,9 +3950,9 @@ process_fw_state_change_wq(struct work_struct *work)
|
|||
u32 wait;
|
||||
unsigned long flags;
|
||||
|
||||
if (atomic_read(&instance->adprecovery) != MEGASAS_ADPRESET_SM_INFAULT) {
|
||||
if (atomic_read(&instance->adprecovery) != MEGASAS_ADPRESET_SM_INFAULT) {
|
||||
dev_notice(&instance->pdev->dev, "error, recovery st %x\n",
|
||||
atomic_read(&instance->adprecovery));
|
||||
atomic_read(&instance->adprecovery));
|
||||
return ;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,12 +66,14 @@ extern atomic64_t event_counter;
|
|||
#define MPI3MR_NAME_LENGTH 32
|
||||
#define IOCNAME "%s: "
|
||||
|
||||
#define MPI3MR_MAX_SECTORS 2048
|
||||
|
||||
/* Definitions for internal SGL and Chain SGL buffers */
|
||||
#define MPI3MR_PAGE_SIZE_4K 4096
|
||||
#define MPI3MR_SG_DEPTH (MPI3MR_PAGE_SIZE_4K / sizeof(struct mpi3_sge_common))
|
||||
|
||||
/* Definitions for MAX values for shost */
|
||||
#define MPI3MR_MAX_CMDS_LUN 7
|
||||
#define MPI3MR_MAX_CMDS_LUN 128
|
||||
#define MPI3MR_MAX_CDB_LENGTH 32
|
||||
|
||||
/* Admin queue management definitions */
|
||||
|
|
@ -333,6 +335,12 @@ struct mpi3mr_ioc_facts {
|
|||
u8 sge_mod_mask;
|
||||
u8 sge_mod_value;
|
||||
u8 sge_mod_shift;
|
||||
u8 max_dev_per_tg;
|
||||
u16 max_io_throttle_group;
|
||||
u16 io_throttle_data_length;
|
||||
u16 io_throttle_low;
|
||||
u16 io_throttle_high;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -424,6 +432,31 @@ struct mpi3mr_intr_info {
|
|||
char name[MPI3MR_NAME_LENGTH];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpi3mr_throttle_group_info - Throttle group info
|
||||
*
|
||||
* @io_divert: Flag indicates io divert is on or off for the TG
|
||||
* @need_qd_reduction: Flag to indicate QD reduction is needed
|
||||
* @qd_reduction: Queue Depth reduction in units of 10%
|
||||
* @fw_qd: QueueDepth value reported by the firmware
|
||||
* @modified_qd: Modified QueueDepth value due to throttling
|
||||
* @id: Throttle Group ID.
|
||||
* @high: High limit to turn on throttling in 512 byte blocks
|
||||
* @low: Low limit to turn off throttling in 512 byte blocks
|
||||
* @pend_large_data_sz: Counter to track pending large data
|
||||
*/
|
||||
struct mpi3mr_throttle_group_info {
|
||||
u8 io_divert;
|
||||
u8 need_qd_reduction;
|
||||
u8 qd_reduction;
|
||||
u16 fw_qd;
|
||||
u16 modified_qd;
|
||||
u16 id;
|
||||
u32 high;
|
||||
u32 low;
|
||||
atomic_t pend_large_data_sz;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tgt_dev_sas_sata - SAS/SATA device specific
|
||||
* information cached from firmware given data
|
||||
|
|
@ -457,22 +490,33 @@ struct tgt_dev_pcie {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct tgt_dev_volume - virtual device specific information
|
||||
* struct tgt_dev_vd - virtual device specific information
|
||||
* cached from firmware given data
|
||||
*
|
||||
* @state: State of the VD
|
||||
* @tg_qd_reduction: Queue Depth reduction in units of 10%
|
||||
* @tg_id: VDs throttle group ID
|
||||
* @high: High limit to turn on throttling in 512 byte blocks
|
||||
* @low: Low limit to turn off throttling in 512 byte blocks
|
||||
* @tg: Pointer to throttle group info
|
||||
*/
|
||||
struct tgt_dev_volume {
|
||||
struct tgt_dev_vd {
|
||||
u8 state;
|
||||
u8 tg_qd_reduction;
|
||||
u16 tg_id;
|
||||
u32 tg_high;
|
||||
u32 tg_low;
|
||||
struct mpi3mr_throttle_group_info *tg;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* union _form_spec_inf - union of device specific information
|
||||
*/
|
||||
union _form_spec_inf {
|
||||
struct tgt_dev_sas_sata sas_sata_inf;
|
||||
struct tgt_dev_pcie pcie_inf;
|
||||
struct tgt_dev_volume vol_inf;
|
||||
struct tgt_dev_vd vd_inf;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -490,6 +534,7 @@ union _form_spec_inf {
|
|||
* @dev_type: SAS/SATA/PCIE device type
|
||||
* @is_hidden: Should be exposed to upper layers or not
|
||||
* @host_exposed: Already exposed to host or not
|
||||
* @io_throttle_enabled: I/O throttling needed or not
|
||||
* @q_depth: Device specific Queue Depth
|
||||
* @wwid: World wide ID
|
||||
* @dev_spec: Device type specific information
|
||||
|
|
@ -506,6 +551,7 @@ struct mpi3mr_tgt_dev {
|
|||
u8 dev_type;
|
||||
u8 is_hidden;
|
||||
u8 host_exposed;
|
||||
u8 io_throttle_enabled;
|
||||
u16 q_depth;
|
||||
u64 wwid;
|
||||
union _form_spec_inf dev_spec;
|
||||
|
|
@ -557,6 +603,9 @@ static inline void mpi3mr_tgtdev_put(struct mpi3mr_tgt_dev *s)
|
|||
* @dev_removed: Device removed in the Firmware
|
||||
* @dev_removedelay: Device is waiting to be removed in FW
|
||||
* @dev_type: Device type
|
||||
* @io_throttle_enabled: I/O throttling needed or not
|
||||
* @io_divert: Flag indicates io divert is on or off for the dev
|
||||
* @throttle_group: Pointer to throttle group info
|
||||
* @tgt_dev: Internal target device pointer
|
||||
* @pend_count: Counter to track pending I/Os during error
|
||||
* handling
|
||||
|
|
@ -570,6 +619,9 @@ struct mpi3mr_stgt_priv_data {
|
|||
u8 dev_removed;
|
||||
u8 dev_removedelay;
|
||||
u8 dev_type;
|
||||
u8 io_throttle_enabled;
|
||||
u8 io_divert;
|
||||
struct mpi3mr_throttle_group_info *throttle_group;
|
||||
struct mpi3mr_tgt_dev *tgt_dev;
|
||||
u32 pend_count;
|
||||
};
|
||||
|
|
@ -796,6 +848,12 @@ struct scmd_priv {
|
|||
* @logdata_buf: Circular buffer to store log data entries
|
||||
* @logdata_buf_idx: Index of entry in buffer to store
|
||||
* @logdata_entry_sz: log data entry size
|
||||
* @pend_large_data_sz: Counter to track pending large data
|
||||
* @io_throttle_data_length: I/O size to track in 512b blocks
|
||||
* @io_throttle_high: I/O size to start throttle in 512b blocks
|
||||
* @io_throttle_low: I/O size to stop throttle in 512b blocks
|
||||
* @num_io_throttle_group: Maximum number of throttle groups
|
||||
* @throttle_groups: Pointer to throttle group info structures
|
||||
*/
|
||||
struct mpi3mr_ioc {
|
||||
struct list_head list;
|
||||
|
|
@ -960,6 +1018,13 @@ struct mpi3mr_ioc {
|
|||
u8 *logdata_buf;
|
||||
u16 logdata_buf_idx;
|
||||
u16 logdata_entry_sz;
|
||||
|
||||
atomic_t pend_large_data_sz;
|
||||
u32 io_throttle_data_length;
|
||||
u32 io_throttle_high;
|
||||
u32 io_throttle_low;
|
||||
u16 num_io_throttle_group;
|
||||
struct mpi3mr_throttle_group_info *throttle_groups;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2785,6 +2785,27 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
|
|||
mrioc->facts.shutdown_timeout =
|
||||
le16_to_cpu(facts_data->shutdown_timeout);
|
||||
|
||||
mrioc->facts.max_dev_per_tg =
|
||||
facts_data->max_devices_per_throttle_group;
|
||||
mrioc->facts.io_throttle_data_length =
|
||||
le16_to_cpu(facts_data->io_throttle_data_length);
|
||||
mrioc->facts.max_io_throttle_group =
|
||||
le16_to_cpu(facts_data->max_io_throttle_group);
|
||||
mrioc->facts.io_throttle_low = le16_to_cpu(facts_data->io_throttle_low);
|
||||
mrioc->facts.io_throttle_high =
|
||||
le16_to_cpu(facts_data->io_throttle_high);
|
||||
|
||||
/* Store in 512b block count */
|
||||
if (mrioc->facts.io_throttle_data_length)
|
||||
mrioc->io_throttle_data_length =
|
||||
(mrioc->facts.io_throttle_data_length * 2 * 4);
|
||||
else
|
||||
/* set the length to 1MB + 1K to disable throttle */
|
||||
mrioc->io_throttle_data_length = MPI3MR_MAX_SECTORS + 2;
|
||||
|
||||
mrioc->io_throttle_high = (mrioc->facts.io_throttle_high * 2 * 1024);
|
||||
mrioc->io_throttle_low = (mrioc->facts.io_throttle_low * 2 * 1024);
|
||||
|
||||
ioc_info(mrioc, "ioc_num(%d), maxopQ(%d), maxopRepQ(%d), maxdh(%d),",
|
||||
mrioc->facts.ioc_num, mrioc->facts.max_op_req_q,
|
||||
mrioc->facts.max_op_reply_q, mrioc->facts.max_devhandle);
|
||||
|
|
@ -2798,6 +2819,13 @@ static void mpi3mr_process_factsdata(struct mpi3mr_ioc *mrioc,
|
|||
ioc_info(mrioc, "DMA mask %d InitialPE status 0x%x\n",
|
||||
mrioc->facts.dma_mask, (facts_flags &
|
||||
MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK));
|
||||
ioc_info(mrioc,
|
||||
"max_dev_per_throttle_group(%d), max_throttle_groups(%d)\n",
|
||||
mrioc->facts.max_dev_per_tg, mrioc->facts.max_io_throttle_group);
|
||||
ioc_info(mrioc,
|
||||
"io_throttle_data_len(%dKiB), io_throttle_high(%dMiB), io_throttle_low(%dMiB)\n",
|
||||
mrioc->facts.io_throttle_data_length * 4,
|
||||
mrioc->facts.io_throttle_high, mrioc->facts.io_throttle_low);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3666,6 +3694,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
|||
int retval = 0;
|
||||
u8 retry = 0;
|
||||
struct mpi3_ioc_facts_data facts_data;
|
||||
u32 sz;
|
||||
|
||||
retry_init:
|
||||
retval = mpi3mr_bring_ioc_ready(mrioc);
|
||||
|
|
@ -3691,6 +3720,9 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
|||
|
||||
mrioc->max_host_ios = mrioc->facts.max_reqs - MPI3MR_INTERNAL_CMDS_RESVD;
|
||||
|
||||
mrioc->num_io_throttle_group = mrioc->facts.max_io_throttle_group;
|
||||
atomic_set(&mrioc->pend_large_data_sz, 0);
|
||||
|
||||
if (reset_devices)
|
||||
mrioc->max_host_ios = min_t(int, mrioc->max_host_ios,
|
||||
MPI3MR_HOST_IOS_KDUMP);
|
||||
|
|
@ -3760,6 +3792,15 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
|||
}
|
||||
}
|
||||
|
||||
if (!mrioc->throttle_groups && mrioc->num_io_throttle_group) {
|
||||
dprint_init(mrioc, "allocating memory for throttle groups\n");
|
||||
sz = sizeof(struct mpi3mr_throttle_group_info);
|
||||
mrioc->throttle_groups = (struct mpi3mr_throttle_group_info *)
|
||||
kcalloc(mrioc->num_io_throttle_group, sz, GFP_KERNEL);
|
||||
if (!mrioc->throttle_groups)
|
||||
goto out_failed_noretry;
|
||||
}
|
||||
|
||||
retval = mpi3mr_enable_events(mrioc);
|
||||
if (retval) {
|
||||
ioc_err(mrioc, "failed to enable events %d\n",
|
||||
|
|
@ -3981,6 +4022,7 @@ static void mpi3mr_memset_op_req_q_buffers(struct mpi3mr_ioc *mrioc, u16 qidx)
|
|||
void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
u16 i;
|
||||
struct mpi3mr_throttle_group_info *tg;
|
||||
|
||||
mrioc->change_count = 0;
|
||||
mrioc->active_poll_qcount = 0;
|
||||
|
|
@ -4029,6 +4071,22 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
|
|||
spin_lock_init(&mrioc->req_qinfo[i].q_lock);
|
||||
mpi3mr_memset_op_req_q_buffers(mrioc, i);
|
||||
}
|
||||
|
||||
atomic_set(&mrioc->pend_large_data_sz, 0);
|
||||
if (mrioc->throttle_groups) {
|
||||
tg = mrioc->throttle_groups;
|
||||
for (i = 0; i < mrioc->num_io_throttle_group; i++, tg++) {
|
||||
tg->id = 0;
|
||||
tg->fw_qd = 0;
|
||||
tg->modified_qd = 0;
|
||||
tg->io_divert = 0;
|
||||
tg->need_qd_reduction = 0;
|
||||
tg->high = 0;
|
||||
tg->low = 0;
|
||||
tg->qd_reduction = 0;
|
||||
atomic_set(&tg->pend_large_data_sz, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4663,6 +4721,15 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
|
|||
ioc_err(mrioc, "Failed to issue soft reset to the ioc\n");
|
||||
goto out;
|
||||
}
|
||||
if (mrioc->num_io_throttle_group !=
|
||||
mrioc->facts.max_io_throttle_group) {
|
||||
ioc_err(mrioc,
|
||||
"max io throttle group doesn't match old(%d), new(%d)\n",
|
||||
mrioc->num_io_throttle_group,
|
||||
mrioc->facts.max_io_throttle_group);
|
||||
retval = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mpi3mr_flush_delayed_cmd_lists(mrioc);
|
||||
mpi3mr_flush_drv_cmds(mrioc);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ MODULE_PARM_DESC(logging_level,
|
|||
static void mpi3mr_send_event_ack(struct mpi3mr_ioc *mrioc, u8 event,
|
||||
struct mpi3mr_drv_cmd *cmdparam, u32 event_ctx);
|
||||
|
||||
#define MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION (0xFFFF)
|
||||
|
||||
/**
|
||||
* mpi3mr_host_tag_for_scmd - Get host tag for a scmd
|
||||
* @mrioc: Adapter instance reference
|
||||
|
|
@ -354,6 +356,50 @@ void mpi3mr_cleanup_fwevt_list(struct mpi3mr_ioc *mrioc)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_queue_qd_reduction_event - Queue TG QD reduction event
|
||||
* @mrioc: Adapter instance reference
|
||||
* @tg: Throttle group information pointer
|
||||
*
|
||||
* Accessor to queue on synthetically generated driver event to
|
||||
* the event worker thread, the driver event will be used to
|
||||
* reduce the QD of all VDs in the TG from the worker thread.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void mpi3mr_queue_qd_reduction_event(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_throttle_group_info *tg)
|
||||
{
|
||||
struct mpi3mr_fwevt *fwevt;
|
||||
u16 sz = sizeof(struct mpi3mr_throttle_group_info *);
|
||||
|
||||
/*
|
||||
* If the QD reduction event is already queued due to throttle and if
|
||||
* the QD is not restored through device info change event
|
||||
* then dont queue further reduction events
|
||||
*/
|
||||
if (tg->fw_qd != tg->modified_qd)
|
||||
return;
|
||||
|
||||
fwevt = mpi3mr_alloc_fwevt(sz);
|
||||
if (!fwevt) {
|
||||
ioc_warn(mrioc, "failed to queue TG QD reduction event\n");
|
||||
return;
|
||||
}
|
||||
*(struct mpi3mr_throttle_group_info **)fwevt->event_data = tg;
|
||||
fwevt->mrioc = mrioc;
|
||||
fwevt->event_id = MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION;
|
||||
fwevt->send_ack = 0;
|
||||
fwevt->process_evt = 1;
|
||||
fwevt->evt_ctx = 0;
|
||||
fwevt->event_data_size = sz;
|
||||
tg->modified_qd = max_t(u16, (tg->fw_qd * tg->qd_reduction) / 10, 8);
|
||||
|
||||
dprint_event_bh(mrioc, "qd reduction event queued for tg_id(%d)\n",
|
||||
tg->id);
|
||||
mpi3mr_fwevt_add_to_list(mrioc, fwevt);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_invalidate_devhandles -Invalidate device handles
|
||||
* @mrioc: Adapter instance reference
|
||||
|
|
@ -373,6 +419,9 @@ void mpi3mr_invalidate_devhandles(struct mpi3mr_ioc *mrioc)
|
|||
if (tgtdev->starget && tgtdev->starget->hostdata) {
|
||||
tgt_priv = tgtdev->starget->hostdata;
|
||||
tgt_priv->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
|
||||
tgt_priv->io_throttle_enabled = 0;
|
||||
tgt_priv->io_divert = 0;
|
||||
tgt_priv->throttle_group = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -709,6 +758,35 @@ static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_from_tgtpriv(
|
|||
return tgtdev;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_set_io_divert_for_all_vd_in_tg -set divert for TG VDs
|
||||
* @mrioc: Adapter instance reference
|
||||
* @tg: Throttle group information pointer
|
||||
* @divert_value: 1 or 0
|
||||
*
|
||||
* Accessor to set io_divert flag for each device associated
|
||||
* with the given throttle group with the given value.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_throttle_group_info *tg, u8 divert_value)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct mpi3mr_tgt_dev *tgtdev;
|
||||
struct mpi3mr_stgt_priv_data *tgt_priv;
|
||||
|
||||
spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
|
||||
list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) {
|
||||
if (tgtdev->starget && tgtdev->starget->hostdata) {
|
||||
tgt_priv = tgtdev->starget->hostdata;
|
||||
if (tgt_priv->throttle_group == tg)
|
||||
tgt_priv->io_divert = divert_value;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_print_device_event_notice - print notice related to post processing of
|
||||
* device event after controller reset.
|
||||
|
|
@ -840,6 +918,7 @@ static int mpi3mr_change_queue_depth(struct scsi_device *sdev,
|
|||
else if (!q_depth)
|
||||
q_depth = MPI3MR_DEFAULT_SDEV_QD;
|
||||
retval = scsi_change_queue_depth(sdev, q_depth);
|
||||
sdev->max_queue_depth = sdev->queue_depth;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -926,6 +1005,7 @@ void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc)
|
|||
* @mrioc: Adapter instance reference
|
||||
* @tgtdev: Target device internal structure
|
||||
* @dev_pg0: New device page0
|
||||
* @is_added: Flag to indicate the device is just added
|
||||
*
|
||||
* Update the information from the device page0 into the driver
|
||||
* cached target device structure.
|
||||
|
|
@ -933,10 +1013,11 @@ void mpi3mr_rfresh_tgtdevs(struct mpi3mr_ioc *mrioc)
|
|||
* Return: Nothing.
|
||||
*/
|
||||
static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_tgt_dev *tgtdev, struct mpi3_device_page0 *dev_pg0)
|
||||
struct mpi3mr_tgt_dev *tgtdev, struct mpi3_device_page0 *dev_pg0,
|
||||
bool is_added)
|
||||
{
|
||||
u16 flags = 0;
|
||||
struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data;
|
||||
struct mpi3mr_stgt_priv_data *scsi_tgt_priv_data = NULL;
|
||||
u8 prot_mask = 0;
|
||||
|
||||
tgtdev->perst_id = le16_to_cpu(dev_pg0->persistent_id);
|
||||
|
|
@ -951,12 +1032,19 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
|||
flags = le16_to_cpu(dev_pg0->flags);
|
||||
tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN);
|
||||
|
||||
if (is_added == true)
|
||||
tgtdev->io_throttle_enabled =
|
||||
(flags & MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED) ? 1 : 0;
|
||||
|
||||
|
||||
if (tgtdev->starget && tgtdev->starget->hostdata) {
|
||||
scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data *)
|
||||
tgtdev->starget->hostdata;
|
||||
scsi_tgt_priv_data->perst_id = tgtdev->perst_id;
|
||||
scsi_tgt_priv_data->dev_handle = tgtdev->dev_handle;
|
||||
scsi_tgt_priv_data->dev_type = tgtdev->dev_type;
|
||||
scsi_tgt_priv_data->io_throttle_enabled =
|
||||
tgtdev->io_throttle_enabled;
|
||||
}
|
||||
|
||||
switch (dev_pg0->access_status) {
|
||||
|
|
@ -1034,10 +1122,32 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
|
|||
{
|
||||
struct mpi3_device0_vd_format *vdinf =
|
||||
&dev_pg0->device_specific.vd_format;
|
||||
struct mpi3mr_throttle_group_info *tg = NULL;
|
||||
u16 vdinf_io_throttle_group =
|
||||
le16_to_cpu(vdinf->io_throttle_group);
|
||||
|
||||
tgtdev->dev_spec.vol_inf.state = vdinf->vd_state;
|
||||
tgtdev->dev_spec.vd_inf.state = vdinf->vd_state;
|
||||
if (vdinf->vd_state == MPI3_DEVICE0_VD_STATE_OFFLINE)
|
||||
tgtdev->is_hidden = 1;
|
||||
tgtdev->dev_spec.vd_inf.tg_id = vdinf_io_throttle_group;
|
||||
tgtdev->dev_spec.vd_inf.tg_high =
|
||||
le16_to_cpu(vdinf->io_throttle_group_high) * 2048;
|
||||
tgtdev->dev_spec.vd_inf.tg_low =
|
||||
le16_to_cpu(vdinf->io_throttle_group_low) * 2048;
|
||||
if (vdinf_io_throttle_group < mrioc->num_io_throttle_group) {
|
||||
tg = mrioc->throttle_groups + vdinf_io_throttle_group;
|
||||
tg->id = vdinf_io_throttle_group;
|
||||
tg->high = tgtdev->dev_spec.vd_inf.tg_high;
|
||||
tg->low = tgtdev->dev_spec.vd_inf.tg_low;
|
||||
tg->qd_reduction =
|
||||
tgtdev->dev_spec.vd_inf.tg_qd_reduction;
|
||||
if (is_added == true)
|
||||
tg->fw_qd = tgtdev->q_depth;
|
||||
tg->modified_qd = tgtdev->q_depth;
|
||||
}
|
||||
tgtdev->dev_spec.vd_inf.tg = tg;
|
||||
if (scsi_tgt_priv_data)
|
||||
scsi_tgt_priv_data->throttle_group = tg;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -1134,7 +1244,7 @@ static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_ioc *mrioc,
|
|||
tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, dev_handle);
|
||||
if (!tgtdev)
|
||||
goto out;
|
||||
mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0);
|
||||
mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0, false);
|
||||
if (!tgtdev->is_hidden && !tgtdev->host_exposed)
|
||||
mpi3mr_report_tgtdev_to_host(mrioc, perst_id);
|
||||
if (tgtdev->is_hidden && tgtdev->host_exposed)
|
||||
|
|
@ -1427,6 +1537,60 @@ static void mpi3mr_logdata_evt_bh(struct mpi3mr_ioc *mrioc,
|
|||
fwevt->event_data_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_update_sdev_qd - Update SCSI device queue depath
|
||||
* @sdev: SCSI device reference
|
||||
* @data: Queue depth reference
|
||||
*
|
||||
* This is an iterator function called for each SCSI device in a
|
||||
* target to update the QD of each SCSI device.
|
||||
*
|
||||
* Return: Nothing.
|
||||
*/
|
||||
static void mpi3mr_update_sdev_qd(struct scsi_device *sdev, void *data)
|
||||
{
|
||||
u16 *q_depth = (u16 *)data;
|
||||
|
||||
scsi_change_queue_depth(sdev, (int)*q_depth);
|
||||
sdev->max_queue_depth = sdev->queue_depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_set_qd_for_all_vd_in_tg -set QD for TG VDs
|
||||
* @mrioc: Adapter instance reference
|
||||
* @tg: Throttle group information pointer
|
||||
*
|
||||
* Accessor to reduce QD for each device associated with the
|
||||
* given throttle group.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void mpi3mr_set_qd_for_all_vd_in_tg(struct mpi3mr_ioc *mrioc,
|
||||
struct mpi3mr_throttle_group_info *tg)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct mpi3mr_tgt_dev *tgtdev;
|
||||
struct mpi3mr_stgt_priv_data *tgt_priv;
|
||||
|
||||
|
||||
spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
|
||||
list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) {
|
||||
if (tgtdev->starget && tgtdev->starget->hostdata) {
|
||||
tgt_priv = tgtdev->starget->hostdata;
|
||||
if (tgt_priv->throttle_group == tg) {
|
||||
dprint_event_bh(mrioc,
|
||||
"updating qd due to throttling for persist_id(%d) original_qd(%d), reduced_qd (%d)\n",
|
||||
tgt_priv->perst_id, tgtdev->q_depth,
|
||||
tg->modified_qd);
|
||||
starget_for_each_device(tgtdev->starget,
|
||||
(void *)&tg->modified_qd,
|
||||
mpi3mr_update_sdev_qd);
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_fwevt_bh - Firmware event bottomhalf handler
|
||||
* @mrioc: Adapter instance reference
|
||||
|
|
@ -1484,6 +1648,20 @@ static void mpi3mr_fwevt_bh(struct mpi3mr_ioc *mrioc,
|
|||
mpi3mr_logdata_evt_bh(mrioc, fwevt);
|
||||
break;
|
||||
}
|
||||
case MPI3MR_DRIVER_EVENT_TG_QD_REDUCTION:
|
||||
{
|
||||
struct mpi3mr_throttle_group_info *tg;
|
||||
|
||||
tg = *(struct mpi3mr_throttle_group_info **)fwevt->event_data;
|
||||
dprint_event_bh(mrioc,
|
||||
"qd reduction event processed for tg_id(%d) reduction_needed(%d)\n",
|
||||
tg->id, tg->need_qd_reduction);
|
||||
if (tg->need_qd_reduction) {
|
||||
mpi3mr_set_qd_for_all_vd_in_tg(mrioc, tg);
|
||||
tg->need_qd_reduction = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1540,13 +1718,13 @@ static int mpi3mr_create_tgtdev(struct mpi3mr_ioc *mrioc,
|
|||
perst_id = le16_to_cpu(dev_pg0->persistent_id);
|
||||
tgtdev = mpi3mr_get_tgtdev_by_perst_id(mrioc, perst_id);
|
||||
if (tgtdev) {
|
||||
mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0);
|
||||
mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0, true);
|
||||
mpi3mr_tgtdev_put(tgtdev);
|
||||
} else {
|
||||
tgtdev = mpi3mr_alloc_tgtdev();
|
||||
if (!tgtdev)
|
||||
return -ENOMEM;
|
||||
mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0);
|
||||
mpi3mr_update_tgtdev(mrioc, tgtdev, dev_pg0, true);
|
||||
mpi3mr_tgtdev_add_to_list(mrioc, tgtdev);
|
||||
}
|
||||
|
||||
|
|
@ -2558,6 +2736,11 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
|||
u32 xfer_count = 0, sense_count = 0, resp_data = 0;
|
||||
u16 dev_handle = 0xFFFF;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
struct mpi3mr_stgt_priv_data *stgt_priv_data = NULL;
|
||||
struct mpi3mr_sdev_priv_data *sdev_priv_data = NULL;
|
||||
u32 ioc_pend_data_len = 0, tg_pend_data_len = 0, data_len_blks = 0;
|
||||
struct mpi3mr_throttle_group_info *tg = NULL;
|
||||
u8 throttle_enabled_dev = 0;
|
||||
|
||||
*reply_dma = 0;
|
||||
reply_desc_type = le16_to_cpu(reply_desc->reply_flags) &
|
||||
|
|
@ -2614,6 +2797,51 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_ioc *mrioc,
|
|||
goto out;
|
||||
}
|
||||
priv = scsi_cmd_priv(scmd);
|
||||
|
||||
data_len_blks = scsi_bufflen(scmd) >> 9;
|
||||
sdev_priv_data = scmd->device->hostdata;
|
||||
if (sdev_priv_data) {
|
||||
stgt_priv_data = sdev_priv_data->tgt_priv_data;
|
||||
if (stgt_priv_data) {
|
||||
tg = stgt_priv_data->throttle_group;
|
||||
throttle_enabled_dev =
|
||||
stgt_priv_data->io_throttle_enabled;
|
||||
}
|
||||
}
|
||||
if (unlikely((data_len_blks >= mrioc->io_throttle_data_length) &&
|
||||
throttle_enabled_dev)) {
|
||||
ioc_pend_data_len = atomic_sub_return(data_len_blks,
|
||||
&mrioc->pend_large_data_sz);
|
||||
if (tg) {
|
||||
tg_pend_data_len = atomic_sub_return(data_len_blks,
|
||||
&tg->pend_large_data_sz);
|
||||
if (tg->io_divert && ((ioc_pend_data_len <=
|
||||
mrioc->io_throttle_low) &&
|
||||
(tg_pend_data_len <= tg->low))) {
|
||||
tg->io_divert = 0;
|
||||
mpi3mr_set_io_divert_for_all_vd_in_tg(
|
||||
mrioc, tg, 0);
|
||||
}
|
||||
} else {
|
||||
if (ioc_pend_data_len <= mrioc->io_throttle_low)
|
||||
stgt_priv_data->io_divert = 0;
|
||||
}
|
||||
} else if (unlikely((stgt_priv_data && stgt_priv_data->io_divert))) {
|
||||
ioc_pend_data_len = atomic_read(&mrioc->pend_large_data_sz);
|
||||
if (!tg) {
|
||||
if (ioc_pend_data_len <= mrioc->io_throttle_low)
|
||||
stgt_priv_data->io_divert = 0;
|
||||
|
||||
} else if (ioc_pend_data_len <= mrioc->io_throttle_low) {
|
||||
tg_pend_data_len = atomic_read(&tg->pend_large_data_sz);
|
||||
if (tg->io_divert && (tg_pend_data_len <= tg->low)) {
|
||||
tg->io_divert = 0;
|
||||
mpi3mr_set_io_divert_for_all_vd_in_tg(
|
||||
mrioc, tg, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success_desc) {
|
||||
scmd->result = DID_OK << 16;
|
||||
goto out_success;
|
||||
|
|
@ -3834,6 +4062,11 @@ static int mpi3mr_target_alloc(struct scsi_target *starget)
|
|||
tgt_dev->starget = starget;
|
||||
atomic_set(&scsi_tgt_priv_data->block_io, 0);
|
||||
retval = 0;
|
||||
scsi_tgt_priv_data->io_throttle_enabled =
|
||||
tgt_dev->io_throttle_enabled;
|
||||
if (tgt_dev->dev_type == MPI3_DEVICE_DEVFORM_VD)
|
||||
scsi_tgt_priv_data->throttle_group =
|
||||
tgt_dev->dev_spec.vd_inf.tg;
|
||||
} else
|
||||
retval = -ENXIO;
|
||||
spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
|
||||
|
|
@ -3989,10 +4222,13 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
|
|||
int retval = 0;
|
||||
u16 dev_handle;
|
||||
u16 host_tag;
|
||||
u32 scsiio_flags = 0;
|
||||
u32 scsiio_flags = 0, data_len_blks = 0;
|
||||
struct request *rq = scsi_cmd_to_rq(scmd);
|
||||
int iprio_class;
|
||||
u8 is_pcie_dev = 0;
|
||||
u32 tracked_io_sz = 0;
|
||||
u32 ioc_pend_data_len = 0, tg_pend_data_len = 0;
|
||||
struct mpi3mr_throttle_group_info *tg = NULL;
|
||||
|
||||
if (mrioc->unrecoverable) {
|
||||
scmd->result = DID_ERROR << 16;
|
||||
|
|
@ -4096,11 +4332,50 @@ static int mpi3mr_qcmd(struct Scsi_Host *shost,
|
|||
goto out;
|
||||
}
|
||||
op_req_q = &mrioc->req_qinfo[scmd_priv_data->req_q_idx];
|
||||
data_len_blks = scsi_bufflen(scmd) >> 9;
|
||||
if ((data_len_blks >= mrioc->io_throttle_data_length) &&
|
||||
stgt_priv_data->io_throttle_enabled) {
|
||||
tracked_io_sz = data_len_blks;
|
||||
tg = stgt_priv_data->throttle_group;
|
||||
if (tg) {
|
||||
ioc_pend_data_len = atomic_add_return(data_len_blks,
|
||||
&mrioc->pend_large_data_sz);
|
||||
tg_pend_data_len = atomic_add_return(data_len_blks,
|
||||
&tg->pend_large_data_sz);
|
||||
if (!tg->io_divert && ((ioc_pend_data_len >=
|
||||
mrioc->io_throttle_high) ||
|
||||
(tg_pend_data_len >= tg->high))) {
|
||||
tg->io_divert = 1;
|
||||
tg->need_qd_reduction = 1;
|
||||
mpi3mr_set_io_divert_for_all_vd_in_tg(mrioc,
|
||||
tg, 1);
|
||||
mpi3mr_queue_qd_reduction_event(mrioc, tg);
|
||||
}
|
||||
} else {
|
||||
ioc_pend_data_len = atomic_add_return(data_len_blks,
|
||||
&mrioc->pend_large_data_sz);
|
||||
if (ioc_pend_data_len >= mrioc->io_throttle_high)
|
||||
stgt_priv_data->io_divert = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (stgt_priv_data->io_divert) {
|
||||
scsiio_req->msg_flags |=
|
||||
MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE;
|
||||
scsiio_flags |= MPI3_SCSIIO_FLAGS_DIVERT_REASON_IO_THROTTLING;
|
||||
}
|
||||
scsiio_req->flags = cpu_to_le32(scsiio_flags);
|
||||
|
||||
if (mpi3mr_op_request_post(mrioc, op_req_q,
|
||||
scmd_priv_data->mpi3mr_scsiio_req)) {
|
||||
mpi3mr_clear_scmd_priv(mrioc, scmd);
|
||||
retval = SCSI_MLQUEUE_HOST_BUSY;
|
||||
if (tracked_io_sz) {
|
||||
atomic_sub(tracked_io_sz, &mrioc->pend_large_data_sz);
|
||||
if (tg)
|
||||
atomic_sub(tracked_io_sz,
|
||||
&tg->pend_large_data_sz);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -4313,6 +4588,8 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
shost->max_channel = 0;
|
||||
shost->max_id = 0xFFFFFFFF;
|
||||
|
||||
shost->host_tagset = 1;
|
||||
|
||||
if (prot_mask >= 0)
|
||||
scsi_host_set_prot(shost, prot_mask);
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -873,7 +873,7 @@ mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc)
|
|||
* @fault_code: fault code
|
||||
*/
|
||||
void
|
||||
mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code)
|
||||
mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc, u16 fault_code)
|
||||
{
|
||||
ioc_err(ioc, "fault_state(0x%04x)!\n", fault_code);
|
||||
}
|
||||
|
|
@ -1057,7 +1057,7 @@ _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
|
|||
desc = "config no defaults";
|
||||
break;
|
||||
case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
|
||||
desc = "config cant commit";
|
||||
desc = "config can't commit";
|
||||
break;
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -1321,7 +1321,7 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
|
|||
* @log_info: log info
|
||||
*/
|
||||
static void
|
||||
_base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info)
|
||||
_base_sas_log_info(struct MPT3SAS_ADAPTER *ioc, u32 log_info)
|
||||
{
|
||||
union loginfo_type {
|
||||
u32 loginfo;
|
||||
|
|
@ -1393,7 +1393,7 @@ _base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
|
|||
|
||||
if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
|
||||
(ioc->logging_level & MPT_DEBUG_REPLY)) {
|
||||
_base_sas_ioc_info(ioc , mpi_reply,
|
||||
_base_sas_ioc_info(ioc, mpi_reply,
|
||||
mpt3sas_base_get_msg_frame(ioc, smid));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5294,7 +5294,7 @@ _scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
|
|||
}
|
||||
|
||||
/**
|
||||
* _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
|
||||
* _scsih_scsi_ioc_info - translated non-successful SCSI_IO request
|
||||
* @ioc: per adapter object
|
||||
* @scmd: pointer to scsi command object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
|
|
@ -12410,7 +12410,6 @@ scsih_suspend(struct device *dev)
|
|||
return rc;
|
||||
|
||||
mpt3sas_base_stop_watchdog(ioc);
|
||||
flush_scheduled_work();
|
||||
scsi_block_requests(shost);
|
||||
_scsih_nvme_shutdown(ioc);
|
||||
ioc_info(ioc, "pdev=0x%p, slot=%s, entering operating state\n",
|
||||
|
|
|
|||
|
|
@ -699,6 +699,10 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void pm8001_chip_post_init(struct pm8001_hba_info *pm8001_ha)
|
||||
{
|
||||
}
|
||||
|
||||
static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)
|
||||
{
|
||||
u32 max_wait_count;
|
||||
|
|
@ -4934,6 +4938,7 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
|
|||
const struct pm8001_dispatch pm8001_8001_dispatch = {
|
||||
.name = "pmc8001",
|
||||
.chip_init = pm8001_chip_init,
|
||||
.chip_post_init = pm8001_chip_post_init,
|
||||
.chip_soft_rst = pm8001_chip_soft_rst,
|
||||
.chip_rst = pm8001_hw_chip_rst,
|
||||
.chip_iounmap = pm8001_chip_iounmap,
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ MODULE_PARM_DESC(link_rate, "Enable link rate.\n"
|
|||
" 8: Link rate 12.0G\n");
|
||||
|
||||
static struct scsi_transport_template *pm8001_stt;
|
||||
static int pm8001_init_ccb_tag(struct pm8001_hba_info *, struct Scsi_Host *, struct pci_dev *);
|
||||
static int pm8001_init_ccb_tag(struct pm8001_hba_info *);
|
||||
|
||||
/*
|
||||
* chip info structure to identify chip key functionality as
|
||||
|
|
@ -81,6 +81,18 @@ LIST_HEAD(hba_list);
|
|||
|
||||
struct workqueue_struct *pm8001_wq;
|
||||
|
||||
static int pm8001_map_queues(struct Scsi_Host *shost)
|
||||
{
|
||||
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
|
||||
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
|
||||
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
|
||||
|
||||
if (pm8001_ha->number_of_intr > 1)
|
||||
blk_mq_pci_map_queues(qmap, pm8001_ha->pdev, 1);
|
||||
|
||||
return blk_mq_map_queues(qmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* The main structure which LLDD must register for scsi core.
|
||||
*/
|
||||
|
|
@ -109,6 +121,8 @@ static struct scsi_host_template pm8001_sht = {
|
|||
#endif
|
||||
.shost_groups = pm8001_host_groups,
|
||||
.track_queue_depth = 1,
|
||||
.cmd_per_lun = 32,
|
||||
.map_queues = pm8001_map_queues,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -607,12 +621,8 @@ static int pm8001_prep_sas_ha_init(struct Scsi_Host *shost,
|
|||
|
||||
shost->transportt = pm8001_stt;
|
||||
shost->max_id = PM8001_MAX_DEVICES;
|
||||
shost->max_lun = 8;
|
||||
shost->max_channel = 0;
|
||||
shost->unique_id = pm8001_id;
|
||||
shost->max_cmd_len = 16;
|
||||
shost->can_queue = PM8001_CAN_QUEUE;
|
||||
shost->cmd_per_lun = 32;
|
||||
return 0;
|
||||
exit_free1:
|
||||
kfree(arr_port);
|
||||
|
|
@ -933,31 +943,35 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
|
|||
*/
|
||||
static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
|
||||
{
|
||||
u32 number_of_intr;
|
||||
int rc, cpu_online_count;
|
||||
unsigned int allocated_irq_vectors;
|
||||
int rc;
|
||||
|
||||
/* SPCv controllers supports 64 msi-x */
|
||||
if (pm8001_ha->chip_id == chip_8001) {
|
||||
number_of_intr = 1;
|
||||
rc = pci_alloc_irq_vectors(pm8001_ha->pdev, 1, 1,
|
||||
PCI_IRQ_MSIX);
|
||||
} else {
|
||||
number_of_intr = PM8001_MAX_MSIX_VEC;
|
||||
/*
|
||||
* Queue index #0 is used always for housekeeping, so don't
|
||||
* include in the affinity spreading.
|
||||
*/
|
||||
struct irq_affinity desc = {
|
||||
.pre_vectors = 1,
|
||||
};
|
||||
rc = pci_alloc_irq_vectors_affinity(
|
||||
pm8001_ha->pdev, 2, PM8001_MAX_MSIX_VEC,
|
||||
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, &desc);
|
||||
}
|
||||
|
||||
cpu_online_count = num_online_cpus();
|
||||
number_of_intr = min_t(int, cpu_online_count, number_of_intr);
|
||||
rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
|
||||
number_of_intr, PCI_IRQ_MSIX);
|
||||
allocated_irq_vectors = rc;
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Assigns the number of interrupts */
|
||||
number_of_intr = min_t(int, allocated_irq_vectors, number_of_intr);
|
||||
pm8001_ha->number_of_intr = number_of_intr;
|
||||
pm8001_ha->number_of_intr = allocated_irq_vectors;
|
||||
|
||||
/* Maximum queue number updating in HBA structure */
|
||||
pm8001_ha->max_q_num = number_of_intr;
|
||||
pm8001_ha->max_q_num = allocated_irq_vectors;
|
||||
|
||||
pm8001_dbg(pm8001_ha, INIT,
|
||||
"pci_alloc_irq_vectors request ret:%d no of intr %d\n",
|
||||
|
|
@ -1124,10 +1138,23 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
|
|||
goto err_out_ha_free;
|
||||
}
|
||||
|
||||
rc = pm8001_init_ccb_tag(pm8001_ha, shost, pdev);
|
||||
rc = pm8001_init_ccb_tag(pm8001_ha);
|
||||
if (rc)
|
||||
goto err_out_enable;
|
||||
|
||||
|
||||
PM8001_CHIP_DISP->chip_post_init(pm8001_ha);
|
||||
|
||||
if (pm8001_ha->number_of_intr > 1) {
|
||||
shost->nr_hw_queues = pm8001_ha->number_of_intr - 1;
|
||||
/*
|
||||
* For now, ensure we're not sent too many commands by setting
|
||||
* host_tagset. This is also required if we start using request
|
||||
* tag.
|
||||
*/
|
||||
shost->host_tagset = 1;
|
||||
}
|
||||
|
||||
rc = scsi_add_host(shost, &pdev->dev);
|
||||
if (rc)
|
||||
goto err_out_ha_free;
|
||||
|
|
@ -1177,16 +1204,14 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
|
|||
/**
|
||||
* pm8001_init_ccb_tag - allocate memory to CCB and tag.
|
||||
* @pm8001_ha: our hba card information.
|
||||
* @shost: scsi host which has been allocated outside.
|
||||
* @pdev: pci device.
|
||||
*/
|
||||
static int
|
||||
pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost,
|
||||
struct pci_dev *pdev)
|
||||
static int pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha)
|
||||
{
|
||||
int i = 0;
|
||||
struct Scsi_Host *shost = pm8001_ha->shost;
|
||||
struct device *dev = pm8001_ha->dev;
|
||||
u32 max_out_io, ccb_count;
|
||||
u32 can_queue;
|
||||
int i;
|
||||
|
||||
max_out_io = pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io;
|
||||
ccb_count = min_t(int, PM8001_MAX_CCB, max_out_io);
|
||||
|
|
@ -1209,7 +1234,7 @@ pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost,
|
|||
goto err_out_noccb;
|
||||
}
|
||||
for (i = 0; i < ccb_count; i++) {
|
||||
pm8001_ha->ccb_info[i].buf_prd = dma_alloc_coherent(&pdev->dev,
|
||||
pm8001_ha->ccb_info[i].buf_prd = dma_alloc_coherent(dev,
|
||||
sizeof(struct pm8001_prd) * PM8001_MAX_DMA_SG,
|
||||
&pm8001_ha->ccb_info[i].ccb_dma_handle,
|
||||
GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,11 @@ static int pm8001_find_tag(struct sas_task *task, u32 *tag)
|
|||
void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
|
||||
{
|
||||
void *bitmap = pm8001_ha->tags;
|
||||
clear_bit(tag, bitmap);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pm8001_ha->bitmap_lock, flags);
|
||||
__clear_bit(tag, bitmap);
|
||||
spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,9 +80,9 @@ void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag)
|
|||
*/
|
||||
int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
|
||||
{
|
||||
unsigned int tag;
|
||||
void *bitmap = pm8001_ha->tags;
|
||||
unsigned long flags;
|
||||
unsigned int tag;
|
||||
|
||||
spin_lock_irqsave(&pm8001_ha->bitmap_lock, flags);
|
||||
tag = find_first_zero_bit(bitmap, pm8001_ha->tags_num);
|
||||
|
|
@ -86,7 +90,7 @@ int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
|
|||
spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
|
||||
return -SAS_QUEUE_FULL;
|
||||
}
|
||||
set_bit(tag, bitmap);
|
||||
__set_bit(tag, bitmap);
|
||||
spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
|
||||
*tag_out = tag;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@
|
|||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/sas_ata.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/blk-mq.h>
|
||||
#include <linux/blk-mq-pci.h>
|
||||
#include "pm8001_defs.h"
|
||||
|
||||
#define DRV_NAME "pm80xx"
|
||||
|
|
@ -172,6 +174,7 @@ struct forensic_data {
|
|||
struct pm8001_dispatch {
|
||||
char *name;
|
||||
int (*chip_init)(struct pm8001_hba_info *pm8001_ha);
|
||||
void (*chip_post_init)(struct pm8001_hba_info *pm8001_ha);
|
||||
int (*chip_soft_rst)(struct pm8001_hba_info *pm8001_ha);
|
||||
void (*chip_rst)(struct pm8001_hba_info *pm8001_ha);
|
||||
int (*chip_ioremap)(struct pm8001_hba_info *pm8001_ha);
|
||||
|
|
|
|||
|
|
@ -1469,11 +1469,18 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
|
|||
} else
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pm80xx_chip_post_init(struct pm8001_hba_info *pm8001_ha)
|
||||
{
|
||||
/* send SAS protocol timer configuration page to FW */
|
||||
ret = pm80xx_set_sas_protocol_timer_config(pm8001_ha);
|
||||
pm80xx_set_sas_protocol_timer_config(pm8001_ha);
|
||||
|
||||
/* Check for encryption */
|
||||
if (pm8001_ha->chip->encrypt) {
|
||||
int ret;
|
||||
|
||||
pm8001_dbg(pm8001_ha, INIT, "Checking for encryption\n");
|
||||
ret = pm80xx_get_encrypt_info(pm8001_ha);
|
||||
if (ret == -1) {
|
||||
|
|
@ -1485,7 +1492,6 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
|
|||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)
|
||||
|
|
@ -4349,6 +4355,29 @@ static int check_enc_sat_cmd(struct sas_task *task)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u32 pm80xx_chip_get_q_index(struct sas_task *task)
|
||||
{
|
||||
struct scsi_cmnd *scmd = NULL;
|
||||
u32 blk_tag;
|
||||
|
||||
if (task->uldd_task) {
|
||||
struct ata_queued_cmd *qc;
|
||||
|
||||
if (dev_is_sata(task->dev)) {
|
||||
qc = task->uldd_task;
|
||||
scmd = qc->scsicmd;
|
||||
} else {
|
||||
scmd = task->uldd_task;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scmd)
|
||||
return 0;
|
||||
|
||||
blk_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
|
||||
return blk_mq_unique_tag_to_hwq(blk_tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* pm80xx_chip_ssp_io_req - send an SSP task to FW
|
||||
* @pm8001_ha: our hba card information.
|
||||
|
|
@ -4364,7 +4393,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
|
|||
u32 tag = ccb->ccb_tag;
|
||||
u64 phys_addr, end_addr;
|
||||
u32 end_addr_high, end_addr_low;
|
||||
u32 q_index, cpu_id;
|
||||
u32 q_index;
|
||||
u32 opc = OPC_INB_SSPINIIOSTART;
|
||||
|
||||
memset(&ssp_cmd, 0, sizeof(ssp_cmd));
|
||||
|
|
@ -4385,8 +4414,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
|
|||
ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
|
||||
memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
|
||||
task->ssp_task.cmd->cmd_len);
|
||||
cpu_id = smp_processor_id();
|
||||
q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
|
||||
q_index = pm80xx_chip_get_q_index(task);
|
||||
|
||||
/* Check if encryption is set */
|
||||
if (pm8001_ha->chip->encrypt &&
|
||||
|
|
@ -4515,8 +4543,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
|
|||
struct domain_device *dev = task->dev;
|
||||
struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;
|
||||
struct ata_queued_cmd *qc = task->uldd_task;
|
||||
u32 tag = ccb->ccb_tag;
|
||||
u32 q_index, cpu_id;
|
||||
u32 tag = ccb->ccb_tag, q_index;
|
||||
struct sata_start_req sata_cmd;
|
||||
u32 hdr_tag, ncg_tag = 0;
|
||||
u64 phys_addr, end_addr;
|
||||
|
|
@ -4526,8 +4553,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
|
|||
unsigned long flags;
|
||||
u32 opc = OPC_INB_SATA_HOST_OPSTART;
|
||||
memset(&sata_cmd, 0, sizeof(sata_cmd));
|
||||
cpu_id = smp_processor_id();
|
||||
q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
|
||||
|
||||
q_index = pm80xx_chip_get_q_index(task);
|
||||
|
||||
if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
|
||||
ATAP = 0x04; /* no data*/
|
||||
|
|
@ -5011,6 +5038,7 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
|
|||
const struct pm8001_dispatch pm8001_80xx_dispatch = {
|
||||
.name = "pmc80xx",
|
||||
.chip_init = pm80xx_chip_init,
|
||||
.chip_post_init = pm80xx_chip_post_init,
|
||||
.chip_soft_rst = pm80xx_chip_soft_rst,
|
||||
.chip_rst = pm80xx_hw_chip_rst,
|
||||
.chip_iounmap = pm8001_chip_iounmap,
|
||||
|
|
|
|||
|
|
@ -2414,9 +2414,12 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
|
|||
int rval;
|
||||
u16 retry = 10;
|
||||
|
||||
if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) {
|
||||
iscsi_host_remove(qedi->shost);
|
||||
if (mode == QEDI_MODE_NORMAL)
|
||||
iscsi_host_remove(qedi->shost, false);
|
||||
else if (mode == QEDI_MODE_SHUTDOWN)
|
||||
iscsi_host_remove(qedi->shost, true);
|
||||
|
||||
if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) {
|
||||
if (qedi->tmf_thread) {
|
||||
destroy_workqueue(qedi->tmf_thread);
|
||||
qedi->tmf_thread = NULL;
|
||||
|
|
@ -2491,7 +2494,7 @@ static void qedi_board_disable_work(struct work_struct *work)
|
|||
if (test_and_set_bit(QEDI_IN_SHUTDOWN, &qedi->flags))
|
||||
return;
|
||||
|
||||
__qedi_remove(qedi->pdev, QEDI_MODE_SHUTDOWN);
|
||||
__qedi_remove(qedi->pdev, QEDI_MODE_NORMAL);
|
||||
}
|
||||
|
||||
static void qedi_shutdown(struct pci_dev *pdev)
|
||||
|
|
@ -2791,7 +2794,7 @@ static int __qedi_probe(struct pci_dev *pdev, int mode)
|
|||
#ifdef CONFIG_DEBUG_FS
|
||||
qedi_dbg_host_exit(&qedi->dbg_ctx);
|
||||
#endif
|
||||
iscsi_host_remove(qedi->shost);
|
||||
iscsi_host_remove(qedi->shost, false);
|
||||
stop_iscsi_func:
|
||||
qedi_ops->stop(qedi->cdev);
|
||||
stop_slowpath:
|
||||
|
|
|
|||
|
|
@ -2476,7 +2476,6 @@ static DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show,
|
|||
qla2x00_port_speed_store);
|
||||
static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL);
|
||||
static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL);
|
||||
static DEVICE_ATTR_RO(edif_doorbell);
|
||||
|
||||
static struct attribute *qla2x00_host_attrs[] = {
|
||||
&dev_attr_driver_version.attr,
|
||||
|
|
@ -2521,7 +2520,6 @@ static struct attribute *qla2x00_host_attrs[] = {
|
|||
&dev_attr_port_no.attr,
|
||||
&dev_attr_fw_attr.attr,
|
||||
&dev_attr_dport_diagnostics.attr,
|
||||
&dev_attr_edif_doorbell.attr,
|
||||
&dev_attr_mpi_pause.attr,
|
||||
&dev_attr_qlini_mode.attr,
|
||||
&dev_attr_ql2xiniexchg.attr,
|
||||
|
|
@ -2716,17 +2714,27 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
|
|||
if (!fcport)
|
||||
return;
|
||||
|
||||
/* Now that the rport has been deleted, set the fcport state to
|
||||
FCS_DEVICE_DEAD */
|
||||
qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD);
|
||||
ql_dbg(ql_dbg_async, fcport->vha, 0x5101,
|
||||
DBG_FCPORT_PRFMT(fcport, "dev_loss_tmo expiry, rport_state=%d",
|
||||
rport->port_state));
|
||||
|
||||
/*
|
||||
* Now that the rport has been deleted, set the fcport state to
|
||||
* FCS_DEVICE_DEAD, if the fcport is still lost.
|
||||
*/
|
||||
if (fcport->scan_state != QLA_FCPORT_FOUND)
|
||||
qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD);
|
||||
|
||||
/*
|
||||
* Transport has effectively 'deleted' the rport, clear
|
||||
* all local references.
|
||||
*/
|
||||
spin_lock_irqsave(host->host_lock, flags);
|
||||
fcport->rport = fcport->drport = NULL;
|
||||
*((fc_port_t **)rport->dd_data) = NULL;
|
||||
/* Confirm port has not reappeared before clearing pointers. */
|
||||
if (rport->port_state != FC_PORTSTATE_ONLINE) {
|
||||
fcport->rport = fcport->drport = NULL;
|
||||
*((fc_port_t **)rport->dd_data) = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(host->host_lock, flags);
|
||||
|
||||
if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
|
||||
|
|
@ -2759,9 +2767,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
|
|||
/*
|
||||
* At this point all fcport's software-states are cleared. Perform any
|
||||
* final cleanup of firmware resources (PCBs and XCBs).
|
||||
*
|
||||
* Attempt to cleanup only lost devices.
|
||||
*/
|
||||
if (fcport->loop_id != FC_NO_LOOP_ID) {
|
||||
if (IS_FWI2_CAPABLE(fcport->vha->hw)) {
|
||||
if (IS_FWI2_CAPABLE(fcport->vha->hw) &&
|
||||
fcport->scan_state != QLA_FCPORT_FOUND) {
|
||||
if (fcport->loop_id != FC_NO_LOOP_ID)
|
||||
fcport->logout_on_delete = 1;
|
||||
|
||||
|
|
@ -2771,7 +2782,7 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
|
|||
__LINE__);
|
||||
qlt_schedule_sess_for_deletion(fcport);
|
||||
}
|
||||
} else {
|
||||
} else if (!IS_FWI2_CAPABLE(fcport->vha->hw)) {
|
||||
qla2x00_port_logout(fcport->vha, fcport);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2424,6 +2424,89 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qla2x00_do_dport_diagnostics_v2(struct bsg_job *bsg_job)
|
||||
{
|
||||
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
|
||||
struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
|
||||
scsi_qla_host_t *vha = shost_priv(host);
|
||||
int rval;
|
||||
struct qla_dport_diag_v2 *dd;
|
||||
mbx_cmd_t mc;
|
||||
mbx_cmd_t *mcp = &mc;
|
||||
uint16_t options;
|
||||
|
||||
if (!IS_DPORT_CAPABLE(vha->hw))
|
||||
return -EPERM;
|
||||
|
||||
dd = kzalloc(sizeof(*dd), GFP_KERNEL);
|
||||
if (!dd)
|
||||
return -ENOMEM;
|
||||
|
||||
sg_copy_to_buffer(bsg_job->request_payload.sg_list,
|
||||
bsg_job->request_payload.sg_cnt, dd, sizeof(*dd));
|
||||
|
||||
options = dd->options;
|
||||
|
||||
/* Check dport Test in progress */
|
||||
if (options == QLA_GET_DPORT_RESULT_V2 &&
|
||||
vha->dport_status & DPORT_DIAG_IN_PROGRESS) {
|
||||
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
|
||||
EXT_STATUS_DPORT_DIAG_IN_PROCESS;
|
||||
goto dportcomplete;
|
||||
}
|
||||
|
||||
/* Check chip reset in progress and start/restart requests arrive */
|
||||
if (vha->dport_status & DPORT_DIAG_CHIP_RESET_IN_PROGRESS &&
|
||||
(options == QLA_START_DPORT_TEST_V2 ||
|
||||
options == QLA_RESTART_DPORT_TEST_V2)) {
|
||||
vha->dport_status &= ~DPORT_DIAG_CHIP_RESET_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/* Check chip reset in progress and get result request arrive */
|
||||
if (vha->dport_status & DPORT_DIAG_CHIP_RESET_IN_PROGRESS &&
|
||||
options == QLA_GET_DPORT_RESULT_V2) {
|
||||
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
|
||||
EXT_STATUS_DPORT_DIAG_NOT_RUNNING;
|
||||
goto dportcomplete;
|
||||
}
|
||||
|
||||
rval = qla26xx_dport_diagnostics_v2(vha, dd, mcp);
|
||||
|
||||
if (rval == QLA_SUCCESS) {
|
||||
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
|
||||
EXT_STATUS_OK;
|
||||
if (options == QLA_START_DPORT_TEST_V2 ||
|
||||
options == QLA_RESTART_DPORT_TEST_V2) {
|
||||
dd->mbx1 = mcp->mb[0];
|
||||
dd->mbx2 = mcp->mb[1];
|
||||
vha->dport_status |= DPORT_DIAG_IN_PROGRESS;
|
||||
} else if (options == QLA_GET_DPORT_RESULT_V2) {
|
||||
dd->mbx1 = le16_to_cpu(vha->dport_data[1]);
|
||||
dd->mbx2 = le16_to_cpu(vha->dport_data[2]);
|
||||
}
|
||||
} else {
|
||||
dd->mbx1 = mcp->mb[0];
|
||||
dd->mbx2 = mcp->mb[1];
|
||||
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
|
||||
EXT_STATUS_DPORT_DIAG_ERR;
|
||||
}
|
||||
|
||||
dportcomplete:
|
||||
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
|
||||
bsg_job->reply_payload.sg_cnt, dd, sizeof(*dd));
|
||||
|
||||
bsg_reply->reply_payload_rcv_len = sizeof(*dd);
|
||||
bsg_job->reply_len = sizeof(*bsg_reply);
|
||||
bsg_reply->result = DID_OK << 16;
|
||||
bsg_job_done(bsg_job, bsg_reply->result,
|
||||
bsg_reply->reply_payload_rcv_len);
|
||||
|
||||
kfree(dd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
|
||||
{
|
||||
|
|
@ -2860,6 +2943,9 @@ qla2x00_process_vendor_specific(struct scsi_qla_host *vha, struct bsg_job *bsg_j
|
|||
case QL_VND_DPORT_DIAGNOSTICS:
|
||||
return qla2x00_do_dport_diagnostics(bsg_job);
|
||||
|
||||
case QL_VND_DPORT_DIAGNOSTICS_V2:
|
||||
return qla2x00_do_dport_diagnostics_v2(bsg_job);
|
||||
|
||||
case QL_VND_EDIF_MGMT:
|
||||
return qla_edif_app_mgmt(bsg_job);
|
||||
|
||||
|
|
@ -2975,6 +3061,13 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
|
|||
|
||||
ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n",
|
||||
__func__, bsg_job);
|
||||
|
||||
if (qla2x00_isp_reg_stat(ha)) {
|
||||
ql_log(ql_log_info, vha, 0x9007,
|
||||
"PCI/Register disconnect.\n");
|
||||
qla_pci_set_eeh_busy(vha);
|
||||
}
|
||||
|
||||
/* find the bsg job from the active list of commands */
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
for (que = 0; que < ha->max_req_queues; que++) {
|
||||
|
|
@ -2992,7 +3085,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
|
|||
sp->u.bsg_job == bsg_job) {
|
||||
req->outstanding_cmds[cnt] = NULL;
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
if (ha->isp_ops->abort_command(sp)) {
|
||||
|
||||
if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) {
|
||||
ql_log(ql_log_warn, vha, 0x7089,
|
||||
"mbx abort_command failed.\n");
|
||||
bsg_reply->result = -EIO;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#define QL_VND_GET_TGT_STATS 0x25
|
||||
#define QL_VND_MANAGE_HOST_PORT 0x26
|
||||
#define QL_VND_MBX_PASSTHRU 0x2B
|
||||
#define QL_VND_DPORT_DIAGNOSTICS_V2 0x2C
|
||||
|
||||
/* BSG Vendor specific subcode returns */
|
||||
#define EXT_STATUS_OK 0
|
||||
|
|
@ -60,6 +61,9 @@
|
|||
#define EXT_STATUS_TIMEOUT 30
|
||||
#define EXT_STATUS_THREAD_FAILED 31
|
||||
#define EXT_STATUS_DATA_CMP_FAILED 32
|
||||
#define EXT_STATUS_DPORT_DIAG_ERR 40
|
||||
#define EXT_STATUS_DPORT_DIAG_IN_PROCESS 41
|
||||
#define EXT_STATUS_DPORT_DIAG_NOT_RUNNING 42
|
||||
|
||||
/* BSG definations for interpreting CommandSent field */
|
||||
#define INT_DEF_LB_LOOPBACK_CMD 0
|
||||
|
|
@ -288,6 +292,17 @@ struct qla_dport_diag {
|
|||
uint8_t unused[62];
|
||||
} __packed;
|
||||
|
||||
#define QLA_GET_DPORT_RESULT_V2 0 /* Get Result */
|
||||
#define QLA_RESTART_DPORT_TEST_V2 1 /* Restart test */
|
||||
#define QLA_START_DPORT_TEST_V2 2 /* Start test */
|
||||
struct qla_dport_diag_v2 {
|
||||
uint16_t options;
|
||||
uint16_t mbx1;
|
||||
uint16_t mbx2;
|
||||
uint8_t unused[58];
|
||||
uint8_t buf[1024]; /* Test Result */
|
||||
} __packed;
|
||||
|
||||
/* D_Port options */
|
||||
#define QLA_DPORT_RESULT 0x0
|
||||
#define QLA_DPORT_START 0x2
|
||||
|
|
|
|||
|
|
@ -383,5 +383,5 @@ ql_mask_match(uint level)
|
|||
if (ql2xextended_error_logging == 1)
|
||||
ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
|
||||
|
||||
return (level & ql2xextended_error_logging) == level;
|
||||
return level && ((level & ql2xextended_error_logging) == level);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ typedef union {
|
|||
#include "qla_nvme.h"
|
||||
#define QLA2XXX_DRIVER_NAME "qla2xxx"
|
||||
#define QLA2XXX_APIDEV "ql2xapidev"
|
||||
#define QLA2XXX_MANUFACTURER "QLogic Corporation"
|
||||
#define QLA2XXX_MANUFACTURER "Marvell Semiconductor, Inc."
|
||||
|
||||
/*
|
||||
* We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
|
||||
|
|
@ -1173,6 +1173,12 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
|
|||
|
||||
/* ISP mailbox loopback echo diagnostic error code */
|
||||
#define MBS_LB_RESET 0x17
|
||||
|
||||
/* AEN mailbox Port Diagnostics test */
|
||||
#define AEN_START_DIAG_TEST 0x0 /* start the diagnostics */
|
||||
#define AEN_DONE_DIAG_TEST_WITH_NOERR 0x1 /* Done with no errors */
|
||||
#define AEN_DONE_DIAG_TEST_WITH_ERR 0x2 /* Done with error.*/
|
||||
|
||||
/*
|
||||
* Firmware options 1, 2, 3.
|
||||
*/
|
||||
|
|
@ -2158,6 +2164,11 @@ typedef struct {
|
|||
#define CS_IOCB_ERROR 0x31 /* Generic error for IOCB request
|
||||
failure */
|
||||
#define CS_REJECT_RECEIVED 0x4E /* Reject received */
|
||||
#define CS_EDIF_AUTH_ERROR 0x63 /* decrypt error */
|
||||
#define CS_EDIF_PAD_LEN_ERROR 0x65 /* pad > frame size, not 4byte align */
|
||||
#define CS_EDIF_INV_REQ 0x66 /* invalid request */
|
||||
#define CS_EDIF_SPI_ERROR 0x67 /* rx frame unable to locate sa */
|
||||
#define CS_EDIF_HDR_ERROR 0x69 /* data frame != expected len */
|
||||
#define CS_BAD_PAYLOAD 0x80 /* Driver defined */
|
||||
#define CS_UNKNOWN 0x81 /* Driver defined */
|
||||
#define CS_RETRY 0x82 /* Driver defined */
|
||||
|
|
@ -2626,7 +2637,6 @@ typedef struct fc_port {
|
|||
struct {
|
||||
uint32_t enable:1; /* device is edif enabled/req'd */
|
||||
uint32_t app_stop:2;
|
||||
uint32_t app_started:1;
|
||||
uint32_t aes_gmac:1;
|
||||
uint32_t app_sess_online:1;
|
||||
uint32_t tx_sa_set:1;
|
||||
|
|
@ -2637,6 +2647,7 @@ typedef struct fc_port {
|
|||
uint32_t rx_rekey_cnt;
|
||||
uint64_t tx_bytes;
|
||||
uint64_t rx_bytes;
|
||||
uint8_t sess_down_acked;
|
||||
uint8_t auth_state;
|
||||
uint16_t authok:1;
|
||||
uint16_t rekey_cnt;
|
||||
|
|
@ -3204,6 +3215,8 @@ struct ct_sns_rsp {
|
|||
#define GFF_NVME_OFFSET 23 /* type = 28h */
|
||||
struct {
|
||||
uint8_t fc4_features[128];
|
||||
#define FC4_FF_TARGET BIT_0
|
||||
#define FC4_FF_INITIATOR BIT_1
|
||||
} gff_id;
|
||||
struct {
|
||||
uint8_t reserved;
|
||||
|
|
@ -3975,6 +3988,7 @@ struct qla_hw_data {
|
|||
/* SRB cache. */
|
||||
#define SRB_MIN_REQ 128
|
||||
mempool_t *srb_mempool;
|
||||
u8 port_name[WWN_SIZE];
|
||||
|
||||
volatile struct {
|
||||
uint32_t mbox_int :1;
|
||||
|
|
@ -4040,6 +4054,9 @@ struct qla_hw_data {
|
|||
uint32_t n2n_fw_acc_sec:1;
|
||||
uint32_t plogi_template_valid:1;
|
||||
uint32_t port_isolated:1;
|
||||
uint32_t eeh_flush:2;
|
||||
#define EEH_FLUSH_RDY 1
|
||||
#define EEH_FLUSH_DONE 2
|
||||
} flags;
|
||||
|
||||
uint16_t max_exchg;
|
||||
|
|
@ -4074,6 +4091,7 @@ struct qla_hw_data {
|
|||
uint32_t rsp_que_len;
|
||||
uint32_t req_que_off;
|
||||
uint32_t rsp_que_off;
|
||||
unsigned long eeh_jif;
|
||||
|
||||
/* Multi queue data structs */
|
||||
device_reg_t *mqiobase;
|
||||
|
|
@ -4256,8 +4274,8 @@ struct qla_hw_data {
|
|||
#define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001)
|
||||
#define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS)
|
||||
#define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED)
|
||||
#define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha) || \
|
||||
IS_QLA27XX(ha) || IS_QLA28XX(ha))
|
||||
#define IS_MQUE_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
|
||||
IS_QLA28XX(ha))
|
||||
#define IS_BIDI_CAPABLE(ha) \
|
||||
(IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
|
||||
/* Bit 21 of fw_attributes decides the MCTP capabilities */
|
||||
|
|
@ -5012,6 +5030,10 @@ typedef struct scsi_qla_host {
|
|||
u64 short_link_down_cnt;
|
||||
struct edif_dbell e_dbell;
|
||||
struct pur_core pur_cinfo;
|
||||
|
||||
#define DPORT_DIAG_IN_PROGRESS BIT_0
|
||||
#define DPORT_DIAG_CHIP_RESET_IN_PROGRESS BIT_1
|
||||
uint16_t dport_status;
|
||||
} scsi_qla_host_t;
|
||||
|
||||
struct qla27xx_image_status {
|
||||
|
|
@ -5443,4 +5465,10 @@ struct ql_vnd_tgt_stats_resp {
|
|||
#define IS_SESSION_DELETED(_fcport) (_fcport->disc_state == DSC_DELETE_PEND || \
|
||||
_fcport->disc_state == DSC_DELETED)
|
||||
|
||||
#define DBG_FCPORT_PRFMT(_fp, _fmt, _args...) \
|
||||
"%s: %8phC: " _fmt " (state=%d disc_state=%d scan_state=%d loopid=0x%x deleted=%d flags=0x%x)\n", \
|
||||
__func__, _fp->port_name, ##_args, atomic_read(&_fp->state), \
|
||||
_fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \
|
||||
_fp->flags
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -52,6 +52,31 @@ const char *sc_to_str(uint16_t cmd)
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
static struct edb_node *qla_edb_getnext(scsi_qla_host_t *vha)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct edb_node *edbnode = NULL;
|
||||
|
||||
spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
/* db nodes are fifo - no qualifications done */
|
||||
if (!list_empty(&vha->e_dbell.head)) {
|
||||
edbnode = list_first_entry(&vha->e_dbell.head,
|
||||
struct edb_node, list);
|
||||
list_del_init(&edbnode->list);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
return edbnode;
|
||||
}
|
||||
|
||||
static void qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node)
|
||||
{
|
||||
list_del_init(&node->list);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
static struct edif_list_entry *qla_edif_list_find_sa_index(fc_port_t *fcport,
|
||||
uint16_t handle)
|
||||
{
|
||||
|
|
@ -257,14 +282,8 @@ qla2x00_find_fcport_by_pid(scsi_qla_host_t *vha, port_id_t *id)
|
|||
|
||||
f = NULL;
|
||||
list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
|
||||
if ((f->flags & FCF_FCSP_DEVICE)) {
|
||||
ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x2058,
|
||||
"Found secure fcport - nn %8phN pn %8phN portid=0x%x, 0x%x.\n",
|
||||
f->node_name, f->port_name,
|
||||
f->d_id.b24, id->b24);
|
||||
if (f->d_id.b24 == id->b24)
|
||||
return f;
|
||||
}
|
||||
if (f->d_id.b24 == id->b24)
|
||||
return f;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -280,14 +299,19 @@ qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid)
|
|||
{
|
||||
/* check that the app is allow/known to the driver */
|
||||
|
||||
if (appid.app_vid == EDIF_APP_ID) {
|
||||
ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x911d, "%s app id ok\n", __func__);
|
||||
return true;
|
||||
if (appid.app_vid != EDIF_APP_ID) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app id not ok (%x)",
|
||||
__func__, appid.app_vid);
|
||||
return false;
|
||||
}
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app id not ok (%x)",
|
||||
__func__, appid.app_vid);
|
||||
|
||||
return false;
|
||||
if (appid.version != EDIF_VERSION1) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app version is not ok (%x)",
|
||||
__func__, appid.version);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -486,16 +510,35 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
/* mark doorbell as active since an app is now present */
|
||||
vha->e_dbell.db_flags |= EDB_ACTIVE;
|
||||
} else {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911e, "%s doorbell already active\n",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (N2N_TOPO(vha->hw)) {
|
||||
if (vha->hw->flags.n2n_fw_acc_sec)
|
||||
set_bit(N2N_LINK_RESET, &vha->dpc_flags);
|
||||
else
|
||||
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list)
|
||||
fcport->n2n_link_reset_cnt = 0;
|
||||
|
||||
if (vha->hw->flags.n2n_fw_acc_sec) {
|
||||
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list)
|
||||
qla_edif_sa_ctl_init(vha, fcport);
|
||||
|
||||
/*
|
||||
* While authentication app was not running, remote device
|
||||
* could still try to login with this local port. Let's
|
||||
* clear the state and try again.
|
||||
*/
|
||||
qla2x00_wait_for_sess_deletion(vha);
|
||||
|
||||
/* bounce the link to get the other guy to relogin */
|
||||
if (!vha->hw->flags.n2n_bigger) {
|
||||
set_bit(N2N_LINK_RESET, &vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(vha);
|
||||
}
|
||||
} else {
|
||||
qla2x00_wait_for_hba_online(vha);
|
||||
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(vha);
|
||||
qla2xxx_wake_dpc(vha);
|
||||
qla2x00_wait_for_hba_online(vha);
|
||||
}
|
||||
} else {
|
||||
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x2058,
|
||||
|
|
@ -517,19 +560,31 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
if (atomic_read(&vha->loop_state) == LOOP_DOWN)
|
||||
break;
|
||||
|
||||
fcport->edif.app_started = 1;
|
||||
fcport->login_retry = vha->hw->login_retry_count;
|
||||
|
||||
/* no activity */
|
||||
fcport->edif.app_stop = 0;
|
||||
fcport->edif.app_sess_online = 0;
|
||||
|
||||
if (fcport->scan_state != QLA_FCPORT_FOUND)
|
||||
continue;
|
||||
|
||||
if (fcport->port_type == FCT_UNKNOWN &&
|
||||
!fcport->fc4_features)
|
||||
rval = qla24xx_async_gffid(vha, fcport, true);
|
||||
|
||||
if (!rval && !(fcport->fc4_features & FC4_FF_TARGET ||
|
||||
fcport->port_type & (FCT_TARGET|FCT_NVME_TARGET)))
|
||||
continue;
|
||||
|
||||
rval = 0;
|
||||
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911e,
|
||||
"%s wwpn %8phC calling qla_edif_reset_auth_wait\n",
|
||||
__func__, fcport->port_name);
|
||||
fcport->edif.app_sess_online = 0;
|
||||
qlt_schedule_sess_for_deletion(fcport);
|
||||
qla_edif_sa_ctl_init(vha, fcport);
|
||||
}
|
||||
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
|
||||
}
|
||||
|
||||
if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {
|
||||
|
|
@ -540,9 +595,11 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
__func__);
|
||||
}
|
||||
|
||||
out:
|
||||
appreply.host_support_edif = vha->hw->flags.edif_enabled;
|
||||
appreply.edif_enode_active = vha->pur_cinfo.enode_flags;
|
||||
appreply.edif_edb_active = vha->e_dbell.db_flags;
|
||||
appreply.version = EDIF_VERSION1;
|
||||
|
||||
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
|
||||
|
||||
|
|
@ -610,9 +667,6 @@ qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
|
||||
fcport->send_els_logo = 1;
|
||||
qlt_schedule_sess_for_deletion(fcport);
|
||||
|
||||
/* qla_edif_flush_sa_ctl_lists(fcport); */
|
||||
fcport->edif.app_started = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -672,6 +726,7 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
portid.b.area = appplogiok.u.d_id.b.area;
|
||||
portid.b.al_pa = appplogiok.u.d_id.b.al_pa;
|
||||
|
||||
appplogireply.version = EDIF_VERSION1;
|
||||
switch (appplogiok.type) {
|
||||
case PL_TYPE_WWPN:
|
||||
fcport = qla2x00_find_fcport_by_wwpn(vha,
|
||||
|
|
@ -864,6 +919,8 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
} else {
|
||||
struct fc_port *fcport = NULL, *tf;
|
||||
|
||||
app_reply->version = EDIF_VERSION1;
|
||||
|
||||
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
|
||||
if (!(fcport->flags & FCF_FCSP_DEVICE))
|
||||
continue;
|
||||
|
|
@ -880,9 +937,25 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24)
|
||||
continue;
|
||||
|
||||
app_reply->ports[pcnt].rekey_count =
|
||||
fcport->edif.rekey_cnt;
|
||||
if (!N2N_TOPO(vha->hw)) {
|
||||
if (fcport->scan_state != QLA_FCPORT_FOUND)
|
||||
continue;
|
||||
|
||||
if (fcport->port_type == FCT_UNKNOWN &&
|
||||
!fcport->fc4_features)
|
||||
rval = qla24xx_async_gffid(vha, fcport,
|
||||
true);
|
||||
|
||||
if (!rval &&
|
||||
!(fcport->fc4_features & FC4_FF_TARGET ||
|
||||
fcport->port_type &
|
||||
(FCT_TARGET | FCT_NVME_TARGET)))
|
||||
continue;
|
||||
}
|
||||
|
||||
rval = 0;
|
||||
|
||||
app_reply->ports[pcnt].version = EDIF_VERSION1;
|
||||
app_reply->ports[pcnt].remote_type =
|
||||
VND_CMD_RTYPE_UNKNOWN;
|
||||
if (fcport->port_type & (FCT_NVME_TARGET | FCT_TARGET))
|
||||
|
|
@ -979,6 +1052,8 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
} else {
|
||||
struct fc_port *fcport = NULL, *tf;
|
||||
|
||||
app_reply->version = EDIF_VERSION1;
|
||||
|
||||
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
|
||||
if (fcport->edif.enable) {
|
||||
if (pcnt > app_req.num_ports)
|
||||
|
|
@ -1012,6 +1087,164 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
return rval;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
qla_edif_ack(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
||||
{
|
||||
struct fc_port *fcport;
|
||||
struct aen_complete_cmd ack;
|
||||
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
|
||||
|
||||
sg_copy_to_buffer(bsg_job->request_payload.sg_list,
|
||||
bsg_job->request_payload.sg_cnt, &ack, sizeof(ack));
|
||||
|
||||
ql_dbg(ql_dbg_edif, vha, 0x70cf,
|
||||
"%s: %06x event_code %x\n",
|
||||
__func__, ack.port_id.b24, ack.event_code);
|
||||
|
||||
fcport = qla2x00_find_fcport_by_pid(vha, &ack.port_id);
|
||||
SET_DID_STATUS(bsg_reply->result, DID_OK);
|
||||
|
||||
if (!fcport) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x70cf,
|
||||
"%s: unable to find fcport %06x \n",
|
||||
__func__, ack.port_id.b24);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (ack.event_code) {
|
||||
case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
|
||||
fcport->edif.sess_down_acked = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qla_edif_consume_dbell(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
||||
{
|
||||
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
|
||||
u32 sg_skip, reply_payload_len;
|
||||
bool keep;
|
||||
struct edb_node *dbnode = NULL;
|
||||
struct edif_app_dbell ap;
|
||||
int dat_size = 0;
|
||||
|
||||
sg_skip = 0;
|
||||
reply_payload_len = bsg_job->reply_payload.payload_len;
|
||||
|
||||
while ((reply_payload_len - sg_skip) >= sizeof(struct edb_node)) {
|
||||
dbnode = qla_edb_getnext(vha);
|
||||
if (dbnode) {
|
||||
keep = true;
|
||||
dat_size = 0;
|
||||
ap.event_code = dbnode->ntype;
|
||||
switch (dbnode->ntype) {
|
||||
case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
|
||||
case VND_CMD_AUTH_STATE_NEEDED:
|
||||
ap.port_id = dbnode->u.plogi_did;
|
||||
dat_size += sizeof(ap.port_id);
|
||||
break;
|
||||
case VND_CMD_AUTH_STATE_ELS_RCVD:
|
||||
ap.port_id = dbnode->u.els_sid;
|
||||
dat_size += sizeof(ap.port_id);
|
||||
break;
|
||||
case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:
|
||||
ap.port_id = dbnode->u.sa_aen.port_id;
|
||||
memcpy(&ap.event_data, &dbnode->u,
|
||||
sizeof(struct edif_sa_update_aen));
|
||||
dat_size += sizeof(struct edif_sa_update_aen);
|
||||
break;
|
||||
default:
|
||||
keep = false;
|
||||
ql_log(ql_log_warn, vha, 0x09102,
|
||||
"%s unknown DB type=%d %p\n",
|
||||
__func__, dbnode->ntype, dbnode);
|
||||
break;
|
||||
}
|
||||
ap.event_data_size = dat_size;
|
||||
/* 8 = sizeof(ap.event_code + ap.event_data_size) */
|
||||
dat_size += 8;
|
||||
if (keep)
|
||||
sg_skip += sg_copy_buffer(bsg_job->reply_payload.sg_list,
|
||||
bsg_job->reply_payload.sg_cnt,
|
||||
&ap, dat_size, sg_skip, false);
|
||||
|
||||
ql_dbg(ql_dbg_edif, vha, 0x09102,
|
||||
"%s Doorbell consumed : type=%d %p\n",
|
||||
__func__, dbnode->ntype, dbnode);
|
||||
|
||||
kfree(dbnode);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SET_DID_STATUS(bsg_reply->result, DID_OK);
|
||||
bsg_reply->reply_payload_rcv_len = sg_skip;
|
||||
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __qla_edif_dbell_bsg_done(scsi_qla_host_t *vha, struct bsg_job *bsg_job,
|
||||
u32 delay)
|
||||
{
|
||||
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
|
||||
|
||||
/* small sleep for doorbell events to accumulate */
|
||||
if (delay)
|
||||
msleep(delay);
|
||||
|
||||
qla_edif_consume_dbell(vha, bsg_job);
|
||||
|
||||
bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
|
||||
}
|
||||
|
||||
static void qla_edif_dbell_bsg_done(scsi_qla_host_t *vha)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct bsg_job *prev_bsg_job = NULL;
|
||||
|
||||
spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
|
||||
if (vha->e_dbell.dbell_bsg_job) {
|
||||
prev_bsg_job = vha->e_dbell.dbell_bsg_job;
|
||||
vha->e_dbell.dbell_bsg_job = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
if (prev_bsg_job)
|
||||
__qla_edif_dbell_bsg_done(vha, prev_bsg_job, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
qla_edif_dbell_bsg(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool return_bsg = false;
|
||||
|
||||
/* flush previous dbell bsg */
|
||||
qla_edif_dbell_bsg_done(vha);
|
||||
|
||||
spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
|
||||
if (list_empty(&vha->e_dbell.head) && DBELL_ACTIVE(vha)) {
|
||||
/*
|
||||
* when the next db event happens, bsg_job will return.
|
||||
* Otherwise, timer will return it.
|
||||
*/
|
||||
vha->e_dbell.dbell_bsg_job = bsg_job;
|
||||
vha->e_dbell.bsg_expire = jiffies + 10 * HZ;
|
||||
} else {
|
||||
return_bsg = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
if (return_bsg)
|
||||
__qla_edif_dbell_bsg_done(vha, bsg_job, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
qla_edif_app_mgmt(struct bsg_job *bsg_job)
|
||||
{
|
||||
|
|
@ -1023,8 +1256,13 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
|
|||
bool done = true;
|
||||
int32_t rval = 0;
|
||||
uint32_t vnd_sc = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
|
||||
u32 level = ql_dbg_edif;
|
||||
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911d, "%s vnd subcmd=%x\n",
|
||||
/* doorbell is high traffic */
|
||||
if (vnd_sc == QL_VND_SC_READ_DBELL)
|
||||
level = 0;
|
||||
|
||||
ql_dbg(level, vha, 0x911d, "%s vnd subcmd=%x\n",
|
||||
__func__, vnd_sc);
|
||||
|
||||
sg_copy_to_buffer(bsg_job->request_payload.sg_list,
|
||||
|
|
@ -1033,7 +1271,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
|
|||
|
||||
if (!vha->hw->flags.edif_enabled ||
|
||||
test_bit(VPORT_DELETE, &vha->dpc_flags)) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911d,
|
||||
ql_dbg(level, vha, 0x911d,
|
||||
"%s edif not enabled or vp delete. bsg ptr done %p. dpc_flags %lx\n",
|
||||
__func__, bsg_job, vha->dpc_flags);
|
||||
|
||||
|
|
@ -1042,7 +1280,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
|
|||
}
|
||||
|
||||
if (!qla_edif_app_check(vha, appcheck)) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911d,
|
||||
ql_dbg(level, vha, 0x911d,
|
||||
"%s app checked failed.\n",
|
||||
__func__);
|
||||
|
||||
|
|
@ -1074,6 +1312,13 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
|
|||
case QL_VND_SC_GET_STATS:
|
||||
rval = qla_edif_app_getstats(vha, bsg_job);
|
||||
break;
|
||||
case QL_VND_SC_AEN_COMPLETE:
|
||||
rval = qla_edif_ack(vha, bsg_job);
|
||||
break;
|
||||
case QL_VND_SC_READ_DBELL:
|
||||
rval = qla_edif_dbell_bsg(vha, bsg_job);
|
||||
done = false;
|
||||
break;
|
||||
default:
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n",
|
||||
__func__,
|
||||
|
|
@ -1085,7 +1330,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
|
|||
|
||||
done:
|
||||
if (done) {
|
||||
ql_dbg(ql_dbg_user, vha, 0x7009,
|
||||
ql_dbg(level, vha, 0x7009,
|
||||
"%s: %d bsg ptr done %p\n", __func__, __LINE__, bsg_job);
|
||||
bsg_job_done(bsg_job, bsg_reply->result,
|
||||
bsg_reply->reply_payload_rcv_len);
|
||||
|
|
@ -1247,6 +1492,8 @@ qla24xx_check_sadb_avail_slot(struct bsg_job *bsg_job, fc_port_t *fcport,
|
|||
|
||||
#define QLA_SA_UPDATE_FLAGS_RX_KEY 0x0
|
||||
#define QLA_SA_UPDATE_FLAGS_TX_KEY 0x2
|
||||
#define EDIF_MSLEEP_INTERVAL 100
|
||||
#define EDIF_RETRY_COUNT 50
|
||||
|
||||
int
|
||||
qla24xx_sadb_update(struct bsg_job *bsg_job)
|
||||
|
|
@ -1259,7 +1506,7 @@ qla24xx_sadb_update(struct bsg_job *bsg_job)
|
|||
struct edif_list_entry *edif_entry = NULL;
|
||||
int found = 0;
|
||||
int rval = 0;
|
||||
int result = 0;
|
||||
int result = 0, cnt;
|
||||
struct qla_sa_update_frame sa_frame;
|
||||
struct srb_iocb *iocb_cmd;
|
||||
port_id_t portid;
|
||||
|
|
@ -1500,11 +1747,23 @@ qla24xx_sadb_update(struct bsg_job *bsg_job)
|
|||
sp->done = qla2x00_bsg_job_done;
|
||||
iocb_cmd = &sp->u.iocb_cmd;
|
||||
iocb_cmd->u.sa_update.sa_frame = sa_frame;
|
||||
|
||||
cnt = 0;
|
||||
retry:
|
||||
rval = qla2x00_start_sp(sp);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
switch (rval) {
|
||||
case QLA_SUCCESS:
|
||||
break;
|
||||
case EAGAIN:
|
||||
msleep(EDIF_MSLEEP_INTERVAL);
|
||||
cnt++;
|
||||
if (cnt < EDIF_RETRY_COUNT)
|
||||
goto retry;
|
||||
|
||||
fallthrough;
|
||||
default:
|
||||
ql_log(ql_dbg_edif, vha, 0x70e3,
|
||||
"qla2x00_start_sp failed=%d.\n", rval);
|
||||
"%s qla2x00_start_sp failed=%d.\n",
|
||||
__func__, rval);
|
||||
|
||||
qla2x00_rel_sp(sp);
|
||||
rval = -EIO;
|
||||
|
|
@ -1797,30 +2056,6 @@ qla_edb_init(scsi_qla_host_t *vha)
|
|||
/* initialize lock which protects doorbell & init list */
|
||||
spin_lock_init(&vha->e_dbell.db_lock);
|
||||
INIT_LIST_HEAD(&vha->e_dbell.head);
|
||||
|
||||
/* create and initialize doorbell */
|
||||
init_completion(&vha->e_dbell.dbell);
|
||||
}
|
||||
|
||||
static void
|
||||
qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node)
|
||||
{
|
||||
/*
|
||||
* releases the space held by this edb node entry
|
||||
* this function does _not_ free the edb node itself
|
||||
* NB: the edb node entry passed should not be on any list
|
||||
*
|
||||
* currently for doorbell there's no additional cleanup
|
||||
* needed, but here as a placeholder for furture use.
|
||||
*/
|
||||
|
||||
if (!node) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x09122,
|
||||
"%s error - no valid node passed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
node->ntype = N_UNDEF;
|
||||
}
|
||||
|
||||
static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid)
|
||||
|
|
@ -1867,11 +2102,8 @@ static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid)
|
|||
}
|
||||
spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(e, tmp, &edb_list, list) {
|
||||
list_for_each_entry_safe(e, tmp, &edb_list, list)
|
||||
qla_edb_node_free(vha, e);
|
||||
list_del_init(&e->list);
|
||||
kfree(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* function called when app is stopping */
|
||||
|
|
@ -1899,14 +2131,10 @@ qla_edb_stop(scsi_qla_host_t *vha)
|
|||
"%s freeing edb_node type=%x\n",
|
||||
__func__, node->ntype);
|
||||
qla_edb_node_free(vha, node);
|
||||
list_del(&node->list);
|
||||
|
||||
kfree(node);
|
||||
}
|
||||
spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
/* wake up doorbell waiters - they'll be dismissed with error code */
|
||||
complete_all(&vha->e_dbell.dbell);
|
||||
qla_edif_dbell_bsg_done(vha);
|
||||
}
|
||||
|
||||
static struct edb_node *
|
||||
|
|
@ -1944,9 +2172,6 @@ qla_edb_node_add(scsi_qla_host_t *vha, struct edb_node *ptr)
|
|||
list_add_tail(&ptr->list, &vha->e_dbell.head);
|
||||
spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
/* ring doorbell for waiters */
|
||||
complete(&vha->e_dbell.dbell);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2010,47 +2235,29 @@ qla_edb_eventcreate(scsi_qla_host_t *vha, uint32_t dbtype,
|
|||
edbnode->u.sa_aen.port_id = fcport->d_id;
|
||||
edbnode->u.sa_aen.status = data;
|
||||
edbnode->u.sa_aen.key_type = data2;
|
||||
edbnode->u.sa_aen.version = EDIF_VERSION1;
|
||||
break;
|
||||
default:
|
||||
ql_dbg(ql_dbg_edif, vha, 0x09102,
|
||||
"%s unknown type: %x\n", __func__, dbtype);
|
||||
qla_edb_node_free(vha, edbnode);
|
||||
kfree(edbnode);
|
||||
edbnode = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (edbnode && (!qla_edb_node_add(vha, edbnode))) {
|
||||
if (edbnode) {
|
||||
if (!qla_edb_node_add(vha, edbnode)) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x09102,
|
||||
"%s unable to add dbnode\n", __func__);
|
||||
kfree(edbnode);
|
||||
return;
|
||||
}
|
||||
ql_dbg(ql_dbg_edif, vha, 0x09102,
|
||||
"%s unable to add dbnode\n", __func__);
|
||||
qla_edb_node_free(vha, edbnode);
|
||||
kfree(edbnode);
|
||||
return;
|
||||
"%s Doorbell produced : type=%d %p\n", __func__, dbtype, edbnode);
|
||||
qla_edif_dbell_bsg_done(vha);
|
||||
if (fcport)
|
||||
fcport->edif.auth_state = dbtype;
|
||||
}
|
||||
if (edbnode && fcport)
|
||||
fcport->edif.auth_state = dbtype;
|
||||
ql_dbg(ql_dbg_edif, vha, 0x09102,
|
||||
"%s Doorbell produced : type=%d %p\n", __func__, dbtype, edbnode);
|
||||
}
|
||||
|
||||
static struct edb_node *
|
||||
qla_edb_getnext(scsi_qla_host_t *vha)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct edb_node *edbnode = NULL;
|
||||
|
||||
spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
/* db nodes are fifo - no qualifications done */
|
||||
if (!list_empty(&vha->e_dbell.head)) {
|
||||
edbnode = list_first_entry(&vha->e_dbell.head,
|
||||
struct edb_node, list);
|
||||
list_del(&edbnode->list);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
|
||||
|
||||
return edbnode;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2078,89 +2285,14 @@ qla_edif_timer(scsi_qla_host_t *vha)
|
|||
ha->edif_post_stop_cnt_down = 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* app uses separate thread to read this. It'll wait until the doorbell
|
||||
* is rung by the driver or the max wait time has expired
|
||||
*/
|
||||
ssize_t
|
||||
edif_doorbell_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
|
||||
struct edb_node *dbnode = NULL;
|
||||
struct edif_app_dbell *ap = (struct edif_app_dbell *)buf;
|
||||
uint32_t dat_siz, buf_size, sz;
|
||||
|
||||
/* TODO: app currently hardcoded to 256. Will transition to bsg */
|
||||
sz = 256;
|
||||
|
||||
/* stop new threads from waiting if we're not init'd */
|
||||
if (DBELL_INACTIVE(vha)) {
|
||||
ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x09122,
|
||||
"%s error - edif db not enabled\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!vha->hw->flags.edif_enabled) {
|
||||
/* edif not enabled */
|
||||
ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x09122,
|
||||
"%s error - edif not enabled\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf_size = 0;
|
||||
while ((sz - buf_size) >= sizeof(struct edb_node)) {
|
||||
/* remove the next item from the doorbell list */
|
||||
dat_siz = 0;
|
||||
dbnode = qla_edb_getnext(vha);
|
||||
if (dbnode) {
|
||||
ap->event_code = dbnode->ntype;
|
||||
switch (dbnode->ntype) {
|
||||
case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
|
||||
case VND_CMD_AUTH_STATE_NEEDED:
|
||||
ap->port_id = dbnode->u.plogi_did;
|
||||
dat_siz += sizeof(ap->port_id);
|
||||
break;
|
||||
case VND_CMD_AUTH_STATE_ELS_RCVD:
|
||||
ap->port_id = dbnode->u.els_sid;
|
||||
dat_siz += sizeof(ap->port_id);
|
||||
break;
|
||||
case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:
|
||||
ap->port_id = dbnode->u.sa_aen.port_id;
|
||||
memcpy(ap->event_data, &dbnode->u,
|
||||
sizeof(struct edif_sa_update_aen));
|
||||
dat_siz += sizeof(struct edif_sa_update_aen);
|
||||
break;
|
||||
default:
|
||||
/* unknown node type, rtn unknown ntype */
|
||||
ap->event_code = VND_CMD_AUTH_STATE_UNDEF;
|
||||
memcpy(ap->event_data, &dbnode->ntype, 4);
|
||||
dat_siz += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_edif, vha, 0x09102,
|
||||
"%s Doorbell consumed : type=%d %p\n",
|
||||
__func__, dbnode->ntype, dbnode);
|
||||
/* we're done with the db node, so free it up */
|
||||
qla_edb_node_free(vha, dbnode);
|
||||
kfree(dbnode);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
ap->event_data_size = dat_siz;
|
||||
/* 8bytes = ap->event_code + ap->event_data_size */
|
||||
buf_size += dat_siz + 8;
|
||||
ap = (struct edif_app_dbell *)(buf + buf_size);
|
||||
}
|
||||
return buf_size;
|
||||
if (vha->e_dbell.dbell_bsg_job && time_after_eq(jiffies, vha->e_dbell.bsg_expire))
|
||||
qla_edif_dbell_bsg_done(vha);
|
||||
}
|
||||
|
||||
static void qla_noop_sp_done(srb_t *sp, int res)
|
||||
{
|
||||
sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
|
||||
/* ref: INIT */
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
}
|
||||
|
|
@ -2185,7 +2317,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e)
|
|||
if (!sa_ctl) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x70e6,
|
||||
"sa_ctl allocation failed\n");
|
||||
return -ENOMEM;
|
||||
rval = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
fcport = sa_ctl->fcport;
|
||||
|
|
@ -2195,7 +2328,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e)
|
|||
if (!sp) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x70e6,
|
||||
"SRB allocation failed\n");
|
||||
return -ENOMEM;
|
||||
rval = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
fcport->flags |= FCF_ASYNC_SENT;
|
||||
|
|
@ -2224,9 +2358,16 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e)
|
|||
|
||||
rval = qla2x00_start_sp(sp);
|
||||
|
||||
if (rval != QLA_SUCCESS)
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
if (rval != QLA_SUCCESS) {
|
||||
goto done_free_sp;
|
||||
}
|
||||
|
||||
return rval;
|
||||
done_free_sp:
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
done:
|
||||
fcport->flags &= ~FCF_ASYNC_ACTIVE;
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
|
@ -2446,8 +2587,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
|
|||
|
||||
fcport = qla2x00_find_fcport_by_pid(host, &purex->pur_info.pur_sid);
|
||||
|
||||
if (DBELL_INACTIVE(vha) ||
|
||||
(fcport && EDIF_SESSION_DOWN(fcport))) {
|
||||
if (DBELL_INACTIVE(vha)) {
|
||||
ql_dbg(ql_dbg_edif, host, 0x0910c, "%s e_dbell.db_flags =%x %06x\n",
|
||||
__func__, host->e_dbell.db_flags,
|
||||
fcport ? fcport->d_id.b24 : 0);
|
||||
|
|
@ -2457,6 +2597,22 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
|
|||
return;
|
||||
}
|
||||
|
||||
if (fcport && EDIF_SESSION_DOWN(fcport)) {
|
||||
ql_dbg(ql_dbg_edif, host, 0x13b6,
|
||||
"%s terminate exchange. Send logo to 0x%x\n",
|
||||
__func__, a.did.b24);
|
||||
|
||||
a.tx_byte_count = a.tx_len = 0;
|
||||
a.tx_addr = 0;
|
||||
a.control_flags = EPD_RX_XCHG; /* EPD_RX_XCHG = terminate cmd */
|
||||
qla_els_reject_iocb(host, (*rsp)->qpair, &a);
|
||||
qla_enode_free(host, ptr);
|
||||
/* send logo to let remote port knows to tear down session */
|
||||
fcport->send_els_logo = 1;
|
||||
qlt_schedule_sess_for_deletion(fcport);
|
||||
return;
|
||||
}
|
||||
|
||||
/* add the local enode to the list */
|
||||
qla_enode_add(host, ptr);
|
||||
|
||||
|
|
@ -2832,6 +2988,12 @@ qla28xx_start_scsi_edif(srb_t *sp)
|
|||
|
||||
tot_dsds = nseg;
|
||||
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
|
||||
|
||||
sp->iores.res_type = RESOURCE_INI;
|
||||
sp->iores.iocb_cnt = req_cnt;
|
||||
if (qla_get_iocbs(sp->qpair, &sp->iores))
|
||||
goto queuing_error;
|
||||
|
||||
if (req->cnt < (req_cnt + 2)) {
|
||||
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
|
||||
rd_reg_dword(req->req_q_out);
|
||||
|
|
@ -3023,6 +3185,7 @@ qla28xx_start_scsi_edif(srb_t *sp)
|
|||
mempool_free(sp->u.scmd.ct6_ctx, ha->ctx_mempool);
|
||||
sp->u.scmd.ct6_ctx = NULL;
|
||||
}
|
||||
qla_put_iocbs(sp->qpair, &sp->iores);
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
|
@ -3349,10 +3512,14 @@ int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
fc_port_t *fcport = NULL;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
srb_t *sp;
|
||||
int rval = (DID_ERROR << 16);
|
||||
int rval = (DID_ERROR << 16), cnt;
|
||||
port_id_t d_id;
|
||||
struct qla_bsg_auth_els_request *p =
|
||||
(struct qla_bsg_auth_els_request *)bsg_job->request;
|
||||
struct qla_bsg_auth_els_reply *rpl =
|
||||
(struct qla_bsg_auth_els_reply *)bsg_job->reply;
|
||||
|
||||
rpl->version = EDIF_VERSION1;
|
||||
|
||||
d_id.b.al_pa = bsg_request->rqst_data.h_els.port_id[2];
|
||||
d_id.b.area = bsg_request->rqst_data.h_els.port_id[1];
|
||||
|
|
@ -3371,7 +3538,7 @@ int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
if (qla_bsg_check(vha, bsg_job, fcport))
|
||||
return 0;
|
||||
|
||||
if (fcport->loop_id == FC_NO_LOOP_ID) {
|
||||
if (EDIF_SESS_DELETE(fcport)) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x910d,
|
||||
"%s ELS code %x, no loop id.\n", __func__,
|
||||
bsg_request->rqst_data.r_els.els_code);
|
||||
|
|
@ -3440,17 +3607,26 @@ int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
sp->free = qla2x00_bsg_sp_free;
|
||||
sp->done = qla2x00_bsg_job_done;
|
||||
|
||||
cnt = 0;
|
||||
retry:
|
||||
rval = qla2x00_start_sp(sp);
|
||||
|
||||
ql_dbg(ql_dbg_edif, vha, 0x700a,
|
||||
"%s %s %8phN xchg %x ctlflag %x hdl %x reqlen %xh bsg ptr %p\n",
|
||||
__func__, sc_to_str(p->e.sub_cmd), fcport->port_name,
|
||||
p->e.extra_rx_xchg_address, p->e.extra_control_flags,
|
||||
sp->handle, sp->remap.req.len, bsg_job);
|
||||
|
||||
if (rval != QLA_SUCCESS) {
|
||||
switch (rval) {
|
||||
case QLA_SUCCESS:
|
||||
ql_dbg(ql_dbg_edif, vha, 0x700a,
|
||||
"%s %s %8phN xchg %x ctlflag %x hdl %x reqlen %xh bsg ptr %p\n",
|
||||
__func__, sc_to_str(p->e.sub_cmd), fcport->port_name,
|
||||
p->e.extra_rx_xchg_address, p->e.extra_control_flags,
|
||||
sp->handle, sp->remap.req.len, bsg_job);
|
||||
break;
|
||||
case EAGAIN:
|
||||
msleep(EDIF_MSLEEP_INTERVAL);
|
||||
cnt++;
|
||||
if (cnt < EDIF_RETRY_COUNT)
|
||||
goto retry;
|
||||
fallthrough;
|
||||
default:
|
||||
ql_log(ql_log_warn, vha, 0x700e,
|
||||
"qla2x00_start_sp failed = %d\n", rval);
|
||||
"%s qla2x00_start_sp failed = %d\n", __func__, rval);
|
||||
SET_DID_STATUS(bsg_reply->result, DID_IMM_RETRY);
|
||||
rval = -EIO;
|
||||
goto done_free_remap_rsp;
|
||||
|
|
@ -3472,14 +3648,29 @@ int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
|
|||
|
||||
void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess)
|
||||
{
|
||||
u16 cnt = 0;
|
||||
|
||||
if (sess->edif.app_sess_online && DBELL_ACTIVE(vha)) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0xf09c,
|
||||
"%s: sess %8phN send port_offline event\n",
|
||||
__func__, sess->port_name);
|
||||
sess->edif.app_sess_online = 0;
|
||||
sess->edif.sess_down_acked = 0;
|
||||
qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_SESSION_SHUTDOWN,
|
||||
sess->d_id.b24, 0, sess);
|
||||
qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24);
|
||||
|
||||
while (!READ_ONCE(sess->edif.sess_down_acked) &&
|
||||
!test_bit(VPORT_DELETE, &vha->dpc_flags)) {
|
||||
msleep(100);
|
||||
cnt++;
|
||||
if (cnt > 100)
|
||||
break;
|
||||
}
|
||||
sess->edif.sess_down_acked = 0;
|
||||
ql_dbg(ql_dbg_disc, vha, 0xf09c,
|
||||
"%s: sess %8phN port_offline event completed\n",
|
||||
__func__, sess->port_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ struct edif_dbell {
|
|||
enum db_flags_t db_flags;
|
||||
spinlock_t db_lock;
|
||||
struct list_head head;
|
||||
struct completion dbell;
|
||||
struct bsg_job *dbell_bsg_job;
|
||||
unsigned long bsg_expire;
|
||||
};
|
||||
|
||||
#define SA_UPDATE_IOCB_TYPE 0x71 /* Security Association Update IOCB entry */
|
||||
|
|
@ -140,4 +141,8 @@ struct enode {
|
|||
(DBELL_ACTIVE(_fcport->vha) && \
|
||||
(_fcport->disc_state == DSC_LOGIN_AUTH_PEND))
|
||||
|
||||
#define EDIF_SESS_DELETE(_s) \
|
||||
(qla_ini_mode_enabled(_s->vha) && (_s->disc_state == DSC_DELETE_PEND || \
|
||||
_s->disc_state == DSC_DELETED))
|
||||
|
||||
#endif /* __QLA_EDIF_H */
|
||||
|
|
|
|||
|
|
@ -7,13 +7,15 @@
|
|||
#ifndef __QLA_EDIF_BSG_H
|
||||
#define __QLA_EDIF_BSG_H
|
||||
|
||||
#define EDIF_VERSION1 1
|
||||
|
||||
/* BSG Vendor specific commands */
|
||||
#define ELS_MAX_PAYLOAD 2112
|
||||
#ifndef WWN_SIZE
|
||||
#define WWN_SIZE 8
|
||||
#endif
|
||||
#define VND_CMD_APP_RESERVED_SIZE 32
|
||||
|
||||
#define VND_CMD_APP_RESERVED_SIZE 28
|
||||
#define VND_CMD_PAD_SIZE 3
|
||||
enum auth_els_sub_cmd {
|
||||
SEND_ELS = 0,
|
||||
SEND_ELS_REPLY,
|
||||
|
|
@ -28,7 +30,9 @@ struct extra_auth_els {
|
|||
#define BSG_CTL_FLAG_LS_ACC 1
|
||||
#define BSG_CTL_FLAG_LS_RJT 2
|
||||
#define BSG_CTL_FLAG_TRM 3
|
||||
uint8_t extra_rsvd[3];
|
||||
uint8_t version;
|
||||
uint8_t pad[2];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct qla_bsg_auth_els_request {
|
||||
|
|
@ -39,51 +43,46 @@ struct qla_bsg_auth_els_request {
|
|||
struct qla_bsg_auth_els_reply {
|
||||
struct fc_bsg_reply r;
|
||||
uint32_t rx_xchg_address;
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
};
|
||||
|
||||
struct app_id {
|
||||
int app_vid;
|
||||
uint8_t app_key[32];
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct app_start_reply {
|
||||
uint32_t host_support_edif;
|
||||
uint32_t edif_enode_active;
|
||||
uint32_t edif_edb_active;
|
||||
uint32_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct app_start {
|
||||
struct app_id app_info;
|
||||
uint32_t prli_to;
|
||||
uint32_t key_shred;
|
||||
uint8_t app_start_flags;
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE - 1];
|
||||
uint8_t version;
|
||||
uint8_t pad[2];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct app_stop {
|
||||
struct app_id app_info;
|
||||
char buf[16];
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct app_plogi_reply {
|
||||
uint32_t prli_status;
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define RECFG_TIME 1
|
||||
#define RECFG_BYTES 2
|
||||
|
||||
struct app_rekey_cfg {
|
||||
struct app_id app_info;
|
||||
uint8_t rekey_mode;
|
||||
port_id_t d_id;
|
||||
uint8_t force;
|
||||
union {
|
||||
int64_t bytes;
|
||||
int64_t time;
|
||||
} rky_units;
|
||||
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
|
|
@ -91,7 +90,9 @@ struct app_pinfo_req {
|
|||
struct app_id app_info;
|
||||
uint8_t num_ports;
|
||||
port_id_t remote_pid;
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct app_pinfo {
|
||||
|
|
@ -103,11 +104,8 @@ struct app_pinfo {
|
|||
#define VND_CMD_RTYPE_INITIATOR 2
|
||||
uint8_t remote_state;
|
||||
uint8_t auth_state;
|
||||
uint8_t rekey_mode;
|
||||
int64_t rekey_count;
|
||||
int64_t rekey_config_value;
|
||||
int64_t rekey_consumed_value;
|
||||
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
|
|
@ -120,6 +118,8 @@ struct app_pinfo {
|
|||
|
||||
struct app_pinfo_reply {
|
||||
uint8_t port_count;
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
struct app_pinfo ports[];
|
||||
} __packed;
|
||||
|
|
@ -127,6 +127,8 @@ struct app_pinfo_reply {
|
|||
struct app_sinfo_req {
|
||||
struct app_id app_info;
|
||||
uint8_t num_ports;
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
|
|
@ -140,6 +142,9 @@ struct app_sinfo {
|
|||
|
||||
struct app_stats_reply {
|
||||
uint8_t elem_count;
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
struct app_sinfo elem[];
|
||||
} __packed;
|
||||
|
||||
|
|
@ -163,9 +168,11 @@ struct qla_sa_update_frame {
|
|||
uint8_t node_name[WWN_SIZE];
|
||||
uint8_t port_name[WWN_SIZE];
|
||||
port_id_t port_id;
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved2[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
// used for edif mgmt bsg interface
|
||||
#define QL_VND_SC_UNDEF 0
|
||||
#define QL_VND_SC_SA_UPDATE 1
|
||||
#define QL_VND_SC_APP_START 2
|
||||
|
|
@ -175,6 +182,22 @@ struct qla_sa_update_frame {
|
|||
#define QL_VND_SC_REKEY_CONFIG 6
|
||||
#define QL_VND_SC_GET_FCINFO 7
|
||||
#define QL_VND_SC_GET_STATS 8
|
||||
#define QL_VND_SC_AEN_COMPLETE 9
|
||||
#define QL_VND_SC_READ_DBELL 10
|
||||
|
||||
/*
|
||||
* bsg caller to provide empty buffer for doorbell events.
|
||||
*
|
||||
* sg_io_v4.din_xferp = empty buffer for door bell events
|
||||
* sg_io_v4.dout_xferp = struct edif_read_dbell *buf
|
||||
*/
|
||||
struct edif_read_dbell {
|
||||
struct app_id app_info;
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
};
|
||||
|
||||
|
||||
/* Application interface data structure for rtn data */
|
||||
#define EXT_DEF_EVENT_DATA_SIZE 64
|
||||
|
|
@ -191,7 +214,9 @@ struct edif_sa_update_aen {
|
|||
port_id_t port_id;
|
||||
uint32_t key_type; /* Tx (1) or RX (2) */
|
||||
uint32_t status; /* 0 succes, 1 failed, 2 timeout , 3 error */
|
||||
uint8_t reserved[16];
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define QL_VND_SA_STAT_SUCCESS 0
|
||||
|
|
@ -212,9 +237,22 @@ struct auth_complete_cmd {
|
|||
uint8_t wwpn[WWN_SIZE];
|
||||
port_id_t d_id;
|
||||
} u;
|
||||
uint32_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct aen_complete_cmd {
|
||||
struct app_id app_info;
|
||||
port_id_t port_id;
|
||||
uint32_t event_code;
|
||||
uint8_t version;
|
||||
uint8_t pad[VND_CMD_PAD_SIZE];
|
||||
uint8_t reserved[VND_CMD_APP_RESERVED_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define RX_DELAY_DELETE_TIMEOUT 20
|
||||
|
||||
#define FCH_EVT_VENDOR_UNIQUE_VPORT_DOWN 1
|
||||
|
||||
#endif /* QLA_EDIF_BSG_H */
|
||||
|
|
|
|||
|
|
@ -807,7 +807,7 @@ struct els_entry_24xx {
|
|||
#define EPD_ELS_COMMAND (0 << 13)
|
||||
#define EPD_ELS_ACC (1 << 13)
|
||||
#define EPD_ELS_RJT (2 << 13)
|
||||
#define EPD_RX_XCHG (3 << 13)
|
||||
#define EPD_RX_XCHG (3 << 13) /* terminate exchange */
|
||||
#define ECF_CLR_PASSTHRU_PEND BIT_12
|
||||
#define ECF_INCL_FRAME_HDR BIT_11
|
||||
#define ECF_SEC_LOGIN BIT_3
|
||||
|
|
|
|||
|
|
@ -193,6 +193,8 @@ extern int ql2xsecenable;
|
|||
extern int ql2xenforce_iocb_limit;
|
||||
extern int ql2xabts_wait_nvme;
|
||||
extern u32 ql2xnvme_queues;
|
||||
extern int ql2xrspq_follow_inptr;
|
||||
extern int ql2xrspq_follow_inptr_legacy;
|
||||
|
||||
extern int qla2x00_loop_reset(scsi_qla_host_t *);
|
||||
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
|
||||
|
|
@ -335,6 +337,7 @@ extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
|
|||
extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha,
|
||||
struct qla_work_evt *e);
|
||||
void qla2x00_sp_release(struct kref *kref);
|
||||
void qla2x00_els_dcmd2_iocb_timeout(void *data);
|
||||
|
||||
/*
|
||||
* Global Function Prototypes in qla_mbx.c source file.
|
||||
|
|
@ -433,7 +436,8 @@ extern int
|
|||
qla2x00_get_resource_cnts(scsi_qla_host_t *);
|
||||
|
||||
extern int
|
||||
qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
|
||||
qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map,
|
||||
u8 *num_entries);
|
||||
|
||||
extern int
|
||||
qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
|
||||
|
|
@ -554,6 +558,10 @@ qla2x00_dump_mctp_data(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
|
|||
extern int
|
||||
qla26xx_dport_diagnostics(scsi_qla_host_t *, void *, uint, uint);
|
||||
|
||||
extern int
|
||||
qla26xx_dport_diagnostics_v2(scsi_qla_host_t *,
|
||||
struct qla_dport_diag_v2 *, mbx_cmd_t *);
|
||||
|
||||
int qla24xx_send_mb_cmd(struct scsi_qla_host *, mbx_cmd_t *);
|
||||
int qla24xx_gpdb_wait(struct scsi_qla_host *, fc_port_t *, u8);
|
||||
int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t,
|
||||
|
|
@ -727,7 +735,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
|
|||
void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *);
|
||||
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
|
||||
void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
|
||||
int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport);
|
||||
int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool);
|
||||
int qla24xx_async_gpnft(scsi_qla_host_t *, u8, srb_t *);
|
||||
void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *);
|
||||
void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *);
|
||||
|
|
@ -989,7 +997,6 @@ fc_port_t *qla2x00_find_fcport_by_pid(scsi_qla_host_t *vha, port_id_t *id);
|
|||
void qla_edb_eventcreate(scsi_qla_host_t *vha, uint32_t dbtype, uint32_t data, uint32_t data2,
|
||||
fc_port_t *fcport);
|
||||
void qla_edb_stop(scsi_qla_host_t *vha);
|
||||
ssize_t edif_doorbell_show(struct device *dev, struct device_attribute *attr, char *buf);
|
||||
int32_t qla_edif_app_mgmt(struct bsg_job *bsg_job);
|
||||
void qla_enode_init(scsi_qla_host_t *vha);
|
||||
void qla_enode_stop(scsi_qla_host_t *vha);
|
||||
|
|
|
|||
|
|
@ -1596,7 +1596,6 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
|
|||
unsigned int callopt)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct init_cb_24xx *icb24 = (void *)ha->init_cb;
|
||||
struct new_utsname *p_sysid = utsname();
|
||||
struct ct_fdmi_hba_attr *eiter;
|
||||
uint16_t alen;
|
||||
|
|
@ -1617,7 +1616,7 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
|
|||
eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
|
||||
alen = scnprintf(
|
||||
eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
|
||||
"%s", "QLogic Corporation");
|
||||
"%s", QLA2XXX_MANUFACTURER);
|
||||
alen += FDMI_ATTR_ALIGNMENT(alen);
|
||||
alen += FDMI_ATTR_TYPELEN(eiter);
|
||||
eiter->len = cpu_to_be16(alen);
|
||||
|
|
@ -1758,8 +1757,8 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
|
|||
/* MAX CT Payload Length */
|
||||
eiter = entries + size;
|
||||
eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);
|
||||
eiter->a.max_ct_len = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ?
|
||||
icb24->frame_payload_size : ha->init_cb->frame_payload_size));
|
||||
eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size >> 2);
|
||||
|
||||
alen = sizeof(eiter->a.max_ct_len);
|
||||
alen += FDMI_ATTR_TYPELEN(eiter);
|
||||
eiter->len = cpu_to_be16(alen);
|
||||
|
|
@ -1851,7 +1850,6 @@ qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries,
|
|||
unsigned int callopt)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct init_cb_24xx *icb24 = (void *)ha->init_cb;
|
||||
struct new_utsname *p_sysid = utsname();
|
||||
char *hostname = p_sysid ?
|
||||
p_sysid->nodename : fc_host_system_hostname(vha->host);
|
||||
|
|
@ -1903,8 +1901,7 @@ qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries,
|
|||
/* Max frame size. */
|
||||
eiter = entries + size;
|
||||
eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
|
||||
eiter->a.max_frame_size = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ?
|
||||
icb24->frame_payload_size : ha->init_cb->frame_payload_size));
|
||||
eiter->a.max_frame_size = cpu_to_be32(ha->frame_payload_size);
|
||||
alen = sizeof(eiter->a.max_frame_size);
|
||||
alen += FDMI_ATTR_TYPELEN(eiter);
|
||||
eiter->len = cpu_to_be16(alen);
|
||||
|
|
@ -3280,19 +3277,12 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
|
|||
return rval;
|
||||
}
|
||||
|
||||
void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea)
|
||||
{
|
||||
fc_port_t *fcport = ea->fcport;
|
||||
|
||||
qla24xx_post_gnl_work(vha, fcport);
|
||||
}
|
||||
|
||||
void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
|
||||
{
|
||||
struct scsi_qla_host *vha = sp->vha;
|
||||
fc_port_t *fcport = sp->fcport;
|
||||
struct ct_sns_rsp *ct_rsp;
|
||||
struct event_arg ea;
|
||||
uint8_t fc4_scsi_feat;
|
||||
uint8_t fc4_nvme_feat;
|
||||
|
||||
|
|
@ -3300,10 +3290,10 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
|
|||
"Async done-%s res %x ID %x. %8phC\n",
|
||||
sp->name, res, fcport->d_id.b24, fcport->port_name);
|
||||
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
|
||||
ct_rsp = sp->u.iocb_cmd.u.ctarg.rsp;
|
||||
fc4_scsi_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
|
||||
fc4_nvme_feat = ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
|
||||
sp->rc = res;
|
||||
|
||||
/*
|
||||
* FC-GS-7, 5.2.3.12 FC-4 Features - format
|
||||
|
|
@ -3324,24 +3314,42 @@ void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
|
|||
}
|
||||
}
|
||||
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.sp = sp;
|
||||
ea.fcport = sp->fcport;
|
||||
ea.rc = res;
|
||||
if (sp->flags & SRB_WAKEUP_ON_COMP) {
|
||||
complete(sp->comp);
|
||||
} else {
|
||||
if (sp->u.iocb_cmd.u.ctarg.req) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sp->u.iocb_cmd.u.ctarg.req_allocated_size,
|
||||
sp->u.iocb_cmd.u.ctarg.req,
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.req = NULL;
|
||||
}
|
||||
|
||||
qla24xx_handle_gffid_event(vha, &ea);
|
||||
/* ref: INIT */
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
if (sp->u.iocb_cmd.u.ctarg.rsp) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
|
||||
}
|
||||
|
||||
/* ref: INIT */
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
/* we should not be here */
|
||||
dump_stack();
|
||||
}
|
||||
}
|
||||
|
||||
/* Get FC4 Feature with Nport ID. */
|
||||
int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
|
||||
int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool wait)
|
||||
{
|
||||
int rval = QLA_FUNCTION_FAILED;
|
||||
struct ct_sns_req *ct_req;
|
||||
srb_t *sp;
|
||||
DECLARE_COMPLETION_ONSTACK(comp);
|
||||
|
||||
if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
|
||||
/* this routine does not have handling for no wait */
|
||||
if (!vha->flags.online || !wait)
|
||||
return rval;
|
||||
|
||||
/* ref: INIT */
|
||||
|
|
@ -3349,43 +3357,86 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|||
if (!sp)
|
||||
return rval;
|
||||
|
||||
fcport->flags |= FCF_ASYNC_SENT;
|
||||
sp->type = SRB_CT_PTHRU_CMD;
|
||||
sp->name = "gffid";
|
||||
sp->gen1 = fcport->rscn_gen;
|
||||
sp->gen2 = fcport->login_gen;
|
||||
qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
|
||||
qla24xx_async_gffid_sp_done);
|
||||
sp->comp = ∁
|
||||
sp->u.iocb_cmd.timeout = qla2x00_els_dcmd2_iocb_timeout;
|
||||
|
||||
if (wait)
|
||||
sp->flags = SRB_WAKEUP_ON_COMP;
|
||||
|
||||
sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
|
||||
sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
|
||||
sp->u.iocb_cmd.u.ctarg.req_allocated_size,
|
||||
&sp->u.iocb_cmd.u.ctarg.req_dma,
|
||||
GFP_KERNEL);
|
||||
if (!sp->u.iocb_cmd.u.ctarg.req) {
|
||||
ql_log(ql_log_warn, vha, 0xd041,
|
||||
"%s: Failed to allocate ct_sns request.\n",
|
||||
__func__);
|
||||
goto done_free_sp;
|
||||
}
|
||||
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
|
||||
&sp->u.iocb_cmd.u.ctarg.rsp_dma,
|
||||
GFP_KERNEL);
|
||||
if (!sp->u.iocb_cmd.u.ctarg.rsp) {
|
||||
ql_log(ql_log_warn, vha, 0xd041,
|
||||
"%s: Failed to allocate ct_sns response.\n",
|
||||
__func__);
|
||||
goto done_free_sp;
|
||||
}
|
||||
|
||||
/* CT_IU preamble */
|
||||
ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFF_ID_CMD,
|
||||
GFF_ID_RSP_SIZE);
|
||||
ct_req = qla2x00_prep_ct_req(sp->u.iocb_cmd.u.ctarg.req, GFF_ID_CMD, GFF_ID_RSP_SIZE);
|
||||
|
||||
ct_req->req.gff_id.port_id[0] = fcport->d_id.b.domain;
|
||||
ct_req->req.gff_id.port_id[1] = fcport->d_id.b.area;
|
||||
ct_req->req.gff_id.port_id[2] = fcport->d_id.b.al_pa;
|
||||
|
||||
sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
|
||||
sp->u.iocb_cmd.u.ctarg.req_size = GFF_ID_REQ_SIZE;
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_size = GFF_ID_RSP_SIZE;
|
||||
sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0x2132,
|
||||
"Async-%s hdl=%x %8phC.\n", sp->name,
|
||||
sp->handle, fcport->port_name);
|
||||
|
||||
rval = qla2x00_start_sp(sp);
|
||||
if (rval != QLA_SUCCESS)
|
||||
goto done_free_sp;
|
||||
|
||||
return rval;
|
||||
if (rval != QLA_SUCCESS) {
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
goto done_free_sp;
|
||||
} else {
|
||||
ql_dbg(ql_dbg_disc, vha, 0x3074,
|
||||
"Async-%s hdl=%x portid %06x\n",
|
||||
sp->name, sp->handle, fcport->d_id.b24);
|
||||
}
|
||||
|
||||
wait_for_completion(sp->comp);
|
||||
rval = sp->rc;
|
||||
|
||||
done_free_sp:
|
||||
if (sp->u.iocb_cmd.u.ctarg.req) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sp->u.iocb_cmd.u.ctarg.req_allocated_size,
|
||||
sp->u.iocb_cmd.u.ctarg.req,
|
||||
sp->u.iocb_cmd.u.ctarg.req_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.req = NULL;
|
||||
}
|
||||
|
||||
if (sp->u.iocb_cmd.u.ctarg.rsp) {
|
||||
dma_free_coherent(&vha->hw->pdev->dev,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp,
|
||||
sp->u.iocb_cmd.u.ctarg.rsp_dma);
|
||||
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
|
||||
}
|
||||
|
||||
/* ref: INIT */
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
fcport->flags &= ~FCF_ASYNC_SENT;
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
|
@ -3578,7 +3629,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
|
|||
do_delete) {
|
||||
if (fcport->loop_id != FC_NO_LOOP_ID) {
|
||||
if (fcport->flags & FCF_FCP2_DEVICE)
|
||||
fcport->logout_on_delete = 0;
|
||||
continue;
|
||||
|
||||
ql_log(ql_log_warn, vha, 0x20f0,
|
||||
"%s %d %8phC post del sess\n",
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ qla2x00_sp_timeout(struct timer_list *t)
|
|||
{
|
||||
srb_t *sp = from_timer(sp, t, u.iocb_cmd.timer);
|
||||
struct srb_iocb *iocb;
|
||||
scsi_qla_host_t *vha = sp->vha;
|
||||
|
||||
WARN_ON(irqs_disabled());
|
||||
iocb = &sp->u.iocb_cmd;
|
||||
|
|
@ -54,6 +55,12 @@ qla2x00_sp_timeout(struct timer_list *t)
|
|||
|
||||
/* ref: TMR */
|
||||
kref_put(&sp->cmd_kref, qla2x00_sp_release);
|
||||
|
||||
if (vha && qla2x00_isp_reg_stat(vha->hw)) {
|
||||
ql_log(ql_log_info, vha, 0x9008,
|
||||
"PCI/Register disconnect.\n");
|
||||
qla_pci_set_eeh_busy(vha);
|
||||
}
|
||||
}
|
||||
|
||||
void qla2x00_sp_free(srb_t *sp)
|
||||
|
|
@ -161,6 +168,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
|
|||
struct srb_iocb *abt_iocb;
|
||||
srb_t *sp;
|
||||
int rval = QLA_FUNCTION_FAILED;
|
||||
uint8_t bail;
|
||||
|
||||
/* ref: INIT for ABTS command */
|
||||
sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
|
||||
|
|
@ -168,6 +176,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
|
|||
if (!sp)
|
||||
return QLA_MEMORY_ALLOC_FAILED;
|
||||
|
||||
QLA_VHA_MARK_BUSY(vha, bail);
|
||||
abt_iocb = &sp->u.iocb_cmd;
|
||||
sp->type = SRB_ABT_CMD;
|
||||
sp->name = "abort";
|
||||
|
|
@ -1480,7 +1489,6 @@ static int qla_chk_secure_login(scsi_qla_host_t *vha, fc_port_t *fcport,
|
|||
ql_dbg(ql_dbg_disc, vha, 0x20ef,
|
||||
"%s %d %8phC EDIF: post DB_AUTH: AUTH needed\n",
|
||||
__func__, __LINE__, fcport->port_name);
|
||||
fcport->edif.app_started = 1;
|
||||
fcport->edif.app_sess_online = 1;
|
||||
|
||||
qla_edb_eventcreate(vha, VND_CMD_AUTH_STATE_NEEDED,
|
||||
|
|
@ -1763,8 +1771,16 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
|
|||
break;
|
||||
|
||||
case DSC_LOGIN_PEND:
|
||||
if (fcport->fw_login_state == DSC_LS_PLOGI_COMP)
|
||||
if (vha->hw->flags.edif_enabled)
|
||||
break;
|
||||
|
||||
if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0x2118,
|
||||
"%s %d %8phC post %s PRLI\n",
|
||||
__func__, __LINE__, fcport->port_name,
|
||||
NVME_TARGET(vha->hw, fcport) ? "NVME" : "FC");
|
||||
qla24xx_post_prli_work(vha, fcport);
|
||||
}
|
||||
break;
|
||||
|
||||
case DSC_UPD_FCPORT:
|
||||
|
|
@ -1818,7 +1834,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
|
|||
case RSCN_PORT_ADDR:
|
||||
fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
|
||||
if (fcport) {
|
||||
if (fcport->flags & FCF_FCP2_DEVICE) {
|
||||
if (fcport->flags & FCF_FCP2_DEVICE &&
|
||||
atomic_read(&fcport->state) == FCS_ONLINE) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0x2115,
|
||||
"Delaying session delete for FCP2 portid=%06x %8phC ",
|
||||
fcport->d_id.b24, fcport->port_name);
|
||||
|
|
@ -1850,7 +1867,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
|
|||
break;
|
||||
case RSCN_AREA_ADDR:
|
||||
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
||||
if (fcport->flags & FCF_FCP2_DEVICE)
|
||||
if (fcport->flags & FCF_FCP2_DEVICE &&
|
||||
atomic_read(&fcport->state) == FCS_ONLINE)
|
||||
continue;
|
||||
|
||||
if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) {
|
||||
|
|
@ -1861,7 +1879,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
|
|||
break;
|
||||
case RSCN_DOM_ADDR:
|
||||
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
||||
if (fcport->flags & FCF_FCP2_DEVICE)
|
||||
if (fcport->flags & FCF_FCP2_DEVICE &&
|
||||
atomic_read(&fcport->state) == FCS_ONLINE)
|
||||
continue;
|
||||
|
||||
if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) {
|
||||
|
|
@ -1873,7 +1892,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
|
|||
case RSCN_FAB_ADDR:
|
||||
default:
|
||||
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
||||
if (fcport->flags & FCF_FCP2_DEVICE)
|
||||
if (fcport->flags & FCF_FCP2_DEVICE &&
|
||||
atomic_read(&fcport->state) == FCS_ONLINE)
|
||||
continue;
|
||||
|
||||
fcport->scan_needed = 1;
|
||||
|
|
@ -2000,12 +2020,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
|
|||
struct srb_iocb *tm_iocb;
|
||||
srb_t *sp;
|
||||
int rval = QLA_FUNCTION_FAILED;
|
||||
uint8_t bail;
|
||||
|
||||
/* ref: INIT */
|
||||
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
|
||||
if (!sp)
|
||||
goto done;
|
||||
|
||||
QLA_VHA_MARK_BUSY(vha, bail);
|
||||
sp->type = SRB_TM_CMD;
|
||||
sp->name = "tmf";
|
||||
qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha),
|
||||
|
|
@ -2124,6 +2146,13 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
|
|||
}
|
||||
|
||||
if (N2N_TOPO(vha->hw)) {
|
||||
if (ea->fcport->n2n_link_reset_cnt ==
|
||||
vha->hw->login_retry_count &&
|
||||
ea->fcport->flags & FCF_FCSP_DEVICE) {
|
||||
/* remote authentication app just started */
|
||||
ea->fcport->n2n_link_reset_cnt = 0;
|
||||
}
|
||||
|
||||
if (ea->fcport->n2n_link_reset_cnt <
|
||||
vha->hw->login_retry_count) {
|
||||
ea->fcport->n2n_link_reset_cnt++;
|
||||
|
|
@ -4509,6 +4538,8 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
|
|||
BIT_6) != 0;
|
||||
ql_dbg(ql_dbg_init, vha, 0x00bc, "FA-WWPN Support: %s.\n",
|
||||
(ha->flags.fawwpn_enabled) ? "enabled" : "disabled");
|
||||
/* Init_cb will be reused for other command(s). Save a backup copy of port_name */
|
||||
memcpy(ha->port_name, ha->init_cb->port_name, WWN_SIZE);
|
||||
}
|
||||
|
||||
/* ELS pass through payload is limit by frame size. */
|
||||
|
|
@ -5273,9 +5304,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
|
|||
INIT_LIST_HEAD(&fcport->edif.tx_sa_list);
|
||||
INIT_LIST_HEAD(&fcport->edif.rx_sa_list);
|
||||
|
||||
if (vha->e_dbell.db_flags == EDB_ACTIVE)
|
||||
fcport->edif.app_started = 1;
|
||||
|
||||
spin_lock_init(&fcport->edif.indx_list_lock);
|
||||
INIT_LIST_HEAD(&fcport->edif.edif_indx_list);
|
||||
|
||||
|
|
@ -5488,6 +5516,22 @@ static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha)
|
|||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
static void
|
||||
qla_reinitialize_link(scsi_qla_host_t *vha)
|
||||
{
|
||||
int rval;
|
||||
|
||||
atomic_set(&vha->loop_state, LOOP_DOWN);
|
||||
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
|
||||
rval = qla2x00_full_login_lip(vha);
|
||||
if (rval == QLA_SUCCESS) {
|
||||
ql_dbg(ql_dbg_disc, vha, 0xd050, "Link reinitialized\n");
|
||||
} else {
|
||||
ql_dbg(ql_dbg_disc, vha, 0xd051,
|
||||
"Link reinitialization failed (%d)\n", rval);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* qla2x00_configure_local_loop
|
||||
* Updates Fibre Channel Device Database with local loop devices.
|
||||
|
|
@ -5539,6 +5583,19 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
|
|||
spin_unlock_irqrestore(&vha->work_lock, flags);
|
||||
|
||||
if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
|
||||
u8 loop_map_entries = 0;
|
||||
int rc;
|
||||
|
||||
rc = qla2x00_get_fcal_position_map(vha, NULL,
|
||||
&loop_map_entries);
|
||||
if (rc == QLA_SUCCESS && loop_map_entries > 1) {
|
||||
/*
|
||||
* There are devices that are still not logged
|
||||
* in. Reinitialize to give them a chance.
|
||||
*/
|
||||
qla_reinitialize_link(vha);
|
||||
return QLA_FUNCTION_FAILED;
|
||||
}
|
||||
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
|
||||
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
|
||||
}
|
||||
|
|
@ -5767,8 +5824,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|||
if (atomic_read(&fcport->state) == FCS_ONLINE)
|
||||
return;
|
||||
|
||||
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
|
||||
|
||||
rport_ids.node_name = wwn_to_u64(fcport->node_name);
|
||||
rport_ids.port_name = wwn_to_u64(fcport->port_name);
|
||||
rport_ids.port_id = fcport->d_id.b.domain << 16 |
|
||||
|
|
@ -5869,7 +5924,6 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|||
qla2x00_reg_remote_port(vha, fcport);
|
||||
break;
|
||||
case MODE_TARGET:
|
||||
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
|
||||
if (!vha->vha_tgt.qla_tgt->tgt_stop &&
|
||||
!vha->vha_tgt.qla_tgt->tgt_stopped)
|
||||
qlt_fc_port_added(vha, fcport);
|
||||
|
|
@ -5887,6 +5941,8 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|||
if (NVME_TARGET(vha->hw, fcport))
|
||||
qla_nvme_register_remote(vha, fcport);
|
||||
|
||||
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
|
||||
|
||||
if (IS_IIDMA_CAPABLE(vha->hw) && vha->hw->flags.gpsc_supported) {
|
||||
if (fcport->id_changed) {
|
||||
fcport->id_changed = 0;
|
||||
|
|
@ -7197,6 +7253,9 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
|
|||
if (vha->flags.online) {
|
||||
qla2x00_abort_isp_cleanup(vha);
|
||||
|
||||
vha->dport_status |= DPORT_DIAG_CHIP_RESET_IN_PROGRESS;
|
||||
vha->dport_status &= ~DPORT_DIAG_IN_PROGRESS;
|
||||
|
||||
if (vha->hw->flags.port_isolated)
|
||||
return status;
|
||||
|
||||
|
|
@ -9657,6 +9716,12 @@ int qla2xxx_disable_port(struct Scsi_Host *host)
|
|||
|
||||
vha->hw->flags.port_isolated = 1;
|
||||
|
||||
if (qla2x00_isp_reg_stat(vha->hw)) {
|
||||
ql_log(ql_log_info, vha, 0x9006,
|
||||
"PCI/Register disconnect, exiting.\n");
|
||||
qla_pci_set_eeh_busy(vha);
|
||||
return FAILED;
|
||||
}
|
||||
if (qla2x00_chip_is_down(vha))
|
||||
return 0;
|
||||
|
||||
|
|
@ -9672,6 +9737,13 @@ int qla2xxx_enable_port(struct Scsi_Host *host)
|
|||
{
|
||||
scsi_qla_host_t *vha = shost_priv(host);
|
||||
|
||||
if (qla2x00_isp_reg_stat(vha->hw)) {
|
||||
ql_log(ql_log_info, vha, 0x9001,
|
||||
"PCI/Register disconnect, exiting.\n");
|
||||
qla_pci_set_eeh_busy(vha);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
vha->hw->flags.port_isolated = 0;
|
||||
/* Set the flag to 1, so that isp_abort can proceed */
|
||||
vha->flags.online = 1;
|
||||
|
|
|
|||
|
|
@ -2819,7 +2819,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
|
|||
sp->vha->qla_stats.control_requests++;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
qla2x00_els_dcmd2_iocb_timeout(void *data)
|
||||
{
|
||||
srb_t *sp = data;
|
||||
|
|
@ -2882,6 +2882,9 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
|
|||
sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name);
|
||||
|
||||
fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
|
||||
/* For edif, set logout on delete to ensure any residual key from FW is flushed.*/
|
||||
fcport->logout_on_delete = 1;
|
||||
fcport->chip_reset = vha->hw->base_qpair->chip_reset;
|
||||
|
||||
if (sp->flags & SRB_WAKEUP_ON_COMP)
|
||||
complete(&lio->u.els_plogi.comp);
|
||||
|
|
|
|||
|
|
@ -1354,9 +1354,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
|
|||
if (!vha->vp_idx) {
|
||||
if (ha->flags.fawwpn_enabled &&
|
||||
(ha->current_topology == ISP_CFG_F)) {
|
||||
void *wwpn = ha->init_cb->port_name;
|
||||
|
||||
memcpy(vha->port_name, wwpn, WWN_SIZE);
|
||||
memcpy(vha->port_name, ha->port_name, WWN_SIZE);
|
||||
fc_host_port_name(vha->host) =
|
||||
wwn_to_u64(vha->port_name);
|
||||
ql_dbg(ql_dbg_init + ql_dbg_verbose,
|
||||
|
|
@ -1761,6 +1759,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
|
|||
break;
|
||||
|
||||
case MBA_DPORT_DIAGNOSTICS:
|
||||
if ((mb[1] & 0xF) == AEN_DONE_DIAG_TEST_WITH_NOERR ||
|
||||
(mb[1] & 0xF) == AEN_DONE_DIAG_TEST_WITH_ERR)
|
||||
vha->dport_status &= ~DPORT_DIAG_IN_PROGRESS;
|
||||
ql_dbg(ql_dbg_async, vha, 0x5052,
|
||||
"D-Port Diagnostics: %04x %04x %04x %04x\n",
|
||||
mb[0], mb[1], mb[2], mb[3]);
|
||||
|
|
@ -2245,9 +2246,9 @@ qla24xx_els_ct_entry(scsi_qla_host_t *v, struct req_que *req,
|
|||
res = DID_ERROR << 16;
|
||||
}
|
||||
|
||||
if (logit) {
|
||||
if (sp->remap.remapped &&
|
||||
((u8 *)sp->remap.rsp.buf)[0] == ELS_LS_RJT) {
|
||||
if (sp->remap.remapped &&
|
||||
((u8 *)sp->remap.rsp.buf)[0] == ELS_LS_RJT) {
|
||||
if (logit) {
|
||||
ql_dbg(ql_dbg_user, vha, 0x503f,
|
||||
"%s IOCB Done LS_RJT hdl=%x comp_status=0x%x\n",
|
||||
type, sp->handle, comp_status);
|
||||
|
|
@ -2259,18 +2260,24 @@ qla24xx_els_ct_entry(scsi_qla_host_t *v, struct req_que *req,
|
|||
pkt)->total_byte_count),
|
||||
e->s_id[0], e->s_id[2], e->s_id[1],
|
||||
e->d_id[2], e->d_id[1], e->d_id[0]);
|
||||
} else {
|
||||
ql_log(ql_log_info, vha, 0x503f,
|
||||
"%s IOCB Done hdl=%x comp_status=0x%x\n",
|
||||
type, sp->handle, comp_status);
|
||||
ql_log(ql_log_info, vha, 0x503f,
|
||||
"subcode 1=0x%x subcode 2=0x%x bytes=0x%x %02x%02x%02x -> %02x%02x%02x\n",
|
||||
fw_status[1], fw_status[2],
|
||||
le32_to_cpu(((struct els_sts_entry_24xx *)
|
||||
pkt)->total_byte_count),
|
||||
e->s_id[0], e->s_id[2], e->s_id[1],
|
||||
e->d_id[2], e->d_id[1], e->d_id[0]);
|
||||
}
|
||||
if (sp->fcport && sp->fcport->flags & FCF_FCSP_DEVICE &&
|
||||
sp->type == SRB_ELS_CMD_HST_NOLOGIN) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911e,
|
||||
"%s rcv reject. Sched delete\n", __func__);
|
||||
qlt_schedule_sess_for_deletion(sp->fcport);
|
||||
}
|
||||
} else if (logit) {
|
||||
ql_log(ql_log_info, vha, 0x503f,
|
||||
"%s IOCB Done hdl=%x comp_status=0x%x\n",
|
||||
type, sp->handle, comp_status);
|
||||
ql_log(ql_log_info, vha, 0x503f,
|
||||
"subcode 1=0x%x subcode 2=0x%x bytes=0x%x %02x%02x%02x -> %02x%02x%02x\n",
|
||||
fw_status[1], fw_status[2],
|
||||
le32_to_cpu(((struct els_sts_entry_24xx *)
|
||||
pkt)->total_byte_count),
|
||||
e->s_id[0], e->s_id[2], e->s_id[1],
|
||||
e->d_id[2], e->d_id[1], e->d_id[0]);
|
||||
}
|
||||
}
|
||||
goto els_ct_done;
|
||||
|
|
@ -2639,7 +2646,7 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
|||
}
|
||||
|
||||
if (unlikely(logit))
|
||||
ql_log(ql_dbg_io, fcport->vha, 0x5060,
|
||||
ql_dbg(ql_dbg_io, fcport->vha, 0x5060,
|
||||
"NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n",
|
||||
sp->name, sp->handle, comp_status,
|
||||
fd->transferred_length, le32_to_cpu(sts->residual_len),
|
||||
|
|
@ -3426,6 +3433,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
|
|||
case CS_PORT_UNAVAILABLE:
|
||||
case CS_TIMEOUT:
|
||||
case CS_RESET:
|
||||
case CS_EDIF_INV_REQ:
|
||||
|
||||
/*
|
||||
* We are going to have the fc class block the rport
|
||||
|
|
@ -3496,7 +3504,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
|
|||
|
||||
out:
|
||||
if (logit)
|
||||
ql_log(ql_dbg_io, fcport->vha, 0x3022,
|
||||
ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
|
||||
"FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
|
||||
comp_status, scsi_status, res, vha->host_no,
|
||||
cp->device->id, cp->device->lun, fcport->d_id.b.domain,
|
||||
|
|
@ -3712,12 +3720,11 @@ void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
|
|||
* Return: 0 all iocbs has arrived, xx- all iocbs have not arrived.
|
||||
*/
|
||||
static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
|
||||
struct rsp_que *rsp, response_t *pkt)
|
||||
struct rsp_que *rsp, response_t *pkt, u32 rsp_q_in)
|
||||
{
|
||||
int start_pkt_ring_index, end_pkt_ring_index, n_ring_index;
|
||||
response_t *end_pkt;
|
||||
int start_pkt_ring_index;
|
||||
u32 iocb_cnt = 0;
|
||||
int rc = 0;
|
||||
u32 rsp_q_in;
|
||||
|
||||
if (pkt->entry_count == 1)
|
||||
return rc;
|
||||
|
|
@ -3728,34 +3735,18 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
|
|||
else
|
||||
start_pkt_ring_index = rsp->ring_index - 1;
|
||||
|
||||
if ((start_pkt_ring_index + pkt->entry_count) >= rsp->length)
|
||||
end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count -
|
||||
rsp->length - 1;
|
||||
if (rsp_q_in < start_pkt_ring_index)
|
||||
/* q in ptr is wrapped */
|
||||
iocb_cnt = rsp->length - start_pkt_ring_index + rsp_q_in;
|
||||
else
|
||||
end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count - 1;
|
||||
iocb_cnt = rsp_q_in - start_pkt_ring_index;
|
||||
|
||||
end_pkt = rsp->ring + end_pkt_ring_index;
|
||||
|
||||
/* next pkt = end_pkt + 1 */
|
||||
n_ring_index = end_pkt_ring_index + 1;
|
||||
if (n_ring_index >= rsp->length)
|
||||
n_ring_index = 0;
|
||||
|
||||
rsp_q_in = rsp->qpair->use_shadow_reg ? *rsp->in_ptr :
|
||||
rd_reg_dword(rsp->rsp_q_in);
|
||||
|
||||
/* rsp_q_in is either wrapped or pointing beyond endpkt */
|
||||
if ((rsp_q_in < start_pkt_ring_index && rsp_q_in < n_ring_index) ||
|
||||
rsp_q_in >= n_ring_index)
|
||||
/* all IOCBs arrived. */
|
||||
rc = 0;
|
||||
else
|
||||
if (iocb_cnt < pkt->entry_count)
|
||||
rc = -EIO;
|
||||
|
||||
ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x5091,
|
||||
"%s - ring %p pkt %p end pkt %p entry count %#x rsp_q_in %d rc %d\n",
|
||||
__func__, rsp->ring, pkt, end_pkt, pkt->entry_count,
|
||||
rsp_q_in, rc);
|
||||
ql_dbg(ql_dbg_init, vha, 0x5091,
|
||||
"%s - ring %p pkt %p entry count %d iocb_cnt %d rsp_q_in %d rc %d\n",
|
||||
__func__, rsp->ring, pkt, pkt->entry_count, iocb_cnt, rsp_q_in, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -3772,6 +3763,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
|||
struct qla_hw_data *ha = vha->hw;
|
||||
struct purex_entry_24xx *purex_entry;
|
||||
struct purex_item *pure_item;
|
||||
u16 rsp_in = 0, cur_ring_index;
|
||||
int follow_inptr, is_shadow_hba;
|
||||
|
||||
if (!ha->flags.fw_started)
|
||||
return;
|
||||
|
|
@ -3781,8 +3774,27 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
|||
qla_cpu_update(rsp->qpair, smp_processor_id());
|
||||
}
|
||||
|
||||
while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
|
||||
#define __update_rsp_in(_update, _is_shadow_hba, _rsp, _rsp_in) \
|
||||
do { \
|
||||
if (_update) { \
|
||||
_rsp_in = _is_shadow_hba ? *(_rsp)->in_ptr : \
|
||||
rd_reg_dword_relaxed((_rsp)->rsp_q_in); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
is_shadow_hba = IS_SHADOW_REG_CAPABLE(ha);
|
||||
follow_inptr = is_shadow_hba ? ql2xrspq_follow_inptr :
|
||||
ql2xrspq_follow_inptr_legacy;
|
||||
|
||||
__update_rsp_in(follow_inptr, is_shadow_hba, rsp, rsp_in);
|
||||
|
||||
while ((likely(follow_inptr &&
|
||||
rsp->ring_index != rsp_in &&
|
||||
rsp->ring_ptr->signature != RESPONSE_PROCESSED)) ||
|
||||
(!follow_inptr &&
|
||||
rsp->ring_ptr->signature != RESPONSE_PROCESSED)) {
|
||||
pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
|
||||
cur_ring_index = rsp->ring_index;
|
||||
|
||||
rsp->ring_index++;
|
||||
if (rsp->ring_index == rsp->length) {
|
||||
|
|
@ -3894,6 +3906,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
|||
}
|
||||
pure_item = qla27xx_copy_fpin_pkt(vha,
|
||||
(void **)&pkt, &rsp);
|
||||
__update_rsp_in(follow_inptr, is_shadow_hba,
|
||||
rsp, rsp_in);
|
||||
if (!pure_item)
|
||||
break;
|
||||
qla24xx_queue_purex_item(vha, pure_item,
|
||||
|
|
@ -3901,7 +3915,17 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
|||
break;
|
||||
|
||||
case ELS_AUTH_ELS:
|
||||
if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt)) {
|
||||
if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt, rsp_in)) {
|
||||
/*
|
||||
* ring_ptr and ring_index were
|
||||
* pre-incremented above. Reset them
|
||||
* back to current. Wait for next
|
||||
* interrupt with all IOCBs to arrive
|
||||
* and re-process.
|
||||
*/
|
||||
rsp->ring_ptr = (response_t *)pkt;
|
||||
rsp->ring_index = cur_ring_index;
|
||||
|
||||
ql_dbg(ql_dbg_init, vha, 0x5091,
|
||||
"Defer processing ELS opcode %#x...\n",
|
||||
purex_entry->els_frame_payload[3]);
|
||||
|
|
@ -4420,16 +4444,12 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
|||
}
|
||||
|
||||
/* Enable MSI-X vector for response queue update for queue 0 */
|
||||
if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
|
||||
if (ha->msixbase && ha->mqiobase &&
|
||||
(ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
|
||||
ql2xmqsupport))
|
||||
ha->mqenable = 1;
|
||||
} else
|
||||
if (ha->mqiobase &&
|
||||
(ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
|
||||
ql2xmqsupport))
|
||||
ha->mqenable = 1;
|
||||
if (IS_MQUE_CAPABLE(ha) &&
|
||||
(ha->msixbase && ha->mqiobase && ha->max_qpairs))
|
||||
ha->mqenable = 1;
|
||||
else
|
||||
ha->mqenable = 0;
|
||||
|
||||
ql_dbg(ql_dbg_multiq, vha, 0xc005,
|
||||
"mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
|
||||
ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
|
||||
|
|
|
|||
|
|
@ -238,6 +238,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
|
|||
ql_dbg(ql_dbg_mbx, vha, 0x1112,
|
||||
"mbox[%d]<-0x%04x\n", cnt, *iptr);
|
||||
wrt_reg_word(optr, *iptr);
|
||||
} else {
|
||||
wrt_reg_word(optr, 0);
|
||||
}
|
||||
|
||||
mboxes >>= 1;
|
||||
|
|
@ -274,6 +276,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
|
|||
atomic_inc(&ha->num_pend_mbx_stage3);
|
||||
if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
|
||||
mcp->tov * HZ)) {
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x117a,
|
||||
"cmd=%x Timeout.\n", command);
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
if (chip_reset != ha->chip_reset) {
|
||||
eeh_delay = ha->flags.eeh_busy ? 1 : 0;
|
||||
|
||||
|
|
@ -286,12 +294,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
|
|||
rval = QLA_ABORTED;
|
||||
goto premature_exit;
|
||||
}
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x117a,
|
||||
"cmd=%x Timeout.\n", command);
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
} else if (ha->flags.purge_mbox ||
|
||||
chip_reset != ha->chip_reset) {
|
||||
eeh_delay = ha->flags.eeh_busy ? 1 : 0;
|
||||
|
|
@ -3066,7 +3068,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
|
|||
* Kernel context.
|
||||
*/
|
||||
int
|
||||
qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
|
||||
qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map,
|
||||
u8 *num_entries)
|
||||
{
|
||||
int rval;
|
||||
mbx_cmd_t mc;
|
||||
|
|
@ -3106,6 +3109,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
|
|||
|
||||
if (pos_map)
|
||||
memcpy(pos_map, pmap, FCAL_MAP_SIZE);
|
||||
if (num_entries)
|
||||
*num_entries = pmap[0];
|
||||
}
|
||||
dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
|
||||
|
||||
|
|
@ -6471,6 +6476,54 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
|
|||
return rval;
|
||||
}
|
||||
|
||||
int
|
||||
qla26xx_dport_diagnostics_v2(scsi_qla_host_t *vha,
|
||||
struct qla_dport_diag_v2 *dd, mbx_cmd_t *mcp)
|
||||
{
|
||||
int rval;
|
||||
dma_addr_t dd_dma;
|
||||
uint size = sizeof(dd->buf);
|
||||
uint16_t options = dd->options;
|
||||
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f,
|
||||
"Entered %s.\n", __func__);
|
||||
|
||||
dd_dma = dma_map_single(&vha->hw->pdev->dev,
|
||||
dd->buf, size, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(&vha->hw->pdev->dev, dd_dma)) {
|
||||
ql_log(ql_log_warn, vha, 0x1194,
|
||||
"Failed to map dma buffer.\n");
|
||||
return QLA_MEMORY_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
memset(dd->buf, 0, size);
|
||||
|
||||
mcp->mb[0] = MBC_DPORT_DIAGNOSTICS;
|
||||
mcp->mb[1] = options;
|
||||
mcp->mb[2] = MSW(LSD(dd_dma));
|
||||
mcp->mb[3] = LSW(LSD(dd_dma));
|
||||
mcp->mb[6] = MSW(MSD(dd_dma));
|
||||
mcp->mb[7] = LSW(MSD(dd_dma));
|
||||
mcp->mb[8] = size;
|
||||
mcp->out_mb = MBX_8 | MBX_7 | MBX_6 | MBX_3 | MBX_2 | MBX_1 | MBX_0;
|
||||
mcp->in_mb = MBX_3 | MBX_2 | MBX_1 | MBX_0;
|
||||
mcp->buf_size = size;
|
||||
mcp->flags = MBX_DMA_IN;
|
||||
mcp->tov = MBX_TOV_SECONDS * 4;
|
||||
rval = qla2x00_mailbox_command(vha, mcp);
|
||||
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval);
|
||||
} else {
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196,
|
||||
"Done %s.\n", __func__);
|
||||
}
|
||||
|
||||
dma_unmap_single(&vha->hw->pdev->dev, dd_dma, size, DMA_FROM_DEVICE);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static void qla2x00_async_mb_sp_done(srb_t *sp, int res)
|
||||
{
|
||||
sp->u.iocb_cmd.u.mbx.rc = res;
|
||||
|
|
|
|||
|
|
@ -166,9 +166,13 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
|
|||
int ret = QLA_SUCCESS;
|
||||
fc_port_t *fcport;
|
||||
|
||||
if (vha->hw->flags.edif_enabled)
|
||||
if (vha->hw->flags.edif_enabled) {
|
||||
if (DBELL_ACTIVE(vha))
|
||||
qla2x00_post_aen_work(vha, FCH_EVT_VENDOR_UNIQUE,
|
||||
FCH_EVT_VENDOR_UNIQUE_VPORT_DOWN);
|
||||
/* delete sessions and flush sa_indexes */
|
||||
qla2x00_wait_for_sess_deletion(vha);
|
||||
}
|
||||
|
||||
if (vha->hw->flags.fw_started)
|
||||
ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
|
||||
|
|
|
|||
|
|
@ -37,11 +37,6 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport)
|
|||
(fcport->nvme_flag & NVME_FLAG_REGISTERED))
|
||||
return 0;
|
||||
|
||||
if (atomic_read(&fcport->state) == FCS_ONLINE)
|
||||
return 0;
|
||||
|
||||
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
|
||||
|
||||
fcport->nvme_flag &= ~NVME_FLAG_RESETTING;
|
||||
|
||||
memset(&req, 0, sizeof(struct nvme_fc_port_info));
|
||||
|
|
|
|||
|
|
@ -333,6 +333,21 @@ MODULE_PARM_DESC(ql2xabts_wait_nvme,
|
|||
"To wait for ABTS response on I/O timeouts for NVMe. (default: 1)");
|
||||
|
||||
|
||||
u32 ql2xdelay_before_pci_error_handling = 5;
|
||||
module_param(ql2xdelay_before_pci_error_handling, uint, 0644);
|
||||
MODULE_PARM_DESC(ql2xdelay_before_pci_error_handling,
|
||||
"Number of seconds delayed before qla begin PCI error self-handling (default: 5).\n");
|
||||
|
||||
int ql2xrspq_follow_inptr = 1;
|
||||
module_param(ql2xrspq_follow_inptr, int, 0644);
|
||||
MODULE_PARM_DESC(ql2xrspq_follow_inptr,
|
||||
"Follow RSP IN pointer for RSP updates for HBAs 27xx and newer (default: 1).");
|
||||
|
||||
int ql2xrspq_follow_inptr_legacy = 1;
|
||||
module_param(ql2xrspq_follow_inptr_legacy, int, 0644);
|
||||
MODULE_PARM_DESC(ql2xrspq_follow_inptr_legacy,
|
||||
"Follow RSP IN pointer for RSP updates for HBAs older than 27XX. (default: 1).");
|
||||
|
||||
static void qla2x00_clear_drv_active(struct qla_hw_data *);
|
||||
static void qla2x00_free_device(scsi_qla_host_t *);
|
||||
static int qla2xxx_map_queues(struct Scsi_Host *shost);
|
||||
|
|
@ -1337,21 +1352,20 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|||
/*
|
||||
* Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED.
|
||||
*/
|
||||
int
|
||||
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
|
||||
uint64_t l, enum nexus_wait_type type)
|
||||
static int
|
||||
__qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t,
|
||||
uint64_t l, enum nexus_wait_type type)
|
||||
{
|
||||
int cnt, match, status;
|
||||
unsigned long flags;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct req_que *req;
|
||||
scsi_qla_host_t *vha = qpair->vha;
|
||||
struct req_que *req = qpair->req;
|
||||
srb_t *sp;
|
||||
struct scsi_cmnd *cmd;
|
||||
|
||||
status = QLA_SUCCESS;
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
req = vha->req;
|
||||
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
|
||||
for (cnt = 1; status == QLA_SUCCESS &&
|
||||
cnt < req->num_outstanding_cmds; cnt++) {
|
||||
sp = req->outstanding_cmds[cnt];
|
||||
|
|
@ -1378,15 +1392,35 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
|
|||
if (!match)
|
||||
continue;
|
||||
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
||||
status = qla2x00_eh_wait_on_command(cmd);
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
|
||||
uint64_t l, enum nexus_wait_type type)
|
||||
{
|
||||
struct qla_qpair *qpair;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
int i, status = QLA_SUCCESS;
|
||||
|
||||
status = __qla2x00_eh_wait_for_pending_commands(ha->base_qpair, t, l,
|
||||
type);
|
||||
for (i = 0; status == QLA_SUCCESS && i < ha->max_qpairs; i++) {
|
||||
qpair = ha->queue_pair_map[i];
|
||||
if (!qpair)
|
||||
continue;
|
||||
status = __qla2x00_eh_wait_for_pending_commands(qpair, t, l,
|
||||
type);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static char *reset_errors[] = {
|
||||
"HBA not online",
|
||||
"HBA not ready",
|
||||
|
|
@ -1420,7 +1454,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
|||
return err;
|
||||
|
||||
if (fcport->deleted)
|
||||
return SUCCESS;
|
||||
return FAILED;
|
||||
|
||||
ql_log(ql_log_info, vha, 0x8009,
|
||||
"DEVICE RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", vha->host_no,
|
||||
|
|
@ -1488,7 +1522,7 @@ qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
|
|||
return err;
|
||||
|
||||
if (fcport->deleted)
|
||||
return SUCCESS;
|
||||
return FAILED;
|
||||
|
||||
ql_log(ql_log_info, vha, 0x8009,
|
||||
"TARGET RESET ISSUED nexus=%ld:%d cmd=%p.\n", vha->host_no,
|
||||
|
|
@ -5472,7 +5506,7 @@ qla2x00_do_work(struct scsi_qla_host *vha)
|
|||
e->u.fcport.fcport, false);
|
||||
break;
|
||||
case QLA_EVT_SA_REPLACE:
|
||||
qla24xx_issue_sa_replace_iocb(vha, e);
|
||||
rc = qla24xx_issue_sa_replace_iocb(vha, e);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -7238,6 +7272,44 @@ static void qla_heart_beat(struct scsi_qla_host *vha, u16 dpc_started)
|
|||
}
|
||||
}
|
||||
|
||||
static void qla_wind_down_chip(scsi_qla_host_t *vha)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
if (!ha->flags.eeh_busy)
|
||||
return;
|
||||
if (ha->pci_error_state)
|
||||
/* system is trying to recover */
|
||||
return;
|
||||
|
||||
/*
|
||||
* Current system is not handling PCIE error. At this point, this is
|
||||
* best effort to wind down the adapter.
|
||||
*/
|
||||
if (time_after_eq(jiffies, ha->eeh_jif + ql2xdelay_before_pci_error_handling * HZ) &&
|
||||
!ha->flags.eeh_flush) {
|
||||
ql_log(ql_log_info, vha, 0x9009,
|
||||
"PCI Error detected, attempting to reset hardware.\n");
|
||||
|
||||
ha->isp_ops->reset_chip(vha);
|
||||
ha->isp_ops->disable_intrs(ha);
|
||||
|
||||
ha->flags.eeh_flush = EEH_FLUSH_RDY;
|
||||
ha->eeh_jif = jiffies;
|
||||
|
||||
} else if (ha->flags.eeh_flush == EEH_FLUSH_RDY &&
|
||||
time_after_eq(jiffies, ha->eeh_jif + 5 * HZ)) {
|
||||
pci_clear_master(ha->pdev);
|
||||
|
||||
/* flush all command */
|
||||
qla2x00_abort_isp_cleanup(vha);
|
||||
ha->flags.eeh_flush = EEH_FLUSH_DONE;
|
||||
|
||||
ql_log(ql_log_info, vha, 0x900a,
|
||||
"PCI Error handling complete, all IOs aborted.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* qla2x00_timer
|
||||
*
|
||||
|
|
@ -7261,6 +7333,8 @@ qla2x00_timer(struct timer_list *t)
|
|||
fc_port_t *fcport = NULL;
|
||||
|
||||
if (ha->flags.eeh_busy) {
|
||||
qla_wind_down_chip(vha);
|
||||
|
||||
ql_dbg(ql_dbg_timer, vha, 0x6000,
|
||||
"EEH = %d, restarting timer.\n",
|
||||
ha->flags.eeh_busy);
|
||||
|
|
@ -7841,6 +7915,9 @@ void qla_pci_set_eeh_busy(struct scsi_qla_host *vha)
|
|||
|
||||
spin_lock_irqsave(&base_vha->work_lock, flags);
|
||||
if (!ha->flags.eeh_busy) {
|
||||
ha->eeh_jif = jiffies;
|
||||
ha->flags.eeh_flush = 0;
|
||||
|
||||
ha->flags.eeh_busy = 1;
|
||||
do_cleanup = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -981,22 +981,6 @@ void qlt_free_session_done(struct work_struct *work)
|
|||
sess->send_els_logo);
|
||||
|
||||
if (!IS_SW_RESV_ADDR(sess->d_id)) {
|
||||
if (ha->flags.edif_enabled &&
|
||||
(!own || own->iocb.u.isp24.status_subcode == ELS_PLOGI)) {
|
||||
sess->edif.authok = 0;
|
||||
if (!ha->flags.host_shutting_down) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911e,
|
||||
"%s wwpn %8phC calling qla2x00_release_all_sadb\n",
|
||||
__func__, sess->port_name);
|
||||
qla2x00_release_all_sadb(vha, sess);
|
||||
} else {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911e,
|
||||
"%s bypassing release_all_sadb\n",
|
||||
__func__);
|
||||
}
|
||||
qla_edif_clear_appdata(vha, sess);
|
||||
qla_edif_sess_down(vha, sess);
|
||||
}
|
||||
qla2x00_mark_device_lost(vha, sess, 0);
|
||||
|
||||
if (sess->send_els_logo) {
|
||||
|
|
@ -1042,6 +1026,25 @@ void qlt_free_session_done(struct work_struct *work)
|
|||
sess->nvme_flag |= NVME_FLAG_DELETING;
|
||||
qla_nvme_unregister_remote_port(sess);
|
||||
}
|
||||
|
||||
if (ha->flags.edif_enabled &&
|
||||
(!own || (own &&
|
||||
own->iocb.u.isp24.status_subcode == ELS_PLOGI))) {
|
||||
sess->edif.authok = 0;
|
||||
if (!ha->flags.host_shutting_down) {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911e,
|
||||
"%s wwpn %8phC calling qla2x00_release_all_sadb\n",
|
||||
__func__, sess->port_name);
|
||||
qla2x00_release_all_sadb(vha, sess);
|
||||
} else {
|
||||
ql_dbg(ql_dbg_edif, vha, 0x911e,
|
||||
"%s bypassing release_all_sadb\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
qla_edif_clear_appdata(vha, sess);
|
||||
qla_edif_sess_down(vha, sess);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
/*
|
||||
* Driver version
|
||||
*/
|
||||
#define QLA2XXX_VERSION "10.02.07.400-k"
|
||||
#define QLA2XXX_VERSION "10.02.07.800-k"
|
||||
|
||||
#define QLA_DRIVER_MAJOR_VER 10
|
||||
#define QLA_DRIVER_MINOR_VER 2
|
||||
#define QLA_DRIVER_PATCH_VER 7
|
||||
#define QLA_DRIVER_BETA_VER 400
|
||||
#define QLA_DRIVER_BETA_VER 800
|
||||
|
|
|
|||
|
|
@ -463,14 +463,12 @@ static void scsi_report_sense(struct scsi_device *sdev,
|
|||
evt_type = SDEV_EVT_LUN_CHANGE_REPORTED;
|
||||
scsi_report_lun_change(sdev);
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"Warning! Received an indication that the "
|
||||
"LUN assignments on this target have "
|
||||
"changed. The Linux SCSI layer does not "
|
||||
"automatically remap LUN assignments.\n");
|
||||
} else if (sshdr->asc == 0x3f)
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"Warning! Received an indication that the "
|
||||
"operating parameters on this target have "
|
||||
"Operating parameters on this target have "
|
||||
"changed. The Linux SCSI layer does not "
|
||||
"automatically adjust these parameters.\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -75,13 +75,6 @@ int scsi_init_sense_cache(struct Scsi_Host *shost)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* When to reinvoke queueing after a resource shortage. It's 3 msecs to
|
||||
* not change behaviour from the previous unplug mechanism, experimentation
|
||||
* may prove this needs changing.
|
||||
*/
|
||||
#define SCSI_QUEUE_DELAY 3
|
||||
|
||||
static void
|
||||
scsi_set_blocked(struct scsi_cmnd *cmd, int reason)
|
||||
{
|
||||
|
|
@ -1648,6 +1641,13 @@ static void scsi_mq_put_budget(struct request_queue *q, int budget_token)
|
|||
sbitmap_put(&sdev->budget_map, budget_token);
|
||||
}
|
||||
|
||||
/*
|
||||
* When to reinvoke queueing after a resource shortage. It's 3 msecs to
|
||||
* not change behaviour from the previous unplug mechanism, experimentation
|
||||
* may prove this needs changing.
|
||||
*/
|
||||
#define SCSI_QUEUE_DELAY 3
|
||||
|
||||
static int scsi_mq_get_budget(struct request_queue *q)
|
||||
{
|
||||
struct scsi_device *sdev = q->queuedata;
|
||||
|
|
|
|||
|
|
@ -1980,7 +1980,7 @@ static void __iscsi_unbind_session(struct work_struct *work)
|
|||
scsi_remove_target(&session->dev);
|
||||
|
||||
if (session->ida_used)
|
||||
ida_simple_remove(&iscsi_sess_ida, target_id);
|
||||
ida_free(&iscsi_sess_ida, target_id);
|
||||
|
||||
unbind_session_exit:
|
||||
iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
|
||||
|
|
@ -2049,7 +2049,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
|
|||
return -ENOMEM;
|
||||
|
||||
if (target_id == ISCSI_MAX_TARGET) {
|
||||
id = ida_simple_get(&iscsi_sess_ida, 0, 0, GFP_KERNEL);
|
||||
id = ida_alloc(&iscsi_sess_ida, GFP_KERNEL);
|
||||
|
||||
if (id < 0) {
|
||||
iscsi_cls_session_printk(KERN_ERR, session,
|
||||
|
|
@ -2088,7 +2088,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
|
|||
device_del(&session->dev);
|
||||
release_ida:
|
||||
if (session->ida_used)
|
||||
ida_simple_remove(&iscsi_sess_ida, session->target_id);
|
||||
ida_free(&iscsi_sess_ida, session->target_id);
|
||||
destroy_wq:
|
||||
destroy_workqueue(session->workq);
|
||||
return err;
|
||||
|
|
@ -2143,8 +2143,6 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
|
|||
return 0;
|
||||
|
||||
iscsi_remove_conn(iscsi_dev_to_conn(dev));
|
||||
iscsi_put_conn(iscsi_dev_to_conn(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2264,17 +2262,19 @@ static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn,
|
|||
}
|
||||
}
|
||||
|
||||
static int iscsi_if_stop_conn(struct iscsi_transport *transport,
|
||||
struct iscsi_uevent *ev)
|
||||
static int iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag)
|
||||
{
|
||||
int flag = ev->u.stop_conn.flag;
|
||||
struct iscsi_cls_conn *conn;
|
||||
|
||||
conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
|
||||
if (!conn)
|
||||
return -EINVAL;
|
||||
|
||||
ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop.\n");
|
||||
/*
|
||||
* For offload, iscsid may not know about the ep like when iscsid is
|
||||
* restarted or for kernel based session shutdown iscsid is not even
|
||||
* up. For these cases, we do the disconnect now.
|
||||
*/
|
||||
mutex_lock(&conn->ep_mutex);
|
||||
if (conn->ep)
|
||||
iscsi_if_disconnect_bound_ep(conn, conn->ep, true);
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
|
||||
/*
|
||||
* If this is a termination we have to call stop_conn with that flag
|
||||
* so the correct states get set. If we haven't run the work yet try to
|
||||
|
|
@ -2284,16 +2284,6 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
|
|||
cancel_work_sync(&conn->cleanup_work);
|
||||
iscsi_stop_conn(conn, flag);
|
||||
} else {
|
||||
/*
|
||||
* For offload, when iscsid is restarted it won't know about
|
||||
* existing endpoints so it can't do a ep_disconnect. We clean
|
||||
* it up here for userspace.
|
||||
*/
|
||||
mutex_lock(&conn->ep_mutex);
|
||||
if (conn->ep)
|
||||
iscsi_if_disconnect_bound_ep(conn, conn->ep, true);
|
||||
mutex_unlock(&conn->ep_mutex);
|
||||
|
||||
/*
|
||||
* Figure out if it was the kernel or userspace initiating this.
|
||||
*/
|
||||
|
|
@ -2349,6 +2339,55 @@ static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
|
|||
ISCSI_DBG_TRANS_CONN(conn, "cleanup done.\n");
|
||||
}
|
||||
|
||||
static int iscsi_iter_force_destroy_conn_fn(struct device *dev, void *data)
|
||||
{
|
||||
struct iscsi_transport *transport;
|
||||
struct iscsi_cls_conn *conn;
|
||||
|
||||
if (!iscsi_is_conn_dev(dev))
|
||||
return 0;
|
||||
|
||||
conn = iscsi_dev_to_conn(dev);
|
||||
transport = conn->transport;
|
||||
|
||||
if (READ_ONCE(conn->state) != ISCSI_CONN_DOWN)
|
||||
iscsi_if_stop_conn(conn, STOP_CONN_TERM);
|
||||
|
||||
transport->destroy_conn(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iscsi_force_destroy_session - destroy a session from the kernel
|
||||
* @session: session to destroy
|
||||
*
|
||||
* Force the destruction of a session from the kernel. This should only be
|
||||
* used when userspace is no longer running during system shutdown.
|
||||
*/
|
||||
void iscsi_force_destroy_session(struct iscsi_cls_session *session)
|
||||
{
|
||||
struct iscsi_transport *transport = session->transport;
|
||||
unsigned long flags;
|
||||
|
||||
WARN_ON_ONCE(system_state == SYSTEM_RUNNING);
|
||||
|
||||
spin_lock_irqsave(&sesslock, flags);
|
||||
if (list_empty(&session->sess_list)) {
|
||||
spin_unlock_irqrestore(&sesslock, flags);
|
||||
/*
|
||||
* Conn/ep is already freed. Session is being torn down via
|
||||
* async path. For shutdown we don't care about it so return.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&sesslock, flags);
|
||||
|
||||
device_for_each_child(&session->dev, NULL,
|
||||
iscsi_iter_force_destroy_conn_fn);
|
||||
transport->destroy_session(session);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_force_destroy_session);
|
||||
|
||||
void iscsi_free_session(struct iscsi_cls_session *session)
|
||||
{
|
||||
ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
|
||||
|
|
@ -3720,7 +3759,12 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
|
|||
case ISCSI_UEVENT_DESTROY_CONN:
|
||||
return iscsi_if_destroy_conn(transport, ev);
|
||||
case ISCSI_UEVENT_STOP_CONN:
|
||||
return iscsi_if_stop_conn(transport, ev);
|
||||
conn = iscsi_conn_lookup(ev->u.stop_conn.sid,
|
||||
ev->u.stop_conn.cid);
|
||||
if (!conn)
|
||||
return -EINVAL;
|
||||
|
||||
return iscsi_if_stop_conn(conn, ev->u.stop_conn.flag);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -4812,7 +4856,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_register_transport);
|
||||
|
||||
int iscsi_unregister_transport(struct iscsi_transport *tt)
|
||||
void iscsi_unregister_transport(struct iscsi_transport *tt)
|
||||
{
|
||||
struct iscsi_internal *priv;
|
||||
unsigned long flags;
|
||||
|
|
@ -4835,8 +4879,6 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
|
|||
sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
|
||||
device_unregister(&priv->dev);
|
||||
mutex_unlock(&rx_queue_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ static void sd_config_discard(struct scsi_disk *, unsigned int);
|
|||
static void sd_config_write_same(struct scsi_disk *);
|
||||
static int sd_revalidate_disk(struct gendisk *);
|
||||
static void sd_unlock_native_capacity(struct gendisk *disk);
|
||||
static void sd_start_done_work(struct work_struct *work);
|
||||
static int sd_probe(struct device *);
|
||||
static int sd_remove(struct device *);
|
||||
static void sd_shutdown(struct device *);
|
||||
|
|
@ -3463,6 +3464,7 @@ static int sd_probe(struct device *dev)
|
|||
sdkp->max_retries = SD_MAX_RETRIES;
|
||||
atomic_set(&sdkp->openers, 0);
|
||||
atomic_set(&sdkp->device->ioerr_cnt, 0);
|
||||
INIT_WORK(&sdkp->start_done_work, sd_start_done_work);
|
||||
|
||||
if (!sdp->request_queue->rq_timeout) {
|
||||
if (sdp->type != TYPE_MOD)
|
||||
|
|
@ -3585,12 +3587,69 @@ static void scsi_disk_release(struct device *dev)
|
|||
kfree(sdkp);
|
||||
}
|
||||
|
||||
/* Process sense data after a START command finished. */
|
||||
static void sd_start_done_work(struct work_struct *work)
|
||||
{
|
||||
struct scsi_disk *sdkp = container_of(work, typeof(*sdkp),
|
||||
start_done_work);
|
||||
struct scsi_sense_hdr sshdr;
|
||||
int res = sdkp->start_result;
|
||||
|
||||
if (res == 0)
|
||||
return;
|
||||
|
||||
sd_print_result(sdkp, "Start/Stop Unit failed", res);
|
||||
|
||||
if (res < 0)
|
||||
return;
|
||||
|
||||
if (scsi_normalize_sense(sdkp->start_sense_buffer,
|
||||
sdkp->start_sense_len, &sshdr))
|
||||
sd_print_sense_hdr(sdkp, &sshdr);
|
||||
}
|
||||
|
||||
/* A START command finished. May be called from interrupt context. */
|
||||
static void sd_start_done(struct request *req, blk_status_t status)
|
||||
{
|
||||
const struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req);
|
||||
struct scsi_disk *sdkp = scsi_disk(req->q->disk);
|
||||
|
||||
sdkp->start_result = scmd->result;
|
||||
WARN_ON_ONCE(scmd->sense_len > SCSI_SENSE_BUFFERSIZE);
|
||||
sdkp->start_sense_len = scmd->sense_len;
|
||||
memcpy(sdkp->start_sense_buffer, scmd->sense_buffer,
|
||||
ARRAY_SIZE(sdkp->start_sense_buffer));
|
||||
WARN_ON_ONCE(!schedule_work(&sdkp->start_done_work));
|
||||
}
|
||||
|
||||
/* Submit a START command asynchronously. */
|
||||
static int sd_submit_start(struct scsi_disk *sdkp, u8 cmd[], u8 cmd_len)
|
||||
{
|
||||
struct scsi_device *sdev = sdkp->device;
|
||||
struct request_queue *q = sdev->request_queue;
|
||||
struct request *req;
|
||||
struct scsi_cmnd *scmd;
|
||||
|
||||
req = scsi_alloc_request(q, REQ_OP_DRV_IN, BLK_MQ_REQ_PM);
|
||||
if (IS_ERR(req))
|
||||
return PTR_ERR(req);
|
||||
|
||||
scmd = blk_mq_rq_to_pdu(req);
|
||||
scmd->cmd_len = cmd_len;
|
||||
memcpy(scmd->cmnd, cmd, cmd_len);
|
||||
scmd->allowed = sdkp->max_retries;
|
||||
req->timeout = SD_TIMEOUT;
|
||||
req->rq_flags |= RQF_PM | RQF_QUIET;
|
||||
req->end_io = sd_start_done;
|
||||
blk_execute_rq_nowait(req, /*at_head=*/true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
|
||||
{
|
||||
unsigned char cmd[6] = { START_STOP }; /* START_VALID */
|
||||
struct scsi_sense_hdr sshdr;
|
||||
struct scsi_device *sdp = sdkp->device;
|
||||
int res;
|
||||
|
||||
if (start)
|
||||
cmd[4] |= 1; /* START */
|
||||
|
|
@ -3601,23 +3660,10 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
|
|||
if (!scsi_device_online(sdp))
|
||||
return -ENODEV;
|
||||
|
||||
res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
|
||||
SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL);
|
||||
if (res) {
|
||||
sd_print_result(sdkp, "Start/Stop Unit failed", res);
|
||||
if (res > 0 && scsi_sense_valid(&sshdr)) {
|
||||
sd_print_sense_hdr(sdkp, &sshdr);
|
||||
/* 0x3a is medium not present */
|
||||
if (sshdr.asc == 0x3a)
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
/* Wait until processing of sense data has finished. */
|
||||
flush_work(&sdkp->start_done_work);
|
||||
|
||||
/* SCSI error codes must not go to the generic layer */
|
||||
if (res)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
return sd_submit_start(sdkp, cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3644,6 +3690,8 @@ static void sd_shutdown(struct device *dev)
|
|||
sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
|
||||
sd_start_stop_device(sdkp, 0);
|
||||
}
|
||||
|
||||
flush_work(&sdkp->start_done_work);
|
||||
}
|
||||
|
||||
static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user