forked from Minki/linux
SCSI misc on 20220804
Updates to the usual drivers (ufs, qla2xx, target, lpfc, smartpqi, mpi3mr). The main driver change that might cause issues on down the road is the conversion of some of our oldest surviving drivers to the DMA API (should only affect m68k). The only major core change is the rework of async resume; the rest are either completely trivial or for updating deprecated APIs. Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCYuvakyYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishfvOAP4m0N6b e3JwoBtB1c0JMKv6G4gka8suEG8p5f4khDu8wwD+LfGUCzG49Y5Ts7rByXfEiGgO krSdwsAZiV6yKg/HuPw= =Ak9L -----END PGP SIGNATURE----- Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI updates from James Bottomley: "Updates to the usual drivers (ufs, qla2xx, target, lpfc, smartpqi, mpi3mr). The main driver change that might cause issues on down the road is the conversion of some of our oldest surviving drivers to the DMA API (should only affect m68k). The only major core change is the rework of async resume; the rest are either completely trivial or for updating deprecated APIs" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (195 commits) scsi: target: Remove XDWRITEREAD emulated support scsi: megaraid: Remove the static variable initialisation scsi: ch: Do not initialise statics to 0 scsi: ufs: core: Fix spelling mistake "Cannnot" -> "Cannot" scsi: target: iscsi: Do not require target authentication scsi: target: iscsi: Allow AuthMethod=None scsi: target: iscsi: Support base64 in CHAP scsi: target: iscsi: Add support for extended CDB AHS scsi: ufs: dt-bindings: Add SC8280XP binding scsi: target: iscsi: Fix clang -Wformat warnings scsi: ufs: core: Read device property for ref clock scsi: libsas: Resume SAS host for phy reset or enable via sysfs scsi: hisi_sas: Modify v3 HW SATA completion error processing scsi: hisi_sas: Relocate DMA unmap of SMP task scsi: hisi_sas: Remove unnecessary variable to hold DMA map elements scsi: hisi_sas: Call hisi_sas_slave_configure() from slave_configure_v3_hw() scsi: mpi3mr: Delete a stray tab scsi: mpi3mr: Unlock on error path scsi: mpi3mr: Reduce VD queue depth on detecting throttling scsi: mpi3mr: Resource Based Metering ...
This commit is contained in:
commit
746fc76b82
@ -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>
|
||||
@ -20811,6 +20803,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 @@ err_out_dif_dma_unmap:
|
||||
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 @@ check_mgmt:
|
||||
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 @@ check_mgmt:
|
||||
*/
|
||||
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 @@ out_err:
|
||||
/* ---------- 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 @@ initpath:
|
||||
|
||||
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 @@ retry_init:
|
||||
|
||||
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 @@ retry_init:
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ err_out_enable:
|
||||
/**
|
||||
* 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 @@ remove_host:
|
||||
#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 @@ force_rx_delete:
|
||||
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 @@ queuing_error:
|
||||
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 @@ done:
|
||||
|
||||
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 @@ done:
|
||||
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 @@ login_logout:
|
||||
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 @@ skip_rio:
|
||||
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 @@ global_port_update:
|
||||
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 @@ check_scsi_status:
|
||||
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 @@ check_scsi_status:
|
||||
|
||||
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 @@ process_err:
|
||||
}
|
||||
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 @@ process_err:
|
||||
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 @@ msix_register_fail:
|
||||
}
|
||||
|
||||
/* 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 @@ release_dev:
|
||||
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 @@ free_priv:
|
||||
}
|
||||
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