Add tri-mode support (SAS/SATA/PCIe).
This includes NVMe device support and adds support for the following adapters: SAS 3408 SAS 3416 SAS 3508 SAS 3516 SAS 3616 SAS 3708 SAS 3716 Reviewed by: ken, scottl, asomers, mav Approved by: ken, scottl, mav MFC after: 2 weeks Relnotes: yes Differential Revision: https://reviews.freebsd.org/D10095
This commit is contained in:
parent
0044ecde83
commit
67feec5045
@ -1,8 +1,8 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2010 Spectra Logic Corporation
|
||||
.\" Copyright (c) 2014 LSI Corp
|
||||
.\" Copyright (c) 2016 Avago Technologies
|
||||
.\" Copyright (c) 2016 Broadcom Ltd.
|
||||
.\" Copyright (c) 2017 Avago Technologies
|
||||
.\" Copyright (c) 2017 Broadcom Ltd.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -38,12 +38,12 @@
|
||||
.\" $Id$
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 6, 2016
|
||||
.Dd May 17, 2017
|
||||
.Dt MPR 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mpr
|
||||
.Nd "LSI Fusion-MPT 3 IT/IR 12Gb/s Serial Attached SCSI/SATA driver"
|
||||
.Nd "LSI Fusion-MPT 3/3.5 IT/IR 12Gb/s Serial Attached SCSI/SATA/PCIe driver"
|
||||
.Sh SYNOPSIS
|
||||
To compile this driver into the kernel, place these lines in the kernel
|
||||
configuration file:
|
||||
@ -62,8 +62,8 @@ mpr_load="YES"
|
||||
The
|
||||
.Nm
|
||||
driver provides support for Broadcom Ltd./Avago Tech (LSI)
|
||||
Fusion-MPT 3 IT/IR
|
||||
.Tn SAS
|
||||
Fusion-MPT 3/3.5 IT/IR
|
||||
.Tn SAS/PCIe
|
||||
controllers.
|
||||
.Sh HARDWARE
|
||||
These controllers are supported by the
|
||||
@ -81,6 +81,24 @@ Broadcom Ltd./Avago Tech (LSI) SAS 3108 (8 Port SAS)
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3216 (16 Port SAS)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3224 (24 Port SAS)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3316 (16 Port SAS)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3324 (24 Port SAS)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3408 (8 Port SAS/PCIe)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3416 (16 Port SAS/PCIe)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3508 (8 Port SAS/PCIe)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3516 (16 Port SAS/PCIe)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3616 (16 Port SAS/PCIe)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3708 (8 Port SAS/PCIe)
|
||||
.It
|
||||
Broadcom Ltd./Avago Tech (LSI) SAS 3716 (16 Port SAS/PCIe)
|
||||
.El
|
||||
.Sh CONFIGURATION
|
||||
In all tunable descriptions below, X represents the adapter number.
|
||||
@ -156,6 +174,24 @@ dev.mpr.X.io_cmds_active
|
||||
.Xr sysctl 8
|
||||
variable.
|
||||
.Pp
|
||||
The current number of free PRP pages is stored in the
|
||||
dev.mpr.X.prp_pages_free
|
||||
.Xr sysctl 8
|
||||
variable.
|
||||
PRP pages are used by NVMe devices for I/O transfers, much like Scatter/Gather
|
||||
lists.
|
||||
.Pp
|
||||
The lowest number of free PRP pages seen since boot is stored in the
|
||||
dev.mpr.X.prp_pages_free_lowwater
|
||||
.Xr sysctl 8
|
||||
variable.
|
||||
.Pp
|
||||
The number of times that PRP page allocations have failed since boot is
|
||||
stored in the
|
||||
dev.mpr.X.prp_page_alloc_fail
|
||||
.Xr sysctl 8
|
||||
variable.
|
||||
.Pp
|
||||
To set the maximum number of pages that will be used per I/O for all adapters,
|
||||
set this tunable in
|
||||
.Xr loader.conf 5 :
|
||||
@ -229,13 +265,13 @@ Send SSU to HDDs, but not to SSDs.
|
||||
Send SSU to both HDDs and SSDs.
|
||||
.El
|
||||
.Pp
|
||||
To control the feature for a specific adapter, set this tunable value in
|
||||
To control this feature for a specific adapter, set this tunable value in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
dev.mpr.X.enable_ssu
|
||||
.Ed
|
||||
.Pp
|
||||
The same set of values are valid when setting this tunable for all adapters.
|
||||
The same set of values are valid as when setting this tunable for all adapters.
|
||||
.Pp
|
||||
SATA disks that take several seconds to spin up and fail the SATA Identify
|
||||
command might not be discovered by the driver.
|
||||
@ -261,6 +297,45 @@ dev.mpr.X.spinup_wait_time=NNNN
|
||||
tunable.
|
||||
NNNN is the number of seconds to wait for SATA devices to spin up when they fail
|
||||
the initial SATA Identify command.
|
||||
.Pp
|
||||
The driver can map devices discovered by the adapter so that target IDs
|
||||
corresponding to a specific device persist across resets and reboots.
|
||||
In some cases it is possible for devices to lose their mapped IDs due to
|
||||
unexpected behavior from certain hardware, such as some types of enclosures.
|
||||
To overcome this problem, a tunable is provided that will force the driver to
|
||||
map devices using the Phy number associated with the device.
|
||||
This feature is not recommended if the topology includes multiple
|
||||
enclosures/expanders.
|
||||
If multiple enclosures/expanders are present in the topology, Phy numbers are
|
||||
repeated, causing all devices at these Phy numbers except the first device to
|
||||
fail enumeration.
|
||||
To control this feature for all adapters, set the
|
||||
.Bd -literal -offset indent
|
||||
hw.mpr.use_phy_num
|
||||
.Ed
|
||||
.Pp
|
||||
tunable in
|
||||
.Xr loader.conf 5
|
||||
to one of these values:
|
||||
.Bl -tag -width 6n -offset indent
|
||||
.It -1
|
||||
Only use Phy numbers to map devices and bypass the driver's mapping logic.
|
||||
.It 0
|
||||
Never use Phy numbers to map devices.
|
||||
.It 1
|
||||
Use Phy numbers to map devices, but only if the driver's mapping logic fails
|
||||
to map the device that is being enumerated.
|
||||
This is the default value.
|
||||
.El
|
||||
.Pp
|
||||
To control this feature for a specific adapter, set this tunable value in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
dev.mpr.X.use_phy_num
|
||||
.Ed
|
||||
.Pp
|
||||
The same set of values are valid as when setting this tunable for all adapters.
|
||||
.Pp
|
||||
.Sh DEBUGGING
|
||||
To enable debugging prints from the
|
||||
.Nm
|
||||
|
@ -44,7 +44,7 @@
|
||||
* scatter/gather formats.
|
||||
* Creation Date: June 21, 2006
|
||||
*
|
||||
* mpi2.h Version: 02.00.42
|
||||
* mpi2.h Version: 02.00.46
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
@ -132,7 +132,8 @@
|
||||
* Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* 03-16-15 02.00.37 Updated for MPI v2.6.
|
||||
* Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* Added Scratchpad registers to
|
||||
* Added Scratchpad registers and
|
||||
* AtomicRequestDescriptorPost register to
|
||||
* MPI2_SYSTEM_INTERFACE_REGS.
|
||||
* Added MPI2_DIAG_SBR_RELOAD.
|
||||
* Added MPI2_IOCSTATUS_INSUFFICIENT_POWER.
|
||||
@ -142,6 +143,14 @@
|
||||
* Added V7 HostDiagnostic register defines
|
||||
* 12-15-15 02.00.41 Bumped MPI_HEADER_VERSION_UNIT
|
||||
* 01-01-16 02.00.42 Bumped MPI_HEADER_VERSION_UNIT
|
||||
* 04-05-16 02.00.43 Modified MPI26_DIAG_BOOT_DEVICE_SELECT defines
|
||||
* to be unique within first 32 characters.
|
||||
* Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* 04-10-16 02.00.44 Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* 07-06-16 02.00.45 Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* 09-02-16 02.00.46 Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -185,7 +194,7 @@
|
||||
|
||||
|
||||
/* Unit and Dev versioning for this MPI header set */
|
||||
#define MPI2_HEADER_VERSION_UNIT (0x2A)
|
||||
#define MPI2_HEADER_VERSION_UNIT (0x2E)
|
||||
#define MPI2_HEADER_VERSION_DEV (0x00)
|
||||
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
|
||||
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
|
||||
@ -245,7 +254,8 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
|
||||
U32 Scratchpad[4]; /* 0xB0 */
|
||||
U32 RequestDescriptorPostLow; /* 0xC0 */
|
||||
U32 RequestDescriptorPostHigh; /* 0xC4 */
|
||||
U32 Reserved7[14]; /* 0xC8 */
|
||||
U32 AtomicRequestDescriptorPost;/* 0xC8 */ /* MPI v2.6 and later; reserved in earlier versions */
|
||||
U32 Reserved7[13]; /* 0xCC */
|
||||
} MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS,
|
||||
Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t;
|
||||
|
||||
@ -293,10 +303,11 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
|
||||
#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800)
|
||||
|
||||
/* Defines for V7A/V7R HostDiagnostic Register */
|
||||
#define MPI26_DIAG_BOOT_DEVICE_SELECT_FLASH64 (0x00000000)
|
||||
#define MPI26_DIAG_BOOT_DEVICE_SELECT_HCDW64 (0x00000800)
|
||||
#define MPI26_DIAG_BOOT_DEVICE_SELECT_FLASH32 (0x00001000)
|
||||
#define MPI26_DIAG_BOOT_DEVICE_SELECT_HCDW32 (0x00001800)
|
||||
#define MPI26_DIAG_BOOT_DEVICE_SEL_64FLASH (0x00000000)
|
||||
#define MPI26_DIAG_BOOT_DEVICE_SEL_64HCDW (0x00000800)
|
||||
#define MPI26_DIAG_BOOT_DEVICE_SEL_32FLASH (0x00001000)
|
||||
#define MPI26_DIAG_BOOT_DEVICE_SEL_32HCDW (0x00001800)
|
||||
|
||||
#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400)
|
||||
#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200)
|
||||
#define MPI2_DIAG_HCB_MODE (0x00000100)
|
||||
@ -379,6 +390,7 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
|
||||
*/
|
||||
#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0)
|
||||
#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4)
|
||||
#define MPI26_ATOMIC_REQUEST_DESCRIPTOR_POST_OFFSET (0x000000C8)
|
||||
|
||||
|
||||
/* Hard Reset delay timings */
|
||||
@ -415,6 +427,7 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
|
||||
#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08)
|
||||
#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A)
|
||||
#define MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO (0x0C)
|
||||
#define MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED (0x10)
|
||||
|
||||
#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
|
||||
|
||||
@ -482,6 +495,14 @@ typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR
|
||||
MPI2_POINTER pMpi25FastPathSCSIIORequestDescriptor_t;
|
||||
|
||||
|
||||
/* PCIe Encapsulated Request Descriptor */
|
||||
typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR
|
||||
MPI26_PCIE_ENCAPSULATED_REQUEST_DESCRIPTOR,
|
||||
MPI2_POINTER PTR_MPI26_PCIE_ENCAPSULATED_REQUEST_DESCRIPTOR,
|
||||
Mpi26PCIeEncapsulatedRequestDescriptor_t,
|
||||
MPI2_POINTER pMpi26PCIeEncapsulatedRequestDescriptor_t;
|
||||
|
||||
|
||||
/* union of Request Descriptors */
|
||||
typedef union _MPI2_REQUEST_DESCRIPTOR_UNION
|
||||
{
|
||||
@ -491,11 +512,35 @@ typedef union _MPI2_REQUEST_DESCRIPTOR_UNION
|
||||
MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
|
||||
MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator;
|
||||
MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR FastPathSCSIIO;
|
||||
MPI26_PCIE_ENCAPSULATED_REQUEST_DESCRIPTOR PCIeEncapsulated;
|
||||
U64 Words;
|
||||
} MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
|
||||
Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t;
|
||||
|
||||
|
||||
/* Atomic Request Descriptors */
|
||||
|
||||
/*
|
||||
* All Atomic Request Descriptors have the same format, so the following
|
||||
* structure is used for all Atomic Request Descriptors:
|
||||
* Atomic Default Request Descriptor
|
||||
* Atomic High Priority Request Descriptor
|
||||
* Atomic SCSI IO Request Descriptor
|
||||
* Atomic SCSI Target Request Descriptor
|
||||
* Atomic RAID Accelerator Request Descriptor
|
||||
* Atomic Fast Path SCSI IO Request Descriptor
|
||||
* Atomic PCIe Encapsulated Request Descriptor
|
||||
*/
|
||||
|
||||
/* Atomic Request Descriptor */
|
||||
typedef struct _MPI26_ATOMIC_REQUEST_DESCRIPTOR
|
||||
{
|
||||
U8 RequestFlags; /* 0x00 */
|
||||
U8 MSIxIndex; /* 0x01 */
|
||||
U16 SMID; /* 0x02 */
|
||||
} MPI26_ATOMIC_REQUEST_DESCRIPTOR,
|
||||
MPI2_POINTER PTR_MPI26_ATOMIC_REQUEST_DESCRIPTOR,
|
||||
Mpi26AtomicRequestDescriptor_t, MPI2_POINTER pMpi26AtomicRequestDescriptor_t;
|
||||
|
||||
/* for the RequestFlags field, use the same defines as MPI2_DEFAULT_REQUEST_DESCRIPTOR */
|
||||
|
||||
@ -520,6 +565,7 @@ typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
|
||||
#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03)
|
||||
#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05)
|
||||
#define MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS (0x06)
|
||||
#define MPI26_RPY_DESCRIPT_FLAGS_PCIE_ENCAPSULATED_SUCCESS (0x08)
|
||||
#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
|
||||
|
||||
/* values for marking a reply descriptor as unused */
|
||||
@ -607,6 +653,14 @@ typedef MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
|
||||
MPI2_POINTER pMpi25FastPathSCSIIOSuccessReplyDescriptor_t;
|
||||
|
||||
|
||||
/* PCIe Encapsulated Success Reply Descriptor */
|
||||
typedef MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR
|
||||
MPI26_PCIE_ENCAPSULATED_SUCCESS_REPLY_DESCRIPTOR,
|
||||
MPI2_POINTER PTR_MPI26_PCIE_ENCAPSULATED_SUCCESS_REPLY_DESCRIPTOR,
|
||||
Mpi26PCIeEncapsulatedSuccessReplyDescriptor_t,
|
||||
MPI2_POINTER pMpi26PCIeEncapsulatedSuccessReplyDescriptor_t;
|
||||
|
||||
|
||||
/* union of Reply Descriptors */
|
||||
typedef union _MPI2_REPLY_DESCRIPTORS_UNION
|
||||
{
|
||||
@ -617,6 +671,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION
|
||||
MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
|
||||
MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess;
|
||||
MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR FastPathSCSIIOSuccess;
|
||||
MPI26_PCIE_ENCAPSULATED_SUCCESS_REPLY_DESCRIPTOR PCIeEncapsulatedSuccess;
|
||||
U64 Words;
|
||||
} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
|
||||
Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
|
||||
@ -659,6 +714,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION
|
||||
#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F) /* Host Based Discovery Action */
|
||||
#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30) /* Power Management Control */
|
||||
#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31) /* Send Host Message */
|
||||
#define MPI2_FUNCTION_NVME_ENCAPSULATED (0x33) /* NVMe Encapsulated (MPI v2.6) */
|
||||
#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) /* beginning of product-specific range */
|
||||
#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) /* end of product-specific range */
|
||||
|
||||
@ -1232,6 +1288,8 @@ typedef union _MPI25_SGE_IO_UNION
|
||||
|
||||
#define MPI26_IEEE_SGE_FLAGS_NSF_MASK (0x1C)
|
||||
#define MPI26_IEEE_SGE_FLAGS_NSF_MPI_IEEE (0x00)
|
||||
#define MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP (0x08)
|
||||
#define MPI26_IEEE_SGE_FLAGS_NSF_NVME_SGL (0x10)
|
||||
|
||||
/* Data Location Address Space */
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
* Title: MPI Configuration messages and pages
|
||||
* Creation Date: November 10, 2006
|
||||
*
|
||||
* mpi2_cnfg.h Version: 02.00.35
|
||||
* mpi2_cnfg.h Version: 02.00.39
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
@ -223,9 +223,38 @@
|
||||
* Flags field to IO Unit Page 7.
|
||||
* Added IO Unit Page 11.
|
||||
* Added new SAS Phy Event codes
|
||||
* Added PCIe configuration pages.
|
||||
* 03-19-15 02.00.32 Fixed PCIe Link Config page structure names to be
|
||||
* unique in first 32 characters.
|
||||
* 05-25-15 02.00.33 Added more defines for the BiosOptions field of
|
||||
* MPI2_CONFIG_PAGE_BIOS_1.
|
||||
* 08-25-15 02.00.34 Added PCIe Device Page 2 SGL format capability.
|
||||
* 12-18-15 02.00.35 Added SATADeviceWaitTime to SAS IO Unit Page 4.
|
||||
* 01-21-16 02.00.36 Added/modified MPI2_MFGPAGE_DEVID_SAS defines.
|
||||
* Added Link field to PCIe Link Pages
|
||||
* Added EnclosureLevel and ConnectorName to PCIe
|
||||
* Device Page 0.
|
||||
* Added define for PCIE IoUnit page 1 max rate shift.
|
||||
* Added comment for reserved ExtPageTypes.
|
||||
* Added SAS 4 22.5 gbs speed support.
|
||||
* Added PCIe 4 16.0 GT/sec speec support.
|
||||
* Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* Added NegotiatedLinkRate and NegotiatedPortWidth to
|
||||
* PCIe device page 0.
|
||||
* 04-10-16 02.00.37 Fixed MPI2_MFGPAGE_DEVID_SAS3616/3708 defines
|
||||
* 07-01-16 02.00.38 Added Manufacturing page 7 Connector types.
|
||||
* Changed declaration of ConnectorName in PCIe DevicePage0
|
||||
* to match SAS DevicePage 0.
|
||||
* Added SATADeviceWaitTime to IO Unit Page 11.
|
||||
* Added MPI26_MFGPAGE_DEVID_SAS4008
|
||||
* Added x16 PCIe width to IO Unit Page 7
|
||||
* Added LINKFLAGS to control SRIS in PCIe IO Unit page 1
|
||||
* phy data.
|
||||
* Added InitStatus to PCIe IO Unit Page 1 header.
|
||||
* 09-01-16 02.00.39 Added MPI26_CONFIG_PAGE_ENCLOSURE_0 and related defines.
|
||||
* Added MPI26_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE and
|
||||
* MPI26_ENCLOS_PGAD_FORM_HANDLE page address formats.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -310,6 +339,12 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19)
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A)
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT (0x1B) /* MPI v2.6 and later */
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH (0x1C) /* MPI v2.6 and later */
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE (0x1D) /* MPI v2.6 and later */
|
||||
#define MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK (0x1E) /* MPI v2.6 and later */
|
||||
/* Product specific reserved values 0xE0 - 0xEF */
|
||||
/* Vendor specific reserved values 0xF0 - 0xFF */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
@ -377,6 +412,12 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
|
||||
|
||||
#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF)
|
||||
|
||||
/* Enclosure PageAddress format */
|
||||
#define MPI26_ENCLOS_PGAD_FORM_MASK (0xF0000000)
|
||||
#define MPI26_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
|
||||
#define MPI26_ENCLOS_PGAD_FORM_HANDLE (0x10000000)
|
||||
|
||||
#define MPI26_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF)
|
||||
|
||||
/* RAID Configuration PageAddress format */
|
||||
#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000)
|
||||
@ -403,6 +444,33 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
|
||||
#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF)
|
||||
|
||||
|
||||
/* PCIe Switch PageAddress format */
|
||||
#define MPI26_PCIE_SWITCH_PGAD_FORM_MASK (0xF0000000)
|
||||
#define MPI26_PCIE_SWITCH_PGAD_FORM_GET_NEXT_HNDL (0x00000000)
|
||||
#define MPI26_PCIE_SWITCH_PGAD_FORM_HNDL_PORTNUM (0x10000000)
|
||||
#define MPI26_PCIE_SWITCH_EXPAND_PGAD_FORM_HNDL (0x20000000)
|
||||
|
||||
#define MPI26_PCIE_SWITCH_PGAD_HANDLE_MASK (0x0000FFFF)
|
||||
#define MPI26_PCIE_SWITCH_PGAD_PORTNUM_MASK (0x00FF0000)
|
||||
#define MPI26_PCIE_SWITCH_PGAD_PORTNUM_SHIFT (16)
|
||||
|
||||
|
||||
/* PCIe Device PageAddress format */
|
||||
#define MPI26_PCIE_DEVICE_PGAD_FORM_MASK (0xF0000000)
|
||||
#define MPI26_PCIE_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
|
||||
#define MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE (0x20000000)
|
||||
|
||||
#define MPI26_PCIE_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF)
|
||||
|
||||
/* PCIe Link PageAddress format */
|
||||
#define MPI26_PCIE_LINK_PGAD_FORM_MASK (0xF0000000)
|
||||
#define MPI26_PCIE_LINK_PGAD_FORM_GET_NEXT_LINK (0x00000000)
|
||||
#define MPI26_PCIE_LINK_PGAD_FORM_LINK_NUM (0x10000000)
|
||||
|
||||
#define MPI26_PCIE_DEVICE_PGAD_LINKNUM_MASK (0x000000FF)
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Configuration messages
|
||||
****************************************************************************/
|
||||
@ -518,6 +586,20 @@ typedef struct _MPI2_CONFIG_REPLY
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3324_3 (0x00C2)
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3324_4 (0x00C3)
|
||||
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3516 (0x00AA)
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3516_1 (0x00AB)
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3416 (0x00AC)
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3508 (0x00AD)
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3508_1 (0x00AE)
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3408 (0x00AF)
|
||||
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3716 (0x00D0)
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3616 (0x00D1)
|
||||
#define MPI26_MFGPAGE_DEVID_SAS3708 (0x00D2)
|
||||
|
||||
#define MPI26_MFGPAGE_DEVID_SAS4008 (0x00A1)
|
||||
|
||||
|
||||
/* Manufacturing Page 0 */
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_MAN_0
|
||||
@ -755,6 +837,12 @@ typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B)
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C)
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D)
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8088_A (0x0E)
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8643_16i (0x0F)
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8654_4i (0x10)
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8654_8i (0x11)
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8611_4i (0x12)
|
||||
#define MPI2_MANPAGE7_PINOUT_SFF_8611_8i (0x13)
|
||||
|
||||
/* defines for the Location field */
|
||||
#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
|
||||
@ -1017,11 +1105,13 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7
|
||||
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2 (0x02)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4 (0x04)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8 (0x08)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X16 (0x10)
|
||||
|
||||
/* defines for IO Unit Page 7 PCIeSpeed field */
|
||||
#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS (0x00)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02)
|
||||
#define MPI2_IOUNITPAGE7_PCIE_SPEED_16_0_GBPS (0x03)
|
||||
|
||||
/* defines for IO Unit Page 7 ProcessorState field */
|
||||
#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F)
|
||||
@ -1079,6 +1169,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7
|
||||
/* defines for IO Unit Page 7 Flags field */
|
||||
#define MPI2_IOUNITPAGE7_FLAG_CABLE_POWER_EXC (0x01)
|
||||
|
||||
|
||||
/* IO Unit Page 8 */
|
||||
|
||||
#define MPI2_IOUNIT8_NUM_THRESHOLDS (4)
|
||||
@ -1228,7 +1319,7 @@ typedef struct _MPI26_CONFIG_PAGE_IO_UNIT_11
|
||||
U32 Reserved3; /* 0x1C */
|
||||
U32 Reserved4; /* 0x20 */
|
||||
U8 BootDeviceWaitTime; /* 0x24 */
|
||||
U8 Reserved5; /* 0x25 */
|
||||
U8 SATADeviceWaitTime; /* 0x25 */
|
||||
U16 Reserved6; /* 0x26 */
|
||||
U8 NumPhys; /* 0x28 */
|
||||
U8 PEInitialSpinupDelay; /* 0x29 */
|
||||
@ -1249,9 +1340,6 @@ typedef struct _MPI26_CONFIG_PAGE_IO_UNIT_11
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* IOC Config Pages
|
||||
****************************************************************************/
|
||||
@ -1968,6 +2056,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
|
||||
#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09)
|
||||
#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A)
|
||||
#define MPI25_SAS_NEG_LINK_RATE_12_0 (0x0B)
|
||||
#define MPI26_SAS_NEG_LINK_RATE_22_5 (0x0C)
|
||||
|
||||
|
||||
/* values for AttachedPhyInfo fields */
|
||||
@ -2035,12 +2124,14 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
|
||||
#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90)
|
||||
#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0)
|
||||
#define MPI25_SAS_PRATE_MAX_RATE_12_0 (0xB0)
|
||||
#define MPI26_SAS_PRATE_MAX_RATE_22_5 (0xC0)
|
||||
#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F)
|
||||
#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00)
|
||||
#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08)
|
||||
#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09)
|
||||
#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A)
|
||||
#define MPI25_SAS_PRATE_MIN_RATE_12_0 (0x0B)
|
||||
#define MPI26_SAS_PRATE_MIN_RATE_22_5 (0x0C)
|
||||
|
||||
|
||||
/* values for SAS HwLinkRate fields */
|
||||
@ -2049,11 +2140,13 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
|
||||
#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90)
|
||||
#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0)
|
||||
#define MPI25_SAS_HWRATE_MAX_RATE_12_0 (0xB0)
|
||||
#define MPI26_SAS_HWRATE_MAX_RATE_22_5 (0xC0)
|
||||
#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F)
|
||||
#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08)
|
||||
#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09)
|
||||
#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A)
|
||||
#define MPI25_SAS_HWRATE_MIN_RATE_12_0 (0x0B)
|
||||
#define MPI26_SAS_HWRATE_MIN_RATE_22_5 (0x0C)
|
||||
|
||||
|
||||
|
||||
@ -2227,11 +2320,13 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1
|
||||
#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90)
|
||||
#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0)
|
||||
#define MPI25_SASIOUNIT1_MAX_RATE_12_0 (0xB0)
|
||||
#define MPI26_SASIOUNIT1_MAX_RATE_22_5 (0xC0)
|
||||
#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F)
|
||||
#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08)
|
||||
#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09)
|
||||
#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A)
|
||||
#define MPI25_SASIOUNIT1_MIN_RATE_12_0 (0x0B)
|
||||
#define MPI26_SASIOUNIT1_MIN_RATE_22_5 (0x0C)
|
||||
|
||||
/* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
|
||||
|
||||
@ -2718,7 +2813,6 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0
|
||||
#define MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID (0x0002)
|
||||
#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
|
||||
|
||||
|
||||
/* SAS Device Page 1 */
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1
|
||||
@ -2885,7 +2979,6 @@ typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG
|
||||
#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0)
|
||||
#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1)
|
||||
#define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2)
|
||||
|
||||
/* Following codes are product specific and in MPI v2.6 and later */
|
||||
#define MPI2_SASPHY3_EVENT_CODE_LCARB_WAIT_TIME (0xD3)
|
||||
#define MPI2_SASPHY3_EVENT_CODE_RCVD_CONN_RESP_WAIT_TIME (0xD4)
|
||||
@ -2898,7 +2991,6 @@ typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG
|
||||
#define MPI2_SASPHY3_EVENT_CODE_SATA_RX_START_RECEIVE (0xDB)
|
||||
#define MPI2_SASPHY3_EVENT_CODE_SMP_RX_START_RECEIVE (0xDC)
|
||||
|
||||
|
||||
/* values for the CounterType field */
|
||||
#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00)
|
||||
#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01)
|
||||
@ -2989,7 +3081,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0
|
||||
* SAS Enclosure Config Pages
|
||||
****************************************************************************/
|
||||
|
||||
/* SAS Enclosure Page 0 */
|
||||
/* SAS Enclosure Page 0, Enclosure Page 0 */
|
||||
|
||||
typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0
|
||||
{
|
||||
@ -3007,7 +3099,10 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0
|
||||
U32 Reserved4; /* 0x24 */
|
||||
} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
|
||||
MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
|
||||
Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t;
|
||||
Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t,
|
||||
MPI26_CONFIG_PAGE_ENCLOSURE_0,
|
||||
MPI2_POINTER PTR_MPI26_CONFIG_PAGE_ENCLOSURE_0,
|
||||
Mpi26EnclosurePage0_t, MPI2_POINTER pMpi26EnclosurePage0_t;
|
||||
|
||||
#define MPI2_SASENCLOSURE0_PAGEVERSION (0x04)
|
||||
|
||||
@ -3021,6 +3116,17 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0
|
||||
#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
|
||||
#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
|
||||
|
||||
#define MPI26_ENCLOSURE0_PAGEVERSION (0x04)
|
||||
|
||||
/* Values for Enclosure Page 0 Flags field */
|
||||
#define MPI26_ENCLS0_FLAGS_ENCL_LEVEL_VALID (0x0010)
|
||||
#define MPI26_ENCLS0_FLAGS_MNG_MASK (0x000F)
|
||||
#define MPI26_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000)
|
||||
#define MPI26_ENCLS0_FLAGS_MNG_IOC_SES (0x0001)
|
||||
#define MPI26_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
|
||||
#define MPI26_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
|
||||
#define MPI26_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
|
||||
#define MPI26_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
|
||||
|
||||
/****************************************************************************
|
||||
* Log Config Page
|
||||
@ -3300,5 +3406,424 @@ typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS
|
||||
|
||||
/* PageVersion should be provided by product-specific code */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* values for fields used by several types of PCIe Config Pages
|
||||
****************************************************************************/
|
||||
|
||||
/* values for NegotiatedLinkRates fields */
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_MASK_PHYSICAL (0x0F)
|
||||
/* link rates used for Negotiated Physical Link Rate */
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_UNKNOWN (0x00)
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_PHY_DISABLED (0x01)
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_2_5 (0x02)
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_5_0 (0x03)
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_8_0 (0x04)
|
||||
#define MPI26_PCIE_NEG_LINK_RATE_16_0 (0x05)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* PCIe IO Unit Config Pages (MPI v2.6 and later)
|
||||
****************************************************************************/
|
||||
|
||||
/* PCIe IO Unit Page 0 */
|
||||
|
||||
typedef struct _MPI26_PCIE_IO_UNIT0_PHY_DATA
|
||||
{
|
||||
U8 Link; /* 0x00 */
|
||||
U8 LinkFlags; /* 0x01 */
|
||||
U8 PhyFlags; /* 0x02 */
|
||||
U8 NegotiatedLinkRate; /* 0x03 */
|
||||
U32 ControllerPhyDeviceInfo;/* 0x04 */
|
||||
U16 AttachedDevHandle; /* 0x08 */
|
||||
U16 ControllerDevHandle; /* 0x0A */
|
||||
U32 EnumerationStatus; /* 0x0C */
|
||||
U32 Reserved1; /* 0x10 */
|
||||
} MPI26_PCIE_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI26_PCIE_IO_UNIT0_PHY_DATA,
|
||||
Mpi26PCIeIOUnit0PhyData_t, MPI2_POINTER pMpi26PCIeIOUnit0PhyData_t;
|
||||
|
||||
/*
|
||||
* Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
* one and check the value returned for NumPhys at runtime.
|
||||
*/
|
||||
#ifndef MPI26_PCIE_IOUNIT0_PHY_MAX
|
||||
#define MPI26_PCIE_IOUNIT0_PHY_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_0
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U32 Reserved1; /* 0x08 */
|
||||
U8 NumPhys; /* 0x0C */
|
||||
U8 InitStatus; /* 0x0D */
|
||||
U16 Reserved3; /* 0x0E */
|
||||
MPI26_PCIE_IO_UNIT0_PHY_DATA PhyData[MPI26_PCIE_IOUNIT0_PHY_MAX]; /* 0x10 */
|
||||
} MPI26_CONFIG_PAGE_PIOUNIT_0,
|
||||
MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PIOUNIT_0,
|
||||
Mpi26PCIeIOUnitPage0_t, MPI2_POINTER pMpi26PCIeIOUnitPage0_t;
|
||||
|
||||
#define MPI26_PCIEIOUNITPAGE0_PAGEVERSION (0x00)
|
||||
|
||||
/* values for PCIe IO Unit Page 0 LinkFlags */
|
||||
#define MPI26_PCIEIOUNIT0_LINKFLAGS_ENUMERATION_IN_PROGRESS (0x08)
|
||||
|
||||
/* values for PCIe IO Unit Page 0 PhyFlags */
|
||||
#define MPI26_PCIEIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08)
|
||||
|
||||
/* use MPI26_PCIE_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
|
||||
|
||||
/* see mpi2_pci.h for values for PCIe IO Unit Page 0 ControllerPhyDeviceInfo values */
|
||||
|
||||
/* values for PCIe IO Unit Page 0 EnumerationStatus */
|
||||
#define MPI26_PCIEIOUNIT0_ES_MAX_SWITCHES_EXCEEDED (0x40000000)
|
||||
#define MPI26_PCIEIOUNIT0_ES_MAX_DEVICES_EXCEEDED (0x20000000)
|
||||
|
||||
|
||||
/* PCIe IO Unit Page 1 */
|
||||
|
||||
typedef struct _MPI26_PCIE_IO_UNIT1_PHY_DATA
|
||||
{
|
||||
U8 Link; /* 0x00 */
|
||||
U8 LinkFlags; /* 0x01 */
|
||||
U8 PhyFlags; /* 0x02 */
|
||||
U8 MaxMinLinkRate; /* 0x03 */
|
||||
U32 ControllerPhyDeviceInfo; /* 0x04 */
|
||||
U32 Reserved1; /* 0x08 */
|
||||
} MPI26_PCIE_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI26_PCIE_IO_UNIT1_PHY_DATA,
|
||||
Mpi26PCIeIOUnit1PhyData_t, MPI2_POINTER pMpi26PCIeIOUnit1PhyData_t;
|
||||
|
||||
/* values for LinkFlags */
|
||||
#define MPI26_PCIEIOUNIT1_LINKFLAGS_DIS_SRIS (0x00)
|
||||
#define MPI26_PCIEIOUNIT1_LINKFLAGS_EN_SRIS (0x01)
|
||||
|
||||
/*
|
||||
* Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
* one and check the value returned for NumPhys at runtime.
|
||||
*/
|
||||
#ifndef MPI26_PCIE_IOUNIT1_PHY_MAX
|
||||
#define MPI26_PCIE_IOUNIT1_PHY_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PIOUNIT_1
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 ControlFlags; /* 0x08 */
|
||||
U16 Reserved; /* 0x0A */
|
||||
U16 AdditionalControlFlags; /* 0x0C */
|
||||
U16 NVMeMaxQueueDepth; /* 0x0E */
|
||||
U8 NumPhys; /* 0x10 */
|
||||
U8 Reserved1; /* 0x11 */
|
||||
U16 Reserved2; /* 0x12 */
|
||||
MPI26_PCIE_IO_UNIT1_PHY_DATA PhyData[MPI26_PCIE_IOUNIT1_PHY_MAX];/* 0x14 */
|
||||
} MPI26_CONFIG_PAGE_PIOUNIT_1,
|
||||
MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PIOUNIT_1,
|
||||
Mpi26PCIeIOUnitPage1_t, MPI2_POINTER pMpi26PCIeIOUnitPage1_t;
|
||||
|
||||
#define MPI26_PCIEIOUNITPAGE1_PAGEVERSION (0x00)
|
||||
|
||||
/* values for PCIe IO Unit Page 1 PhyFlags */
|
||||
#define MPI26_PCIEIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08)
|
||||
#define MPI26_PCIEIOUNIT1_PHYFLAGS_ENDPOINT_ONLY (0x01)
|
||||
|
||||
/* values for PCIe IO Unit Page 1 MaxMinLinkRate */
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_MASK (0xF0)
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_SHIFT (4)
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_2_5 (0x20)
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_5_0 (0x30)
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_8_0 (0x40)
|
||||
#define MPI26_PCIEIOUNIT1_MAX_RATE_16_0 (0x50)
|
||||
|
||||
/* see mpi2_pci.h for values for PCIe IO Unit Page 0 ControllerPhyDeviceInfo values */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* PCIe Switch Config Pages (MPI v2.6 and later)
|
||||
****************************************************************************/
|
||||
|
||||
/* PCIe Switch Page 0 */
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PSWITCH_0
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U8 PhysicalPort; /* 0x08 */
|
||||
U8 Reserved1; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U16 DevHandle; /* 0x0C */
|
||||
U16 ParentDevHandle; /* 0x0E */
|
||||
U8 NumPorts; /* 0x10 */
|
||||
U8 PCIeLevel; /* 0x11 */
|
||||
U16 Reserved3; /* 0x12 */
|
||||
U32 Reserved4; /* 0x14 */
|
||||
U32 Reserved5; /* 0x18 */
|
||||
U32 Reserved6; /* 0x1C */
|
||||
} MPI26_CONFIG_PAGE_PSWITCH_0, MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PSWITCH_0,
|
||||
Mpi26PCIeSwitchPage0_t, MPI2_POINTER pMpi26PCIeSwitchPage0_t;
|
||||
|
||||
#define MPI26_PCIESWITCH0_PAGEVERSION (0x00)
|
||||
|
||||
|
||||
/* PCIe Switch Page 1 */
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PSWITCH_1
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U8 PhysicalPort; /* 0x08 */
|
||||
U8 Reserved1; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U8 NumPorts; /* 0x0C */
|
||||
U8 PortNum; /* 0x0D */
|
||||
U16 AttachedDevHandle; /* 0x0E */
|
||||
U16 SwitchDevHandle; /* 0x10 */
|
||||
U8 NegotiatedPortWidth; /* 0x12 */
|
||||
U8 NegotiatedLinkRate; /* 0x13 */
|
||||
U32 Reserved4; /* 0x14 */
|
||||
U32 Reserved5; /* 0x18 */
|
||||
} MPI26_CONFIG_PAGE_PSWITCH_1, MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PSWITCH_1,
|
||||
Mpi26PCIeSwitchPage1_t, MPI2_POINTER pMpi26PCIeSwitchPage1_t;
|
||||
|
||||
#define MPI26_PCIESWITCH1_PAGEVERSION (0x00)
|
||||
|
||||
/* use MPI26_PCIE_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* PCIe Device Config Pages (MPI v2.6 and later)
|
||||
****************************************************************************/
|
||||
|
||||
/* PCIe Device Page 0 */
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PCIEDEV_0
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 Slot; /* 0x08 */
|
||||
U16 EnclosureHandle; /* 0x0A */
|
||||
U64 WWID; /* 0x0C */
|
||||
U16 ParentDevHandle; /* 0x14 */
|
||||
U8 PortNum; /* 0x16 */
|
||||
U8 AccessStatus; /* 0x17 */
|
||||
U16 DevHandle; /* 0x18 */
|
||||
U8 PhysicalPort; /* 0x1A */
|
||||
U8 Reserved1; /* 0x1B */
|
||||
U32 DeviceInfo; /* 0x1C */
|
||||
U32 Flags; /* 0x20 */
|
||||
U8 SupportedLinkRates; /* 0x24 */
|
||||
U8 MaxPortWidth; /* 0x25 */
|
||||
U8 NegotiatedPortWidth; /* 0x26 */
|
||||
U8 NegotiatedLinkRate; /* 0x27 */
|
||||
U8 EnclosureLevel; /* 0x28 */
|
||||
U8 Reserved2; /* 0x29 */
|
||||
U16 Reserved3; /* 0x2A */
|
||||
U8 ConnectorName[4]; /* 0x2C */
|
||||
U32 Reserved4; /* 0x30 */
|
||||
U32 Reserved5; /* 0x34 */
|
||||
} MPI26_CONFIG_PAGE_PCIEDEV_0, MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PCIEDEV_0,
|
||||
Mpi26PCIeDevicePage0_t, MPI2_POINTER pMpi26PCIeDevicePage0_t;
|
||||
|
||||
#define MPI26_PCIEDEVICE0_PAGEVERSION (0x01)
|
||||
|
||||
/* values for PCIe Device Page 0 AccessStatus field */
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NO_ERRORS (0x00)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NEEDS_INITIALIZATION (0x04)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_CAPABILITY_FAILED (0x02)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED (0x07)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_MEMORY_SPACE_ACCESS_FAILED (0x08)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_UNSUPPORTED_DEVICE (0x09)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_MSIX_REQUIRED (0x0A)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_UNKNOWN (0x10)
|
||||
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_READY_TIMEOUT (0x30)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_DEVCFG_UNSUPPORTED (0x31)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_IDENTIFY_FAILED (0x32)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_QCONFIG_FAILED (0x33)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_QCREATION_FAILED (0x34)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_EVENTCFG_FAILED (0x35)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_GET_FEATURE_STAT_FAILED (0x36)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_IDLE_TIMEOUT (0x37)
|
||||
#define MPI26_PCIEDEV0_ASTATUS_NVME_FAILURE_STATUS (0x38)
|
||||
|
||||
#define MPI26_PCIEDEV0_ASTATUS_INIT_FAIL_MAX (0x3F)
|
||||
|
||||
/* see mpi2_pci.h for the MPI26_PCIE_DEVINFO_ defines used for the DeviceInfo field */
|
||||
|
||||
/* values for PCIe Device Page 0 Flags field */
|
||||
#define MPI26_PCIEDEV0_FLAGS_UNAUTHORIZED_DEVICE (0x8000)
|
||||
#define MPI26_PCIEDEV0_FLAGS_ENABLED_FAST_PATH (0x4000)
|
||||
#define MPI26_PCIEDEV0_FLAGS_FAST_PATH_CAPABLE (0x2000)
|
||||
#define MPI26_PCIEDEV0_FLAGS_ASYNCHRONOUS_NOTIFICATION (0x0400)
|
||||
#define MPI26_PCIEDEV0_FLAGS_ATA_SW_PRESERVATION (0x0200)
|
||||
#define MPI26_PCIEDEV0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
|
||||
#define MPI26_PCIEDEV0_FLAGS_ATA_48BIT_LBA_SUPPORTED (0x0080)
|
||||
#define MPI26_PCIEDEV0_FLAGS_ATA_SMART_SUPPORTED (0x0040)
|
||||
#define MPI26_PCIEDEV0_FLAGS_ATA_NCQ_SUPPORTED (0x0020)
|
||||
#define MPI26_PCIEDEV0_FLAGS_ATA_FUA_SUPPORTED (0x0010)
|
||||
#define MPI26_PCIEDEV0_FLAGS_ENCL_LEVEL_VALID (0x0002)
|
||||
#define MPI26_PCIEDEV0_FLAGS_DEVICE_PRESENT (0x0001)
|
||||
|
||||
/* values for PCIe Device Page 0 SupportedLinkRates field */
|
||||
#define MPI26_PCIEDEV0_LINK_RATE_16_0_SUPPORTED (0x08)
|
||||
#define MPI26_PCIEDEV0_LINK_RATE_8_0_SUPPORTED (0x04)
|
||||
#define MPI26_PCIEDEV0_LINK_RATE_5_0_SUPPORTED (0x02)
|
||||
#define MPI26_PCIEDEV0_LINK_RATE_2_5_SUPPORTED (0x01)
|
||||
|
||||
/* use MPI26_PCIE_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
|
||||
|
||||
|
||||
/* PCIe Device Page 2 */
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PCIEDEV_2
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U16 DevHandle; /* 0x08 */
|
||||
U16 Reserved1; /* 0x0A */
|
||||
U32 MaximumDataTransferSize;/* 0x0C */
|
||||
U32 Capabilities; /* 0x10 */
|
||||
U32 Reserved2; /* 0x14 */
|
||||
} MPI26_CONFIG_PAGE_PCIEDEV_2, MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PCIEDEV_2,
|
||||
Mpi26PCIeDevicePage2_t, MPI2_POINTER pMpi26PCIeDevicePage2_t;
|
||||
|
||||
#define MPI26_PCIEDEVICE2_PAGEVERSION (0x00)
|
||||
|
||||
/* defines for PCIe Device Page 2 Capabilities field */
|
||||
#define MPI26_PCIEDEV2_CAP_SGL_FORMAT (0x00000004)
|
||||
#define MPI26_PCIEDEV2_CAP_BIT_BUCKET_SUPPORT (0x00000002)
|
||||
#define MPI26_PCIEDEV2_CAP_SGL_SUPPORT (0x00000001)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* PCIe Link Config Pages (MPI v2.6 and later)
|
||||
****************************************************************************/
|
||||
|
||||
/* PCIe Link Page 1 */
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_1
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U8 Link; /* 0x08 */
|
||||
U8 Reserved1; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U32 CorrectableErrorCount; /* 0x0C */
|
||||
U16 NonFatalErrorCount; /* 0x10 */
|
||||
U16 Reserved3; /* 0x12 */
|
||||
U16 FatalErrorCount; /* 0x14 */
|
||||
U16 Reserved4; /* 0x16 */
|
||||
} MPI26_CONFIG_PAGE_PCIELINK_1, MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PCIELINK_1,
|
||||
Mpi26PcieLinkPage1_t, MPI2_POINTER pMpi26PcieLinkPage1_t;
|
||||
|
||||
#define MPI26_PCIELINK1_PAGEVERSION (0x00)
|
||||
|
||||
/* PCIe Link Page 2 */
|
||||
|
||||
typedef struct _MPI26_PCIELINK2_LINK_EVENT
|
||||
{
|
||||
U8 LinkEventCode; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U16 Reserved2; /* 0x02 */
|
||||
U32 LinkEventInfo; /* 0x04 */
|
||||
} MPI26_PCIELINK2_LINK_EVENT, MPI2_POINTER PTR_MPI26_PCIELINK2_LINK_EVENT,
|
||||
Mpi26PcieLink2LinkEvent_t, MPI2_POINTER pMpi26PcieLink2LinkEvent_t;
|
||||
|
||||
/* use MPI26_PCIELINK3_EVTCODE_ for the LinkEventCode field */
|
||||
|
||||
|
||||
/*
|
||||
* Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
* one and check the value returned for NumLinkEvents at runtime.
|
||||
*/
|
||||
#ifndef MPI26_PCIELINK2_LINK_EVENT_MAX
|
||||
#define MPI26_PCIELINK2_LINK_EVENT_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_2
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U8 Link; /* 0x08 */
|
||||
U8 Reserved1; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U8 NumLinkEvents; /* 0x0C */
|
||||
U8 Reserved3; /* 0x0D */
|
||||
U16 Reserved4; /* 0x0E */
|
||||
MPI26_PCIELINK2_LINK_EVENT LinkEvent[MPI26_PCIELINK2_LINK_EVENT_MAX]; /* 0x10 */
|
||||
} MPI26_CONFIG_PAGE_PCIELINK_2, MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PCIELINK_2,
|
||||
Mpi26PcieLinkPage2_t, MPI2_POINTER pMpi26PcieLinkPage2_t;
|
||||
|
||||
#define MPI26_PCIELINK2_PAGEVERSION (0x00)
|
||||
|
||||
|
||||
/* PCIe Link Page 3 */
|
||||
|
||||
typedef struct _MPI26_PCIELINK3_LINK_EVENT_CONFIG
|
||||
{
|
||||
U8 LinkEventCode; /* 0x00 */
|
||||
U8 Reserved1; /* 0x01 */
|
||||
U16 Reserved2; /* 0x02 */
|
||||
U8 CounterType; /* 0x04 */
|
||||
U8 ThresholdWindow; /* 0x05 */
|
||||
U8 TimeUnits; /* 0x06 */
|
||||
U8 Reserved3; /* 0x07 */
|
||||
U32 EventThreshold; /* 0x08 */
|
||||
U16 ThresholdFlags; /* 0x0C */
|
||||
U16 Reserved4; /* 0x0E */
|
||||
} MPI26_PCIELINK3_LINK_EVENT_CONFIG, MPI2_POINTER PTR_MPI26_PCIELINK3_LINK_EVENT_CONFIG,
|
||||
Mpi26PcieLink3LinkEventConfig_t, MPI2_POINTER pMpi26PcieLink3LinkEventConfig_t;
|
||||
|
||||
/* values for LinkEventCode field */
|
||||
#define MPI26_PCIELINK3_EVTCODE_NO_EVENT (0x00)
|
||||
#define MPI26_PCIELINK3_EVTCODE_CORRECTABLE_ERROR_RECEIVED (0x01)
|
||||
#define MPI26_PCIELINK3_EVTCODE_NON_FATAL_ERROR_RECEIVED (0x02)
|
||||
#define MPI26_PCIELINK3_EVTCODE_FATAL_ERROR_RECEIVED (0x03)
|
||||
#define MPI26_PCIELINK3_EVTCODE_DATA_LINK_ERROR_DETECTED (0x04)
|
||||
#define MPI26_PCIELINK3_EVTCODE_TRANSACTION_LAYER_ERROR_DETECTED (0x05)
|
||||
#define MPI26_PCIELINK3_EVTCODE_TLP_ECRC_ERROR_DETECTED (0x06)
|
||||
#define MPI26_PCIELINK3_EVTCODE_POISONED_TLP (0x07)
|
||||
#define MPI26_PCIELINK3_EVTCODE_RECEIVED_NAK_DLLP (0x08)
|
||||
#define MPI26_PCIELINK3_EVTCODE_SENT_NAK_DLLP (0x09)
|
||||
#define MPI26_PCIELINK3_EVTCODE_LTSSM_RECOVERY_STATE (0x0A)
|
||||
#define MPI26_PCIELINK3_EVTCODE_LTSSM_RXL0S_STATE (0x0B)
|
||||
#define MPI26_PCIELINK3_EVTCODE_LTSSM_TXL0S_STATE (0x0C)
|
||||
#define MPI26_PCIELINK3_EVTCODE_LTSSM_L1_STATE (0x0D)
|
||||
#define MPI26_PCIELINK3_EVTCODE_LTSSM_DISABLED_STATE (0x0E)
|
||||
#define MPI26_PCIELINK3_EVTCODE_LTSSM_HOT_RESET_STATE (0x0F)
|
||||
#define MPI26_PCIELINK3_EVTCODE_SYSTEM_ERROR (0x10)
|
||||
#define MPI26_PCIELINK3_EVTCODE_DECODE_ERROR (0x11)
|
||||
#define MPI26_PCIELINK3_EVTCODE_DISPARITY_ERROR (0x12)
|
||||
|
||||
/* values for the CounterType field */
|
||||
#define MPI26_PCIELINK3_COUNTER_TYPE_WRAPPING (0x00)
|
||||
#define MPI26_PCIELINK3_COUNTER_TYPE_SATURATING (0x01)
|
||||
#define MPI26_PCIELINK3_COUNTER_TYPE_PEAK_VALUE (0x02)
|
||||
|
||||
/* values for the TimeUnits field */
|
||||
#define MPI26_PCIELINK3_TM_UNITS_10_MICROSECONDS (0x00)
|
||||
#define MPI26_PCIELINK3_TM_UNITS_100_MICROSECONDS (0x01)
|
||||
#define MPI26_PCIELINK3_TM_UNITS_1_MILLISECOND (0x02)
|
||||
#define MPI26_PCIELINK3_TM_UNITS_10_MILLISECONDS (0x03)
|
||||
|
||||
/* values for the ThresholdFlags field */
|
||||
#define MPI26_PCIELINK3_TFLAGS_EVENT_NOTIFY (0x0001)
|
||||
|
||||
/*
|
||||
* Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
* one and check the value returned for NumLinkEvents at runtime.
|
||||
*/
|
||||
#ifndef MPI26_PCIELINK3_LINK_EVENT_MAX
|
||||
#define MPI26_PCIELINK3_LINK_EVENT_MAX (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_CONFIG_PAGE_PCIELINK_3
|
||||
{
|
||||
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
|
||||
U8 Link; /* 0x08 */
|
||||
U8 Reserved1; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U8 NumLinkEvents; /* 0x0C */
|
||||
U8 Reserved3; /* 0x0D */
|
||||
U16 Reserved4; /* 0x0E */
|
||||
MPI26_PCIELINK3_LINK_EVENT_CONFIG LinkEventConfig[MPI26_PCIELINK3_LINK_EVENT_MAX]; /* 0x10 */
|
||||
} MPI26_CONFIG_PAGE_PCIELINK_3, MPI2_POINTER PTR_MPI26_CONFIG_PAGE_PCIELINK_3,
|
||||
Mpi26PcieLinkPage3_t, MPI2_POINTER pMpi26PcieLinkPage3_t;
|
||||
|
||||
#define MPI26_PCIELINK3_PAGEVERSION (0x00)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
* Title: MPI Host Based Discovery messages and structures
|
||||
* Creation Date: October 21, 2009
|
||||
*
|
||||
* mpi2_hbd.h Version: 02.00.03
|
||||
* mpi2_hbd.h Version: 02.00.04
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
@ -59,6 +59,7 @@
|
||||
* HBD Action request, replaced by AdditionalInfo field.
|
||||
* 11-18-11 02.00.02 Incorporating additions for MPI v2.5.
|
||||
* 11-18-14 02.00.03 Updated copyright information.
|
||||
* 02-17-16 02.00.04 Added SAS 4 22.5 gbs speed support.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -129,6 +130,7 @@ typedef struct _MPI2_HBD_ACTION_REQUEST
|
||||
#define MPI2_HBD_MAX_RATE_3_0 (0x09)
|
||||
#define MPI2_HBD_MAX_RATE_6_0 (0x0A)
|
||||
#define MPI25_HBD_MAX_RATE_12_0 (0x0B)
|
||||
#define MPI26_HBD_MAX_RATE_22_5 (0x0C)
|
||||
|
||||
|
||||
/* Host Based Discovery Action Reply Message */
|
||||
|
@ -41,24 +41,25 @@
|
||||
All rights reserved.
|
||||
|
||||
---------------------------------------
|
||||
Header Set Release Version: 02.00.42
|
||||
Header Set Release Date: 01-04-16
|
||||
Header Set Release Version: 02.00.46
|
||||
Header Set Release Date: 09-07-16
|
||||
---------------------------------------
|
||||
|
||||
Filename Current version Prior version
|
||||
---------- --------------- -------------
|
||||
mpi2.h 02.00.42 02.00.41
|
||||
mpi2_cnfg.h 02.00.35 02.00.34
|
||||
mpi2_init.h 02.00.20 02.00.19
|
||||
mpi2_ioc.h 02.00.27 02.00.27
|
||||
mpi2.h 02.00.46 02.00.45
|
||||
mpi2_cnfg.h 02.00.39 02.00.38
|
||||
mpi2_init.h 02.00.21 02.00.21
|
||||
mpi2_ioc.h 02.00.30 02.00.29
|
||||
mpi2_raid.h 02.00.11 02.00.11
|
||||
mpi2_sas.h 02.00.10 02.00.10
|
||||
mpi2_targ.h 02.00.09 02.00.09
|
||||
mpi2_tool.h 02.00.13 02.00.13
|
||||
mpi2_tool.h 02.00.14 02.00.13
|
||||
mpi2_type.h 02.00.01 02.00.01
|
||||
mpi2_ra.h 02.00.01 02.00.01
|
||||
mpi2_hbd.h 02.00.03 02.00.03
|
||||
mpi2_history.txt 02.00.41 02.00.40
|
||||
mpi2_hbd.h 02.00.04 02.00.04
|
||||
mpi2_pci.h 02.00.02 02.00.02
|
||||
mpi2_history.txt 02.00.43 02.00.43
|
||||
|
||||
|
||||
* Date Version Description
|
||||
@ -141,7 +142,8 @@ mpi2.h
|
||||
* Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* 03-16-15 02.00.37 Updated for MPI v2.6.
|
||||
* Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* Added Scratchpad registers to
|
||||
* Added Scratchpad registers and
|
||||
* AtomicRequestDescriptorPost register to
|
||||
* MPI2_SYSTEM_INTERFACE_REGS.
|
||||
* Added MPI2_DIAG_SBR_RELOAD.
|
||||
* Added MPI2_IOCSTATUS_INSUFFICIENT_POWER.
|
||||
@ -151,6 +153,14 @@ mpi2.h
|
||||
* Added V7 HostDiagnostic register defines
|
||||
* 12-15-15 02.00.41 Bumped MPI_HEADER_VERSION_UNIT
|
||||
* 01-04-16 02.00.42 Bumped MPI_HEADER_VERSION_UNIT
|
||||
* 04-05-16 02.00.43 Modified MPI26_DIAG_BOOT_DEVICE_SELECT defines
|
||||
* to be unique within first 32 characters.
|
||||
* Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* 04-10-16 02.00.44 Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* 07-06-16 02.00.45 Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* 09-02-16 02.00.46 Bumped MPI2_HEADER_VERSION_UNIT.
|
||||
* --------------------------------------------------------------------------
|
||||
|
||||
mpi2_cnfg.h
|
||||
@ -323,9 +333,38 @@ mpi2_cnfg.h
|
||||
* Flags field to IO Unit Page 7.
|
||||
* Added IO Unit Page 11.
|
||||
* Added new SAS Phy Event codes
|
||||
* Added PCIe configuration pages.
|
||||
* 03-19-15 02.00.32 Fixed PCIe Link Config page structure names to be
|
||||
* unique in first 32 characters.
|
||||
* 05-25-15 02.00.33 Added more defines for the BiosOptions field of
|
||||
* MPI2_CONFIG_PAGE_BIOS_1.
|
||||
* 08-25-15 02.00.34 Added PCIe Device Page 2 SGL format capability.
|
||||
* 12-18-15 02.00.35 Added SATADeviceWaitTime to SAS IO Unit Page 4.
|
||||
* 01-21-16 02.00.36 Added/modified MPI2_MFGPAGE_DEVID_SAS defines.
|
||||
* Added Link field to PCIe Link Pages
|
||||
* Added EnclosureLevel and ConnectorName to PCIe
|
||||
* Device Page 0.
|
||||
* Added define for PCIE IoUnit page 1 max rate shift.
|
||||
* Added comment for reserved ExtPageTypes.
|
||||
* Added SAS 4 22.5 gbs speed support.
|
||||
* Added PCIe 4 16.0 GT/sec speec support.
|
||||
* Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* Added NegotiatedLinkRate and NegotiatedPortWidth to
|
||||
* PCIe device page 0.
|
||||
* 04-10-16 02.00.37 Fixed MPI2_MFGPAGE_DEVID_SAS3616/3708 defines
|
||||
* 07-01-16 02.00.38 Added Manufacturing page 7 Connector types.
|
||||
* Changed declaration of ConnectorName in PCIe DevicePage0
|
||||
* to match SAS DevicePage 0.
|
||||
* Added SATADeviceWaitTime to IO Unit Page 11.
|
||||
* Added MPI26_MFGPAGE_DEVID_SAS4008
|
||||
* Added x16 PCIe width to IO Unit Page 7
|
||||
* Added LINKFLAGS to control SRIS in PCIe IO Unit page 1
|
||||
* phy data.
|
||||
* Added InitStatus to PCIe IO Unit Page 1 header.
|
||||
* 09-01-16 02.00.39 Added MPI26_CONFIG_PAGE_ENCLOSURE_0 and related defines.
|
||||
* Added MPI26_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE and
|
||||
* MPI26_ENCLOS_PGAD_FORM_HANDLE page address formats.
|
||||
* --------------------------------------------------------------------------
|
||||
|
||||
mpi2_init.h
|
||||
@ -365,6 +404,8 @@ mpi2_init.h
|
||||
* 08-26-15 02.00.18 Added SCSITASKMGMT_MSGFLAGS for Target Reset.
|
||||
* 12-18-15 02.00.19 Added EEDPObservedValue added to SCSI IO Reply message.
|
||||
* 01-04-16 02.00.20 Modified EEDP reported values in SCSI IO Reply message.
|
||||
* 01-21-16 02.00.21 Modified MPI26_SCSITASKMGMT_MSGFLAGS_PCIE* defines to
|
||||
* be unique within first 32 characters.
|
||||
* --------------------------------------------------------------------------
|
||||
|
||||
mpi2_ioc.h
|
||||
@ -491,9 +532,30 @@ mpi2_ioc.h
|
||||
* MPI26_EVENT_DATA_PCIE_LINK_COUNTER.
|
||||
* Added MPI26_CTRL_OP_SHUTDOWN.
|
||||
* Added MPI26_CTRL_OP_LINK_CLEAR_ERROR_LOG
|
||||
* Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS
|
||||
* Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS and
|
||||
* MPI26_FW_HEADER_PID_FAMILY_3516_SAS.
|
||||
* 08-25-15 02.00.27 Added IC ARCH Class based signature defines.
|
||||
* --------------------------------------------------------------------------
|
||||
* Added MPI26_EVENT_PCIE_ENUM_ES_RESOURCES_EXHAUSTED event.
|
||||
* Added ConigurationFlags field to IOCInit message to
|
||||
* support NVMe SGL format control.
|
||||
* Added PCIe SRIOV support.
|
||||
* 02-17-16 02.00.28 Added SAS 4 22.5 gbs speed support.
|
||||
* Added PCIe 4 16.0 GT/sec speec support.
|
||||
* Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* 07-01-16 02.00.29 Added Archclass for 4008 product.
|
||||
* Added IOCException MPI2_IOCFACTS_EXCEPT_PCIE_DISABLED.
|
||||
* 08-23-16 02.00.30 Added new defines for the ImageType field of FWDownload
|
||||
* Request Message.
|
||||
* Added new defines for the ImageType field of FWUpload
|
||||
* Request Message.
|
||||
* Added new values for the RegionType field in the Layout
|
||||
* Data sections of the FLASH Layout Extended Image Data.
|
||||
* Added new defines for the ReasonCode field of
|
||||
* Active Cable Exception Event.
|
||||
* Added MPI2_EVENT_ENCL_DEVICE_STATUS_CHANGE and
|
||||
* MPI26_EVENT_DATA_ENCL_DEV_STATUS_CHANGE.
|
||||
* --------------------------------------------------------------------------
|
||||
|
||||
mpi2_raid.h
|
||||
* 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
|
||||
@ -581,6 +643,8 @@ mpi2_tool.h
|
||||
* 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info.
|
||||
* 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC.
|
||||
* 11-18-14 02.00.13 Updated copyright information.
|
||||
* 08-25-16 02.00.14 Added new values for the Flags field of Toolbox Clean
|
||||
* Tool Request Message.
|
||||
* --------------------------------------------------------------------------
|
||||
|
||||
mpi2_type.h
|
||||
@ -599,24 +663,33 @@ mpi2_hbd.h
|
||||
* HBD Action request, replaced by AdditionalInfo field.
|
||||
* 11-18-11 02.00.02 Incorporating additions for MPI v2.5.
|
||||
* 11-18-14 02.00.03 Updated copyright information.
|
||||
* 02-17-16 02.00.04 Added SAS 4 22.5 gbs speed support.
|
||||
* --------------------------------------------------------------------------
|
||||
|
||||
mpi2_pci.h
|
||||
* 03-16-15 02.00.00 Initial version.
|
||||
* 02-17-16 02.00.01 Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* 07-01-16 02.00.02 Added MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP to
|
||||
* NVME Encapsulated Request.
|
||||
* --------------------------------------------------------------------------
|
||||
|
||||
mpi2_history.txt Parts list history
|
||||
|
||||
Filename 02.00.42
|
||||
---------- --------
|
||||
mpi2.h 02.00.42
|
||||
mpi2_cnfg.h 02.00.35
|
||||
mpi2_init.h 02.00.20
|
||||
mpi2_ioc.h 02.00.27
|
||||
mpi2_raid.h 02.00.11
|
||||
mpi2_sas.h 02.00.10
|
||||
mpi2_targ.h 02.00.09
|
||||
mpi2_tool.h 02.00.13
|
||||
mpi2_type.h 02.00.01
|
||||
mpi2_ra.h 02.00.01
|
||||
mpi2_hbd.h 02.00.03
|
||||
Filename 02.00.46 02.00.45 02.00.44 02.00.43 02.00.42
|
||||
---------- -------- -------- -------- -------- --------
|
||||
mpi2.h 02.00.46 02.00.45 02.00.44 02.00.43 02.00.42
|
||||
mpi2_cnfg.h 02.00.39 02.00.38 02.00.37 02.00.36 02.00.35
|
||||
mpi2_init.h 02.00.21 02.00.21 02.00.21 02.00.21 02.00.20
|
||||
mpi2_ioc.h 02.00.30 02.00.29 02.00.28 02.00.28 02.00.27
|
||||
mpi2_raid.h 02.00.11 02.00.11 02.00.11 02.00.11 02.00.11
|
||||
mpi2_sas.h 02.00.10 02.00.10 02.00.10 02.00.10 02.00.10
|
||||
mpi2_targ.h 02.00.09 02.00.09 02.00.09 02.00.09 02.00.09
|
||||
mpi2_tool.h 02.00.14 02.00.13 02.00.13 02.00.13 02.00.13
|
||||
mpi2_type.h 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01
|
||||
mpi2_ra.h 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01
|
||||
mpi2_hbd.h 02.00.04 02.00.04 02.00.04 02.00.04 02.00.03
|
||||
mpi2_pci.h 02.00.02 02.00.02 02.00.01 02.00.01 02.00.00
|
||||
|
||||
Filename 02.00.41 02.00.40 02.00.39 02.00.38 02.00.37 02.00.36
|
||||
---------- -------- -------- -------- -------- -------- --------
|
||||
@ -631,6 +704,7 @@ mpi2_tool.h 02.00.13 02.00.13 02.00.13 02.00.13 02.00.13 02.00.13
|
||||
mpi2_type.h 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01
|
||||
mpi2_ra.h 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01
|
||||
mpi2_hbd.h 02.00.03 02.00.03 02.00.03 02.00.03 02.00.03 02.00.03
|
||||
mpi2_pci.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00
|
||||
|
||||
Filename 02.00.35 02.00.34 02.00.33 02.00.32 02.00.31 02.00.30
|
||||
---------- -------- -------- -------- -------- -------- --------
|
||||
|
@ -42,7 +42,7 @@
|
||||
* Title: MPI SCSI initiator mode messages and structures
|
||||
* Creation Date: June 23, 2006
|
||||
*
|
||||
* mpi2_init.h Version: 02.00.20
|
||||
* mpi2_init.h Version: 02.00.21
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
@ -62,7 +62,7 @@
|
||||
* 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t.
|
||||
* 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO
|
||||
* Control field Task Attribute flags.
|
||||
* Moved LUN field defines to mpi2.h becasue they are
|
||||
* Moved LUN field defines to mpi2.h because they are
|
||||
* common to many structures.
|
||||
* 05-06-09 02.00.07 Changed task management type of Query Unit Attention to
|
||||
* Query Asynchronous Event.
|
||||
@ -90,6 +90,8 @@
|
||||
* 08-26-15 02.00.18 Added SCSITASKMGMT_MSGFLAGS for Target Reset.
|
||||
* 12-18-15 02.00.19 Added EEDPObservedValue added to SCSI IO Reply message.
|
||||
* 01-04-16 02.00.20 Modified EEDP reported values in SCSI IO Reply message.
|
||||
* 01-21-16 02.00.21 Modified MPI26_SCSITASKMGMT_MSGFLAGS_PCIE* defines to
|
||||
* be unique within first 32 characters.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -491,12 +493,13 @@ typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST
|
||||
#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT)
|
||||
|
||||
/* MsgFlags bits */
|
||||
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18)
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00)
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18)
|
||||
#define MPI26_SCSITASKMGMT_MSGFLAGS_HOT_RESET_PCIE (0x00)
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00)
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01)
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08)
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10)
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08)
|
||||
#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10)
|
||||
#define MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE (0x18)
|
||||
|
||||
|
||||
/* SCSI Task Management Reply Message */
|
||||
|
@ -42,7 +42,7 @@
|
||||
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
|
||||
* Creation Date: October 11, 2006
|
||||
*
|
||||
* mpi2_ioc.h Version: 02.00.27
|
||||
* mpi2_ioc.h Version: 02.00.30
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
@ -177,9 +177,29 @@
|
||||
* MPI26_EVENT_DATA_PCIE_LINK_COUNTER.
|
||||
* Added MPI26_CTRL_OP_SHUTDOWN.
|
||||
* Added MPI26_CTRL_OP_LINK_CLEAR_ERROR_LOG
|
||||
* Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS
|
||||
* 08-25-15 02.00.27 Added IC ARCH Class based signature defines
|
||||
*
|
||||
* Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS and
|
||||
* MPI26_FW_HEADER_PID_FAMILY_3516_SAS.
|
||||
* 08-25-15 02.00.27 Added IC ARCH Class based signature defines.
|
||||
* Added MPI26_EVENT_PCIE_ENUM_ES_RESOURCES_EXHAUSTED event.
|
||||
* Added ConigurationFlags field to IOCInit message to
|
||||
* support NVMe SGL format control.
|
||||
* Added PCIe SRIOV support.
|
||||
* 02-17-16 02.00.28 Added SAS 4 22.5 gbs speed support.
|
||||
* Added PCIe 4 16.0 GT/sec speec support.
|
||||
* Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* 07-01-16 02.00.29 Added Archclass for 4008 product.
|
||||
* Added IOCException MPI2_IOCFACTS_EXCEPT_PCIE_DISABLED
|
||||
* 08-23-16 02.00.30 Added new defines for the ImageType field of FWDownload
|
||||
* Request Message.
|
||||
* Added new defines for the ImageType field of FWUpload
|
||||
* Request Message.
|
||||
* Added new values for the RegionType field in the Layout
|
||||
* Data sections of the FLASH Layout Extended Image Data.
|
||||
* Added new defines for the ReasonCode field of
|
||||
* Active Cable Exception Event.
|
||||
* Added MPI2_EVENT_ENCL_DEVICE_STATUS_CHANGE and
|
||||
* MPI26_EVENT_DATA_ENCL_DEV_STATUS_CHANGE.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -251,6 +271,9 @@ typedef struct _MPI2_IOC_INIT_REQUEST
|
||||
#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF)
|
||||
#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0)
|
||||
|
||||
/* ConfigurationFlags */
|
||||
#define MPI26_IOCINIT_CFGFLAGS_NVME_SGL_FORMAT (0x0001)
|
||||
|
||||
/* minimum depth for a Reply Descriptor Post Queue */
|
||||
#define MPI2_RDPQ_DEPTH_MIN (16)
|
||||
|
||||
@ -363,6 +386,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY
|
||||
#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0)
|
||||
|
||||
/* IOCExceptions */
|
||||
#define MPI2_IOCFACTS_EXCEPT_PCIE_DISABLED (0x0400)
|
||||
#define MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0200)
|
||||
#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100)
|
||||
|
||||
@ -383,6 +407,8 @@ typedef struct _MPI2_IOC_FACTS_REPLY
|
||||
/* ProductID field uses MPI2_FW_HEADER_PID_ */
|
||||
|
||||
/* IOCCapabilities */
|
||||
#define MPI26_IOCFACTS_CAPABILITY_PCIE_SRIOV (0x00100000)
|
||||
#define MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ (0x00080000)
|
||||
#define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE (0x00040000)
|
||||
#define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE (0x00020000)
|
||||
#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000)
|
||||
@ -400,6 +426,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY
|
||||
#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
|
||||
|
||||
/* ProtocolFlags */
|
||||
#define MPI2_IOCFACTS_PROTOCOL_NVME_DEVICES (0x0008) /* MPI v2.6 and later */
|
||||
#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002)
|
||||
#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001)
|
||||
|
||||
@ -452,6 +479,7 @@ typedef struct _MPI2_PORT_FACTS_REPLY
|
||||
#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20)
|
||||
#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30)
|
||||
#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31)
|
||||
#define MPI2_PORTFACTS_PORTTYPE_TRI_MODE (0x40) /* MPI v2.6 and later */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
@ -564,6 +592,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
|
||||
#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019)
|
||||
#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C)
|
||||
#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D)
|
||||
#define MPI2_EVENT_ENCL_DEVICE_STATUS_CHANGE (0x001D) /* MPI v2.6 and later */
|
||||
#define MPI2_EVENT_IR_VOLUME (0x001E)
|
||||
#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F)
|
||||
#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020)
|
||||
@ -576,6 +605,10 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
|
||||
#define MPI2_EVENT_TEMP_THRESHOLD (0x0027)
|
||||
#define MPI2_EVENT_HOST_MESSAGE (0x0028)
|
||||
#define MPI2_EVENT_POWER_PERFORMANCE_CHANGE (0x0029)
|
||||
#define MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE (0x0030) /* MPI v2.6 and later */
|
||||
#define MPI2_EVENT_PCIE_ENUMERATION (0x0031) /* MPI v2.6 and later */
|
||||
#define MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST (0x0032) /* MPI v2.6 and later */
|
||||
#define MPI2_EVENT_PCIE_LINK_COUNTER (0x0033) /* MPI v2.6 and later */
|
||||
#define MPI2_EVENT_ACTIVE_CABLE_EXCEPTION (0x0034) /* MPI v2.6 and later */
|
||||
#define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E)
|
||||
#define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F)
|
||||
@ -688,11 +721,9 @@ typedef struct _MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT
|
||||
MPI2_POINTER pMpi26EventDataActiveCableExcept_t;
|
||||
|
||||
/* defines for ReasonCode field */
|
||||
#define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00)
|
||||
#define MPI26_EVENT_ACTIVE_CABLE_PRESENT (0x01)
|
||||
#define MPI26_EVENT_ACTIVE_CABLE_DEGRADED (0x02)
|
||||
|
||||
|
||||
#define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00)
|
||||
#define MPI26_EVENT_ACTIVE_CABLE_PRESENT (0x01)
|
||||
#define MPI26_EVENT_ACTIVE_CABLE_DEGRADED (0x02)
|
||||
|
||||
/* Hard Reset Received Event data */
|
||||
|
||||
@ -1048,6 +1079,7 @@ typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST
|
||||
#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09)
|
||||
#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A)
|
||||
#define MPI25_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B)
|
||||
#define MPI26_EVENT_SAS_TOPO_LR_RATE_22_5 (0x0C)
|
||||
|
||||
/* values for the PhyStatus field */
|
||||
#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80)
|
||||
@ -1075,12 +1107,19 @@ typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE
|
||||
} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
|
||||
MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
|
||||
Mpi2EventDataSasEnclDevStatusChange_t,
|
||||
MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t;
|
||||
MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t,
|
||||
MPI26_EVENT_DATA_ENCL_DEV_STATUS_CHANGE,
|
||||
MPI2_POINTER PTR_MPI26_EVENT_DATA_ENCL_DEV_STATUS_CHANGE,
|
||||
Mpi26EventDataEnclDevStatusChange_t,
|
||||
MPI2_POINTER pMpi26EventDataEnclDevStatusChange_t;
|
||||
|
||||
/* SAS Enclosure Device Status Change event ReasonCode values */
|
||||
#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01)
|
||||
#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02)
|
||||
|
||||
/* Enclosure Device Status Change event ReasonCode values */
|
||||
#define MPI26_EVENT_ENCL_RC_ADDED (0x01)
|
||||
#define MPI26_EVENT_ENCL_RC_NOT_RESPONDING (0x02)
|
||||
|
||||
/* SAS PHY Counter Event data */
|
||||
|
||||
@ -1168,6 +1207,167 @@ typedef struct _MPI2_EVENT_DATA_HBD_PHY
|
||||
#define MPI2_EVENT_HBD_DT_SAS (0x01)
|
||||
|
||||
|
||||
/* PCIe Device Status Change Event data (MPI v2.6 and later) */
|
||||
|
||||
typedef struct _MPI26_EVENT_DATA_PCIE_DEVICE_STATUS_CHANGE
|
||||
{
|
||||
U16 TaskTag; /* 0x00 */
|
||||
U8 ReasonCode; /* 0x02 */
|
||||
U8 PhysicalPort; /* 0x03 */
|
||||
U8 ASC; /* 0x04 */
|
||||
U8 ASCQ; /* 0x05 */
|
||||
U16 DevHandle; /* 0x06 */
|
||||
U32 Reserved2; /* 0x08 */
|
||||
U64 WWID; /* 0x0C */
|
||||
U8 LUN[8]; /* 0x14 */
|
||||
} MPI26_EVENT_DATA_PCIE_DEVICE_STATUS_CHANGE,
|
||||
MPI2_POINTER PTR_MPI26_EVENT_DATA_PCIE_DEVICE_STATUS_CHANGE,
|
||||
Mpi26EventDataPCIeDeviceStatusChange_t,
|
||||
MPI2_POINTER pMpi26EventDataPCIeDeviceStatusChange_t;
|
||||
|
||||
/* PCIe Device Status Change Event data ReasonCode values */
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_SMART_DATA (0x05)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_UNSUPPORTED (0x07)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_TASK_ABORT_INTERNAL (0x09)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F)
|
||||
#define MPI26_EVENT_PCIDEV_STAT_RC_DEV_INIT_FAILURE (0x10)
|
||||
|
||||
|
||||
/* PCIe Enumeration Event data (MPI v2.6 and later) */
|
||||
|
||||
typedef struct _MPI26_EVENT_DATA_PCIE_ENUMERATION
|
||||
{
|
||||
U8 Flags; /* 0x00 */
|
||||
U8 ReasonCode; /* 0x01 */
|
||||
U8 PhysicalPort; /* 0x02 */
|
||||
U8 Reserved1; /* 0x03 */
|
||||
U32 EnumerationStatus; /* 0x04 */
|
||||
} MPI26_EVENT_DATA_PCIE_ENUMERATION,
|
||||
MPI2_POINTER PTR_MPI26_EVENT_DATA_PCIE_ENUMERATION,
|
||||
Mpi26EventDataPCIeEnumeration_t,
|
||||
MPI2_POINTER pMpi26EventDataPCIeEnumeration_t;
|
||||
|
||||
/* PCIe Enumeration Event data Flags values */
|
||||
#define MPI26_EVENT_PCIE_ENUM_DEVICE_CHANGE (0x02)
|
||||
#define MPI26_EVENT_PCIE_ENUM_IN_PROGRESS (0x01)
|
||||
|
||||
/* PCIe Enumeration Event data ReasonCode values */
|
||||
#define MPI26_EVENT_PCIE_ENUM_RC_STARTED (0x01)
|
||||
#define MPI26_EVENT_PCIE_ENUM_RC_COMPLETED (0x02)
|
||||
|
||||
/* PCIe Enumeration Event data EnumerationStatus values */
|
||||
#define MPI26_EVENT_PCIE_ENUM_ES_MAX_SWITCHES_EXCEED (0x40000000)
|
||||
#define MPI26_EVENT_PCIE_ENUM_ES_MAX_DEVICES_EXCEED (0x20000000)
|
||||
#define MPI26_EVENT_PCIE_ENUM_ES_RESOURCES_EXHAUSTED (0x10000000)
|
||||
|
||||
|
||||
/* PCIe Topology Change List Event data (MPI v2.6 and later) */
|
||||
|
||||
/*
|
||||
* Host code (drivers, BIOS, utilities, etc.) should leave this define set to
|
||||
* one and check NumEntries at runtime.
|
||||
*/
|
||||
#ifndef MPI26_EVENT_PCIE_TOPO_PORT_COUNT
|
||||
#define MPI26_EVENT_PCIE_TOPO_PORT_COUNT (1)
|
||||
#endif
|
||||
|
||||
typedef struct _MPI26_EVENT_PCIE_TOPO_PORT_ENTRY
|
||||
{
|
||||
U16 AttachedDevHandle; /* 0x00 */
|
||||
U8 PortStatus; /* 0x02 */
|
||||
U8 Reserved1; /* 0x03 */
|
||||
U8 CurrentPortInfo; /* 0x04 */
|
||||
U8 Reserved2; /* 0x05 */
|
||||
U8 PreviousPortInfo; /* 0x06 */
|
||||
U8 Reserved3; /* 0x07 */
|
||||
} MPI26_EVENT_PCIE_TOPO_PORT_ENTRY,
|
||||
MPI2_POINTER PTR_MPI26_EVENT_PCIE_TOPO_PORT_ENTRY,
|
||||
Mpi26EventPCIeTopoPortEntry_t,
|
||||
MPI2_POINTER pMpi26EventPCIeTopoPortEntry_t;
|
||||
|
||||
/* PCIe Topology Change List Event data PortStatus values */
|
||||
#define MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED (0x01)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PS_NOT_RESPONDING (0x02)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PS_PORT_CHANGED (0x03)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PS_NO_CHANGE (0x04)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING (0x05)
|
||||
|
||||
/* PCIe Topology Change List Event data defines for CurrentPortInfo and PreviousPortInfo */
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_LANE_MASK (0xF0)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_LANES_UNKNOWN (0x00)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_1_LANE (0x10)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_2_LANES (0x20)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_4_LANES (0x30)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_8_LANES (0x40)
|
||||
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_MASK (0x0F)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_UNKNOWN (0x00)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_DISABLED (0x01)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_2_5 (0x02)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_5_0 (0x03)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_8_0 (0x04)
|
||||
#define MPI26_EVENT_PCIE_TOPO_PI_RATE_16_0 (0x05)
|
||||
|
||||
typedef struct _MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST
|
||||
{
|
||||
U16 EnclosureHandle; /* 0x00 */
|
||||
U16 SwitchDevHandle; /* 0x02 */
|
||||
U8 NumPorts; /* 0x04 */
|
||||
U8 Reserved1; /* 0x05 */
|
||||
U16 Reserved2; /* 0x06 */
|
||||
U8 NumEntries; /* 0x08 */
|
||||
U8 StartPortNum; /* 0x09 */
|
||||
U8 SwitchStatus; /* 0x0A */
|
||||
U8 PhysicalPort; /* 0x0B */
|
||||
MPI26_EVENT_PCIE_TOPO_PORT_ENTRY PortEntry[MPI26_EVENT_PCIE_TOPO_PORT_COUNT]; /* 0x0C */
|
||||
} MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST,
|
||||
MPI2_POINTER PTR_MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST,
|
||||
Mpi26EventDataPCIeTopologyChangeList_t,
|
||||
MPI2_POINTER pMpi26EventDataPCIeTopologyChangeList_t;
|
||||
|
||||
/* PCIe Topology Change List Event data SwitchStatus values */
|
||||
#define MPI26_EVENT_PCIE_TOPO_SS_NO_PCIE_SWITCH (0x00)
|
||||
#define MPI26_EVENT_PCIE_TOPO_SS_ADDED (0x01)
|
||||
#define MPI26_EVENT_PCIE_TOPO_SS_NOT_RESPONDING (0x02)
|
||||
#define MPI26_EVENT_PCIE_TOPO_SS_RESPONDING (0x03)
|
||||
#define MPI26_EVENT_PCIE_TOPO_SS_DELAY_NOT_RESPONDING (0x04)
|
||||
|
||||
/* PCIe Link Counter Event data (MPI v2.6 and later) */
|
||||
|
||||
typedef struct _MPI26_EVENT_DATA_PCIE_LINK_COUNTER
|
||||
{
|
||||
U64 TimeStamp; /* 0x00 */
|
||||
U32 Reserved1; /* 0x08 */
|
||||
U8 LinkEventCode; /* 0x0C */
|
||||
U8 LinkNum; /* 0x0D */
|
||||
U16 Reserved2; /* 0x0E */
|
||||
U32 LinkEventInfo; /* 0x10 */
|
||||
U8 CounterType; /* 0x14 */
|
||||
U8 ThresholdWindow; /* 0x15 */
|
||||
U8 TimeUnits; /* 0x16 */
|
||||
U8 Reserved3; /* 0x17 */
|
||||
U32 EventThreshold; /* 0x18 */
|
||||
U16 ThresholdFlags; /* 0x1C */
|
||||
U16 Reserved4; /* 0x1E */
|
||||
} MPI26_EVENT_DATA_PCIE_LINK_COUNTER,
|
||||
MPI2_POINTER PTR_MPI26_EVENT_DATA_PCIE_LINK_COUNTER,
|
||||
Mpi26EventDataPcieLinkCounter_t, MPI2_POINTER pMpi26EventDataPcieLinkCounter_t;
|
||||
|
||||
|
||||
/* use MPI26_PCIELINK3_EVTCODE_ values from mpi2_cnfg.h for the LinkEventCode field */
|
||||
|
||||
/* use MPI26_PCIELINK3_COUNTER_TYPE_ values from mpi2_cnfg.h for the CounterType field */
|
||||
|
||||
/* use MPI26_PCIELINK3_TIME_UNITS_ values from mpi2_cnfg.h for the TimeUnits field */
|
||||
|
||||
/* use MPI26_PCIELINK3_TFLAGS_ values from mpi2_cnfg.h for the ThresholdFlags field */
|
||||
|
||||
/****************************************************************************
|
||||
* EventAck message
|
||||
****************************************************************************/
|
||||
@ -1293,6 +1493,13 @@ typedef struct _MPI2_FW_DOWNLOAD_REQUEST
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY (0x0C) /* MPI v2.5 and newer */
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_SBR (0x0E)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_SBR_BACKUP (0x0F)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_HIIM (0x10)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_HIIA (0x11)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_CTLR (0x12)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_IMR_FIRMWARE (0x13)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_MR_NVDATA (0x14)
|
||||
#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
|
||||
|
||||
/* MPI v2.0 FWDownload TransactionContext Element */
|
||||
@ -1386,6 +1593,13 @@ typedef struct _MPI2_FW_UPLOAD_REQUEST
|
||||
#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_CBB_BACKUP (0x0D)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_SBR (0x0E)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_SBR_BACKUP (0x0F)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_HIIM (0x10)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_HIIA (0x11)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_CTLR (0x12)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_IMR_FIRMWARE (0x13)
|
||||
#define MPI2_FW_UPLOAD_ITYPE_MR_NVDATA (0x14)
|
||||
|
||||
/* MPI v2.0 FWUpload TransactionContext Element */
|
||||
typedef struct _MPI2_FW_UPLOAD_TCSGE
|
||||
@ -1509,8 +1723,10 @@ typedef struct _MPI2_FW_IMAGE_HEADER
|
||||
#define MPI26_FW_HEADER_SIGNATURE0_ARC_0 (0x5A)
|
||||
#define MPI26_FW_HEADER_SIGNATURE0_ARC_1 (0x00)
|
||||
#define MPI26_FW_HEADER_SIGNATURE0_ARC_2 (0x01)
|
||||
#define MPI26_FW_HEADER_SIGNATURE0_ARC_3 (0x02)
|
||||
#define MPI26_FW_HEADER_SIGNATURE0 (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_0) // legacy (0x5AEAA55A)
|
||||
#define MPI26_FW_HEADER_SIGNATURE0_3516 (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_1)
|
||||
#define MPI26_FW_HEADER_SIGNATURE0_4008 (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_3)
|
||||
|
||||
/* Signature1 field */
|
||||
#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08)
|
||||
@ -1665,7 +1881,13 @@ typedef struct _MPI2_FLASH_LAYOUT_DATA
|
||||
#define MPI2_FLASH_REGION_COMMON_BOOT_BLOCK (0x0A)
|
||||
#define MPI2_FLASH_REGION_INIT (MPI2_FLASH_REGION_COMMON_BOOT_BLOCK) /* older name */
|
||||
#define MPI2_FLASH_REGION_CBB_BACKUP (0x0D)
|
||||
|
||||
#define MPI2_FLASH_REGION_SBR (0x0E)
|
||||
#define MPI2_FLASH_REGION_SBR_BACKUP (0x0F)
|
||||
#define MPI2_FLASH_REGION_HIIM (0x10)
|
||||
#define MPI2_FLASH_REGION_HIIA (0x11)
|
||||
#define MPI2_FLASH_REGION_CTLR (0x12)
|
||||
#define MPI2_FLASH_REGION_IMR_FIRMWARE (0x13)
|
||||
#define MPI2_FLASH_REGION_MR_NVDATA (0x14)
|
||||
|
||||
/* ImageRevision */
|
||||
#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00)
|
||||
@ -1960,6 +2182,8 @@ typedef struct _MPI26_IOUNIT_CONTROL_REQUEST
|
||||
#define MPI26_CTRL_OP_DEV_ENABLE_PERSIST_CONNECTION (0x17)
|
||||
#define MPI26_CTRL_OP_DEV_DISABLE_PERSIST_CONNECTION (0x18)
|
||||
#define MPI26_CTRL_OP_DEV_CLOSE_PERSIST_CONNECTION (0x19)
|
||||
#define MPI26_CTRL_OP_ENABLE_NVME_SGL_FORMAT (0x1A)
|
||||
#define MPI26_CTRL_OP_DISABLE_NVME_SGL_FORMAT (0x1B)
|
||||
#define MPI26_CTRL_OP_PRODUCT_SPECIFIC_MIN (0x80)
|
||||
|
||||
/* values for the PrimFlags field */
|
||||
|
151
sys/dev/mpr/mpi/mpi2_pci.h
Executable file
151
sys/dev/mpr/mpi/mpi2_pci.h
Executable file
@ -0,0 +1,151 @@
|
||||
/*-
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2016 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2016 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Name: mpi2_pci.h
|
||||
* Title: MPI PCIe Attached Devices structures and definitions.
|
||||
* Creation Date: October 9, 2012
|
||||
*
|
||||
* mpi2_pci.h Version: 02.00.02
|
||||
*
|
||||
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
|
||||
* prefix are for use only on MPI v2.5 products, and must not be used
|
||||
* with MPI v2.0 products. Unless otherwise noted, names beginning with
|
||||
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
*
|
||||
* Date Version Description
|
||||
* -------- -------- ------------------------------------------------------
|
||||
* 03-16-15 02.00.00 Initial version.
|
||||
* 02-17-16 02.00.01 Removed AHCI support.
|
||||
* Removed SOP support.
|
||||
* 07-01-16 02.00.02 Added MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP to
|
||||
* NVME Encapsulated Request.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPI2_PCI_H
|
||||
#define MPI2_PCI_H
|
||||
|
||||
|
||||
/*
|
||||
* Values for the PCIe DeviceInfo field used in PCIe Device Status Change Event
|
||||
* data and PCIe Configuration pages.
|
||||
*/
|
||||
#define MPI26_PCIE_DEVINFO_DIRECT_ATTACH (0x00000010)
|
||||
|
||||
#define MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE (0x0000000F)
|
||||
#define MPI26_PCIE_DEVINFO_NO_DEVICE (0x00000000)
|
||||
#define MPI26_PCIE_DEVINFO_PCI_SWITCH (0x00000001)
|
||||
#define MPI26_PCIE_DEVINFO_NVME (0x00000003)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* NVMe Encapsulated message
|
||||
****************************************************************************/
|
||||
|
||||
/* NVME Encapsulated Request Message */
|
||||
typedef struct _MPI26_NVME_ENCAPSULATED_REQUEST
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 ChainOffset; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 EncapsulatedCommandLength; /* 0x04 */
|
||||
U8 Reserved1; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U32 Reserved3; /* 0x0C */
|
||||
U64 ErrorResponseBaseAddress; /* 0x10 */
|
||||
U16 ErrorResponseAllocationLength; /* 0x18 */
|
||||
U16 Flags; /* 0x1A */
|
||||
U32 DataLength; /* 0x1C */
|
||||
U8 NVMe_Command[4]; /* 0x20 */ /* variable length */
|
||||
|
||||
} MPI26_NVME_ENCAPSULATED_REQUEST, MPI2_POINTER PTR_MPI26_NVME_ENCAPSULATED_REQUEST,
|
||||
Mpi26NVMeEncapsulatedRequest_t, MPI2_POINTER pMpi26NVMeEncapsulatedRequest_t;
|
||||
|
||||
/* defines for the Flags field */
|
||||
#define MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP (0x0020)
|
||||
/* Submission Queue Type*/
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_MASK (0x0010)
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_IO (0x0000)
|
||||
#define MPI26_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0010)
|
||||
/* Error Response Address Space */
|
||||
#define MPI26_NVME_FLAGS_MASK_ERROR_RSP_ADDR (0x000C)
|
||||
#define MPI26_NVME_FLAGS_SYSTEM_RSP_ADDR (0x0000)
|
||||
#define MPI26_NVME_FLAGS_IOCPLB_RSP_ADDR (0x0008)
|
||||
#define MPI26_NVME_FLAGS_IOCPLBNTA_RSP_ADDR (0x000C)
|
||||
/* Data Direction*/
|
||||
#define MPI26_NVME_FLAGS_DATADIRECTION_MASK (0x0003)
|
||||
#define MPI26_NVME_FLAGS_NODATATRANSFER (0x0000)
|
||||
#define MPI26_NVME_FLAGS_WRITE (0x0001)
|
||||
#define MPI26_NVME_FLAGS_READ (0x0002)
|
||||
#define MPI26_NVME_FLAGS_BIDIRECTIONAL (0x0003)
|
||||
|
||||
|
||||
/* NVMe Encapuslated Reply Message */
|
||||
typedef struct _MPI26_NVME_ENCAPSULATED_ERROR_REPLY
|
||||
{
|
||||
U16 DevHandle; /* 0x00 */
|
||||
U8 MsgLength; /* 0x02 */
|
||||
U8 Function; /* 0x03 */
|
||||
U16 EncapsulatedCommandLength; /* 0x04 */
|
||||
U8 Reserved1; /* 0x06 */
|
||||
U8 MsgFlags; /* 0x07 */
|
||||
U8 VP_ID; /* 0x08 */
|
||||
U8 VF_ID; /* 0x09 */
|
||||
U16 Reserved2; /* 0x0A */
|
||||
U16 Reserved3; /* 0x0C */
|
||||
U16 IOCStatus; /* 0x0E */
|
||||
U32 IOCLogInfo; /* 0x10 */
|
||||
U16 ErrorResponseCount; /* 0x14 */
|
||||
U16 Reserved4; /* 0x16 */
|
||||
} MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
|
||||
MPI2_POINTER PTR_MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
|
||||
Mpi26NVMeEncapsulatedErrorReply_t,
|
||||
MPI2_POINTER pMpi26NVMeEncapsulatedErrorReply_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
* Title: MPI diagnostic tool structures and definitions
|
||||
* Creation Date: March 26, 2007
|
||||
*
|
||||
* mpi2_tool.h Version: 02.00.13
|
||||
* mpi2_tool.h Version: 02.00.14
|
||||
*
|
||||
* Version History
|
||||
* ---------------
|
||||
@ -71,6 +71,8 @@
|
||||
* 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info.
|
||||
* 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC.
|
||||
* 11-18-14 02.00.13 Updated copyright information.
|
||||
* 08-25-16 02.00.14 Added new values for the Flags field of Toolbox Clean
|
||||
* Tool Request Message.
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -145,6 +147,16 @@ typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST
|
||||
#define MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC (0x04000000)
|
||||
#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000)
|
||||
#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000)
|
||||
#define MPI2_TOOLBOX_CLEAN_SBR (0x00800000)
|
||||
#define MPI2_TOOLBOX_CLEAN_SBR_BACKUP (0x00400000)
|
||||
#define MPI2_TOOLBOX_CLEAN_HIIM (0x00200000)
|
||||
#define MPI2_TOOLBOX_CLEAN_HIIA (0x00100000)
|
||||
#define MPI2_TOOLBOX_CLEAN_CTLR (0x00080000)
|
||||
#define MPI2_TOOLBOX_CLEAN_IMR_FIRMWARE (0x00040000)
|
||||
#define MPI2_TOOLBOX_CLEAN_MR_NVDATA (0x00020000)
|
||||
#define MPI2_TOOLBOX_CLEAN_RESERVED_5_16 (0x0001FFE0)
|
||||
#define MPI2_TOOLBOX_CLEAN_ALL_BUT_MPB (0x00000010)
|
||||
#define MPI2_TOOLBOX_CLEAN_ENTIRE_FLASH (0x00000008)
|
||||
#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004)
|
||||
#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002)
|
||||
#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001)
|
||||
|
@ -63,18 +63,21 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
|
||||
#include <dev/mpr/mpi/mpi2_type.h>
|
||||
#include <dev/mpr/mpi/mpi2.h>
|
||||
#include <dev/mpr/mpi/mpi2_ioc.h>
|
||||
#include <dev/mpr/mpi/mpi2_sas.h>
|
||||
#include <dev/mpr/mpi/mpi2_pci.h>
|
||||
#include <dev/mpr/mpi/mpi2_cnfg.h>
|
||||
#include <dev/mpr/mpi/mpi2_init.h>
|
||||
#include <dev/mpr/mpi/mpi2_tool.h>
|
||||
#include <dev/mpr/mpr_ioctl.h>
|
||||
#include <dev/mpr/mprvar.h>
|
||||
#include <dev/mpr/mpr_table.h>
|
||||
#include <dev/mpr/mpr_sas.h>
|
||||
|
||||
static int mpr_diag_reset(struct mpr_softc *sc, int sleep_flag);
|
||||
static int mpr_init_queues(struct mpr_softc *sc);
|
||||
@ -87,6 +90,7 @@ static int mpr_send_iocinit(struct mpr_softc *sc);
|
||||
static int mpr_alloc_queues(struct mpr_softc *sc);
|
||||
static int mpr_alloc_replies(struct mpr_softc *sc);
|
||||
static int mpr_alloc_requests(struct mpr_softc *sc);
|
||||
static int mpr_alloc_nvme_prp_pages(struct mpr_softc *sc);
|
||||
static int mpr_attach_log(struct mpr_softc *sc);
|
||||
static __inline void mpr_complete_command(struct mpr_softc *sc,
|
||||
struct mpr_command *cm);
|
||||
@ -110,7 +114,7 @@ static char mpt2_reset_magic[] = { 0x00, 0x0f, 0x04, 0x0b, 0x02, 0x07, 0x0d };
|
||||
|
||||
/*
|
||||
* Added this union to smoothly convert le64toh cm->cm_desc.Words.
|
||||
* Compiler only supports unint64_t to be passed as an argument.
|
||||
* Compiler only supports uint64_t to be passed as an argument.
|
||||
* Otherwise it will through this error:
|
||||
* "aggregate value used where an integer was expected"
|
||||
*/
|
||||
@ -120,7 +124,7 @@ typedef union _reply_descriptor {
|
||||
u32 low;
|
||||
u32 high;
|
||||
} u;
|
||||
}reply_descriptor,address_descriptor;
|
||||
} reply_descriptor, request_descriptor;
|
||||
|
||||
/* Rate limit chain-fail messages to 1 per minute */
|
||||
static struct timeval mpr_chainfail_interval = { 60, 0 };
|
||||
@ -311,7 +315,6 @@ mpr_transition_ready(struct mpr_softc *sc)
|
||||
|
||||
if (error)
|
||||
device_printf(sc->mpr_dev, "Cannot transition IOC to ready\n");
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -392,7 +395,8 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
|
||||
mpr_printf(sc, "IOCCapabilities: %b\n", sc->facts->IOCCapabilities,
|
||||
"\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf"
|
||||
"\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR"
|
||||
"\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc");
|
||||
"\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc"
|
||||
"\22FastPath" "\23RDPQArray" "\24AtomicReqDesc" "\25PCIeSRIOV");
|
||||
|
||||
/*
|
||||
* If the chip doesn't support event replay then a hard reset will be
|
||||
@ -480,12 +484,15 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
|
||||
enabled = TRUE;
|
||||
|
||||
/*
|
||||
* Set flag if EEDP is supported and if TLR is supported.
|
||||
* Set flags for some supported items.
|
||||
*/
|
||||
if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP)
|
||||
sc->eedp_enabled = TRUE;
|
||||
if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)
|
||||
sc->control_TLR = TRUE;
|
||||
if (sc->facts->IOCCapabilities &
|
||||
MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ)
|
||||
sc->atomic_desc_capable = TRUE;
|
||||
|
||||
/*
|
||||
* Size the queues. Since the reply queues always need one free
|
||||
@ -501,6 +508,7 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
|
||||
TAILQ_INIT(&sc->req_list);
|
||||
TAILQ_INIT(&sc->high_priority_req_list);
|
||||
TAILQ_INIT(&sc->chain_list);
|
||||
TAILQ_INIT(&sc->prp_page_list);
|
||||
TAILQ_INIT(&sc->tm_list);
|
||||
}
|
||||
|
||||
@ -634,6 +642,14 @@ mpr_iocfacts_free(struct mpr_softc *sc)
|
||||
if (sc->sense_dmat != NULL)
|
||||
bus_dma_tag_destroy(sc->sense_dmat);
|
||||
|
||||
if (sc->prp_page_busaddr != 0)
|
||||
bus_dmamap_unload(sc->prp_page_dmat, sc->prp_page_map);
|
||||
if (sc->prp_pages != NULL)
|
||||
bus_dmamem_free(sc->prp_page_dmat, sc->prp_pages,
|
||||
sc->prp_page_map);
|
||||
if (sc->prp_page_dmat != NULL)
|
||||
bus_dma_tag_destroy(sc->prp_page_dmat);
|
||||
|
||||
if (sc->reply_busaddr != 0)
|
||||
bus_dmamap_unload(sc->reply_dmat, sc->reply_map);
|
||||
if (sc->reply_frames != NULL)
|
||||
@ -651,6 +667,8 @@ mpr_iocfacts_free(struct mpr_softc *sc)
|
||||
|
||||
if (sc->chains != NULL)
|
||||
free(sc->chains, M_MPR);
|
||||
if (sc->prps != NULL)
|
||||
free(sc->prps, M_MPR);
|
||||
if (sc->commands != NULL) {
|
||||
for (i = 1; i < sc->num_reqs; i++) {
|
||||
cm = &sc->commands[i];
|
||||
@ -804,7 +822,7 @@ mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag)
|
||||
count++;
|
||||
} while (--cntdn);
|
||||
|
||||
out:
|
||||
out:
|
||||
mpr_dprint(sc, MPR_FAULT, "%s: failed due to timeout count(%d), "
|
||||
"int_status(%x)!\n", __func__, count, int_status);
|
||||
return (ETIMEDOUT);
|
||||
@ -959,7 +977,7 @@ mpr_request_sync(struct mpr_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
|
||||
static void
|
||||
mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
{
|
||||
reply_descriptor rd;
|
||||
request_descriptor rd;
|
||||
|
||||
MPR_FUNCTRACE(sc);
|
||||
mpr_dprint(sc, MPR_TRACE, "SMID %u cm %p ccb %p\n",
|
||||
@ -972,14 +990,19 @@ mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
if (++sc->io_cmds_active > sc->io_cmds_highwater)
|
||||
sc->io_cmds_highwater++;
|
||||
|
||||
rd.u.low = cm->cm_desc.Words.Low;
|
||||
rd.u.high = cm->cm_desc.Words.High;
|
||||
rd.word = htole64(rd.word);
|
||||
/* TODO-We may need to make below regwrite atomic */
|
||||
mpr_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET,
|
||||
rd.u.low);
|
||||
mpr_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET,
|
||||
rd.u.high);
|
||||
if (sc->atomic_desc_capable) {
|
||||
rd.u.low = cm->cm_desc.Words.Low;
|
||||
mpr_regwrite(sc, MPI26_ATOMIC_REQUEST_DESCRIPTOR_POST_OFFSET,
|
||||
rd.u.low);
|
||||
} else {
|
||||
rd.u.low = cm->cm_desc.Words.Low;
|
||||
rd.u.high = cm->cm_desc.Words.High;
|
||||
rd.word = htole64(rd.word);
|
||||
mpr_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET,
|
||||
rd.u.low);
|
||||
mpr_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET,
|
||||
rd.u.high);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1047,6 +1070,7 @@ mpr_send_iocinit(struct mpr_softc *sc)
|
||||
time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000);
|
||||
init.TimeStamp.High = htole32((time_in_msec >> 32) & 0xFFFFFFFF);
|
||||
init.TimeStamp.Low = htole32(time_in_msec & 0xFFFFFFFF);
|
||||
init.HostPageSize = HOST_PAGE_SIZE_4K;
|
||||
|
||||
error = mpr_request_sync(sc, &init, &reply, req_sz, reply_sz, 5);
|
||||
if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
|
||||
@ -1276,6 +1300,16 @@ mpr_alloc_requests(struct mpr_softc *sc)
|
||||
sc->chain_free_lowwater++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate NVMe PRP Pages for NVMe SGL support only if the FW supports
|
||||
* these devices.
|
||||
*/
|
||||
if ((sc->facts->MsgVersion >= MPI2_VERSION_02_06) &&
|
||||
(sc->facts->ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_NVME_DEVICES)) {
|
||||
if (mpr_alloc_nvme_prp_pages(sc) == ENOMEM)
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/* XXX Need to pick a more precise value */
|
||||
nsegs = (MAXPHYS / PAGE_SIZE) + 1;
|
||||
if (bus_dma_tag_create( sc->mpr_parent_dmat, /* parent */
|
||||
@ -1316,15 +1350,17 @@ mpr_alloc_requests(struct mpr_softc *sc)
|
||||
cm->cm_desc.Default.SMID = i;
|
||||
cm->cm_sc = sc;
|
||||
TAILQ_INIT(&cm->cm_chain_list);
|
||||
TAILQ_INIT(&cm->cm_prp_page_list);
|
||||
callout_init_mtx(&cm->cm_callout, &sc->mpr_mtx, 0);
|
||||
|
||||
/* XXX Is a failure here a critical problem? */
|
||||
if (bus_dmamap_create(sc->buffer_dmat, 0, &cm->cm_dmamap) == 0)
|
||||
if (bus_dmamap_create(sc->buffer_dmat, 0, &cm->cm_dmamap)
|
||||
== 0) {
|
||||
if (i <= sc->facts->HighPriorityCredit)
|
||||
mpr_free_high_priority_command(sc, cm);
|
||||
else
|
||||
mpr_free_command(sc, cm);
|
||||
else {
|
||||
} else {
|
||||
panic("failed to allocate command %d\n", i);
|
||||
sc->num_reqs = i;
|
||||
break;
|
||||
@ -1334,6 +1370,86 @@ mpr_alloc_requests(struct mpr_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate contiguous buffers for PCIe NVMe devices for building native PRPs,
|
||||
* which are scatter/gather lists for NVMe devices.
|
||||
*
|
||||
* This buffer must be contiguous due to the nature of how NVMe PRPs are built
|
||||
* and translated by FW.
|
||||
*
|
||||
* returns ENOMEM if memory could not be allocated, otherwise returns 0.
|
||||
*/
|
||||
static int
|
||||
mpr_alloc_nvme_prp_pages(struct mpr_softc *sc)
|
||||
{
|
||||
int PRPs_per_page, PRPs_required, pages_required;
|
||||
int rsize, i;
|
||||
struct mpr_prp_page *prp_page;
|
||||
|
||||
/*
|
||||
* Assuming a MAX_IO_SIZE of 1MB and a PAGE_SIZE of 4k, the max number
|
||||
* of PRPs (NVMe's Scatter/Gather Element) needed per I/O is:
|
||||
* MAX_IO_SIZE / PAGE_SIZE = 256
|
||||
*
|
||||
* 1 PRP entry in main frame for PRP list pointer still leaves 255 PRPs
|
||||
* required for the remainder of the 1MB I/O. 512 PRPs can fit into one
|
||||
* page (4096 / 8 = 512), so only one page is required for each I/O.
|
||||
*
|
||||
* Each of these buffers will need to be contiguous. For simplicity,
|
||||
* only one buffer is allocated here, which has all of the space
|
||||
* required for the NVMe Queue Depth. If there are problems allocating
|
||||
* this one buffer, this function will need to change to allocate
|
||||
* individual, contiguous NVME_QDEPTH buffers.
|
||||
*
|
||||
* The real calculation will use the real max io size. Above is just an
|
||||
* example.
|
||||
*
|
||||
*/
|
||||
PRPs_required = sc->maxio / PAGE_SIZE;
|
||||
PRPs_per_page = (PAGE_SIZE / PRP_ENTRY_SIZE) - 1;
|
||||
pages_required = (PRPs_required / PRPs_per_page) + 1;
|
||||
|
||||
sc->prp_buffer_size = PAGE_SIZE * pages_required;
|
||||
rsize = sc->prp_buffer_size * NVME_QDEPTH;
|
||||
if (bus_dma_tag_create( sc->mpr_parent_dmat, /* parent */
|
||||
4, 0, /* algnmnt, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
rsize, /* maxsize */
|
||||
1, /* nsegments */
|
||||
rsize, /* maxsegsize */
|
||||
0, /* flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->prp_page_dmat)) {
|
||||
device_printf(sc->mpr_dev, "Cannot allocate NVMe PRP DMA "
|
||||
"tag\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
if (bus_dmamem_alloc(sc->prp_page_dmat, (void **)&sc->prp_pages,
|
||||
BUS_DMA_NOWAIT, &sc->prp_page_map)) {
|
||||
device_printf(sc->mpr_dev, "Cannot allocate NVMe PRP memory\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
bzero(sc->prp_pages, rsize);
|
||||
bus_dmamap_load(sc->prp_page_dmat, sc->prp_page_map, sc->prp_pages,
|
||||
rsize, mpr_memaddr_cb, &sc->prp_page_busaddr, 0);
|
||||
|
||||
sc->prps = malloc(sizeof(struct mpr_prp_page) * NVME_QDEPTH, M_MPR,
|
||||
M_WAITOK | M_ZERO);
|
||||
for (i = 0; i < NVME_QDEPTH; i++) {
|
||||
prp_page = &sc->prps[i];
|
||||
prp_page->prp_page = (uint64_t *)(sc->prp_pages +
|
||||
i * sc->prp_buffer_size);
|
||||
prp_page->prp_page_busaddr = (uint64_t)(sc->prp_page_busaddr +
|
||||
i * sc->prp_buffer_size);
|
||||
mpr_free_prp_page(sc, prp_page);
|
||||
sc->prp_pages_free_lowwater++;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
mpr_init_queues(struct mpr_softc *sc)
|
||||
{
|
||||
@ -1352,8 +1468,10 @@ mpr_init_queues(struct mpr_softc *sc)
|
||||
/*
|
||||
* Initialize all of the free queue entries.
|
||||
*/
|
||||
for (i = 0; i < sc->fqdepth; i++)
|
||||
sc->free_queue[i] = sc->reply_busaddr + (i * sc->facts->ReplyFrameSize * 4);
|
||||
for (i = 0; i < sc->fqdepth; i++) {
|
||||
sc->free_queue[i] = sc->reply_busaddr +
|
||||
(i * sc->facts->ReplyFrameSize * 4);
|
||||
}
|
||||
sc->replyfreeindex = sc->num_replies;
|
||||
|
||||
return (0);
|
||||
@ -1520,6 +1638,18 @@ mpr_setup_sysctl(struct mpr_softc *sc)
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0,
|
||||
"Use the phy number for enumeration");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "prp_pages_free", CTLFLAG_RD,
|
||||
&sc->prp_pages_free, 0, "number of free PRP pages");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "prp_pages_free_lowwater", CTLFLAG_RD,
|
||||
&sc->prp_pages_free_lowwater, 0,"lowest number of free PRP pages");
|
||||
|
||||
SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "prp_page_alloc_fail", CTLFLAG_RD,
|
||||
&sc->prp_page_alloc_fail, "PRP page allocation failures");
|
||||
}
|
||||
|
||||
int
|
||||
@ -1912,6 +2042,7 @@ mpr_intr_locked(void *data)
|
||||
switch (flags) {
|
||||
case MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS:
|
||||
case MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS:
|
||||
case MPI26_RPY_DESCRIPT_FLAGS_PCIE_ENCAPSULATED_SUCCESS:
|
||||
cm = &sc->commands[le16toh(desc->SCSIIOSuccess.SMID)];
|
||||
cm->cm_reply = NULL;
|
||||
break;
|
||||
@ -2200,6 +2331,519 @@ mpr_deregister_events(struct mpr_softc *sc, struct mpr_event_handle *handle)
|
||||
return (mpr_update_events(sc, NULL, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* mpr_build_nvme_prp - This function is called for NVMe end devices to build a
|
||||
* native SGL (NVMe PRP). The native SGL is built starting in the first PRP entry
|
||||
* of the NVMe message (PRP1). If the data buffer is small enough to be described
|
||||
* entirely using PRP1, then PRP2 is not used. If needed, PRP2 is used to
|
||||
* describe a larger data buffer. If the data buffer is too large to describe
|
||||
* using the two PRP entriess inside the NVMe message, then PRP1 describes the
|
||||
* first data memory segment, and PRP2 contains a pointer to a PRP list located
|
||||
* elsewhere in memory to describe the remaining data memory segments. The PRP
|
||||
* list will be contiguous.
|
||||
|
||||
* The native SGL for NVMe devices is a Physical Region Page (PRP). A PRP
|
||||
* consists of a list of PRP entries to describe a number of noncontigous
|
||||
* physical memory segments as a single memory buffer, just as a SGL does. Note
|
||||
* however, that this function is only used by the IOCTL call, so the memory
|
||||
* given will be guaranteed to be contiguous. There is no need to translate
|
||||
* non-contiguous SGL into a PRP in this case. All PRPs will describe contiguous
|
||||
* space that is one page size each.
|
||||
*
|
||||
* Each NVMe message contains two PRP entries. The first (PRP1) either contains
|
||||
* a PRP list pointer or a PRP element, depending upon the command. PRP2 contains
|
||||
* the second PRP element if the memory being described fits within 2 PRP
|
||||
* entries, or a PRP list pointer if the PRP spans more than two entries.
|
||||
*
|
||||
* A PRP list pointer contains the address of a PRP list, structured as a linear
|
||||
* array of PRP entries. Each PRP entry in this list describes a segment of
|
||||
* physical memory.
|
||||
*
|
||||
* Each 64-bit PRP entry comprises an address and an offset field. The address
|
||||
* always points to the beginning of a PAGE_SIZE physical memory page, and the
|
||||
* offset describes where within that page the memory segment begins. Only the
|
||||
* first element in a PRP list may contain a non-zero offest, implying that all
|
||||
* memory segments following the first begin at the start of a PAGE_SIZE page.
|
||||
*
|
||||
* Each PRP element normally describes a chunck of PAGE_SIZE physical memory,
|
||||
* with exceptions for the first and last elements in the list. If the memory
|
||||
* being described by the list begins at a non-zero offset within the first page,
|
||||
* then the first PRP element will contain a non-zero offset indicating where the
|
||||
* region begins within the page. The last memory segment may end before the end
|
||||
* of the PAGE_SIZE segment, depending upon the overall size of the memory being
|
||||
* described by the PRP list.
|
||||
*
|
||||
* Since PRP entries lack any indication of size, the overall data buffer length
|
||||
* is used to determine where the end of the data memory buffer is located, and
|
||||
* how many PRP entries are required to describe it.
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
void
|
||||
mpr_build_nvme_prp(struct mpr_softc *sc, struct mpr_command *cm,
|
||||
Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request, void *data,
|
||||
uint32_t data_in_sz, uint32_t data_out_sz)
|
||||
{
|
||||
int prp_size = PRP_ENTRY_SIZE;
|
||||
uint64_t *prp_entry, *prp1_entry, *prp2_entry;
|
||||
uint64_t *prp_entry_phys, *prp_page, *prp_page_phys;
|
||||
uint32_t offset, entry_len, page_mask_result, page_mask;
|
||||
bus_addr_t paddr;
|
||||
size_t length;
|
||||
struct mpr_prp_page *prp_page_info = NULL;
|
||||
|
||||
/*
|
||||
* Not all commands require a data transfer. If no data, just return
|
||||
* without constructing any PRP.
|
||||
*/
|
||||
if (!data_in_sz && !data_out_sz)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Set pointers to PRP1 and PRP2, which are in the NVMe command. PRP1 is
|
||||
* located at a 24 byte offset from the start of the NVMe command. Then
|
||||
* set the current PRP entry pointer to PRP1.
|
||||
*/
|
||||
prp1_entry = (uint64_t *)(nvme_encap_request->NVMe_Command +
|
||||
NVME_CMD_PRP1_OFFSET);
|
||||
prp2_entry = (uint64_t *)(nvme_encap_request->NVMe_Command +
|
||||
NVME_CMD_PRP2_OFFSET);
|
||||
prp_entry = prp1_entry;
|
||||
|
||||
/*
|
||||
* For the PRP entries, use the specially allocated buffer of
|
||||
* contiguous memory. PRP Page allocation failures should not happen
|
||||
* because there should be enough PRP page buffers to account for the
|
||||
* possible NVMe QDepth.
|
||||
*/
|
||||
prp_page_info = mpr_alloc_prp_page(sc);
|
||||
KASSERT(prp_page_info != NULL, ("%s: There are no PRP Pages left to be "
|
||||
"used for building a native NVMe SGL.\n", __func__));
|
||||
prp_page = (uint64_t *)prp_page_info->prp_page;
|
||||
prp_page_phys = (uint64_t *)(uintptr_t)prp_page_info->prp_page_busaddr;
|
||||
|
||||
/*
|
||||
* Insert the allocated PRP page into the command's PRP page list. This
|
||||
* will be freed when the command is freed.
|
||||
*/
|
||||
TAILQ_INSERT_TAIL(&cm->cm_prp_page_list, prp_page_info, prp_page_link);
|
||||
|
||||
/*
|
||||
* Check if we are within 1 entry of a page boundary we don't want our
|
||||
* first entry to be a PRP List entry.
|
||||
*/
|
||||
page_mask = PAGE_SIZE - 1;
|
||||
page_mask_result = (uintptr_t)((uint8_t *)prp_page + prp_size) &
|
||||
page_mask;
|
||||
if (!page_mask_result)
|
||||
{
|
||||
/* Bump up to next page boundary. */
|
||||
prp_page = (uint64_t *)((uint8_t *)prp_page + prp_size);
|
||||
prp_page_phys = (uint64_t *)((uint8_t *)prp_page_phys +
|
||||
prp_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set PRP physical pointer, which initially points to the current PRP
|
||||
* DMA memory page.
|
||||
*/
|
||||
prp_entry_phys = prp_page_phys;
|
||||
|
||||
/* Get physical address and length of the data buffer. */
|
||||
paddr = (bus_addr_t)data;
|
||||
if (data_in_sz)
|
||||
length = data_in_sz;
|
||||
else
|
||||
length = data_out_sz;
|
||||
|
||||
/* Loop while the length is not zero. */
|
||||
while (length)
|
||||
{
|
||||
/*
|
||||
* Check if we need to put a list pointer here if we are at page
|
||||
* boundary - prp_size (8 bytes).
|
||||
*/
|
||||
page_mask_result = (uintptr_t)((uint8_t *)prp_entry_phys +
|
||||
prp_size) & page_mask;
|
||||
if (!page_mask_result)
|
||||
{
|
||||
/*
|
||||
* This is the last entry in a PRP List, so we need to
|
||||
* put a PRP list pointer here. What this does is:
|
||||
* - bump the current memory pointer to the next
|
||||
* address, which will be the next full page.
|
||||
* - set the PRP Entry to point to that page. This is
|
||||
* now the PRP List pointer.
|
||||
* - bump the PRP Entry pointer the start of the next
|
||||
* page. Since all of this PRP memory is contiguous,
|
||||
* no need to get a new page - it's just the next
|
||||
* address.
|
||||
*/
|
||||
prp_entry_phys++;
|
||||
*prp_entry =
|
||||
htole64((uint64_t)(uintptr_t)prp_entry_phys);
|
||||
prp_entry++;
|
||||
}
|
||||
|
||||
/* Need to handle if entry will be part of a page. */
|
||||
offset = (uint32_t)paddr & page_mask;
|
||||
entry_len = PAGE_SIZE - offset;
|
||||
|
||||
if (prp_entry == prp1_entry)
|
||||
{
|
||||
/*
|
||||
* Must fill in the first PRP pointer (PRP1) before
|
||||
* moving on.
|
||||
*/
|
||||
*prp1_entry = htole64((uint64_t)paddr);
|
||||
|
||||
/*
|
||||
* Now point to the second PRP entry within the
|
||||
* command (PRP2).
|
||||
*/
|
||||
prp_entry = prp2_entry;
|
||||
}
|
||||
else if (prp_entry == prp2_entry)
|
||||
{
|
||||
/*
|
||||
* Should the PRP2 entry be a PRP List pointer or just a
|
||||
* regular PRP pointer? If there is more than one more
|
||||
* page of data, must use a PRP List pointer.
|
||||
*/
|
||||
if (length > PAGE_SIZE)
|
||||
{
|
||||
/*
|
||||
* PRP2 will contain a PRP List pointer because
|
||||
* more PRP's are needed with this command. The
|
||||
* list will start at the beginning of the
|
||||
* contiguous buffer.
|
||||
*/
|
||||
*prp2_entry =
|
||||
htole64(
|
||||
(uint64_t)(uintptr_t)prp_entry_phys);
|
||||
|
||||
/*
|
||||
* The next PRP Entry will be the start of the
|
||||
* first PRP List.
|
||||
*/
|
||||
prp_entry = prp_page;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* After this, the PRP Entries are complete.
|
||||
* This command uses 2 PRP's and no PRP list.
|
||||
*/
|
||||
*prp2_entry = htole64((uint64_t)paddr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Put entry in list and bump the addresses.
|
||||
*
|
||||
* After PRP1 and PRP2 are filled in, this will fill in
|
||||
* all remaining PRP entries in a PRP List, one per each
|
||||
* time through the loop.
|
||||
*/
|
||||
*prp_entry = htole64((uint64_t)paddr);
|
||||
prp_entry++;
|
||||
prp_entry_phys++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bump the phys address of the command's data buffer by the
|
||||
* entry_len.
|
||||
*/
|
||||
paddr += entry_len;
|
||||
|
||||
/* Decrement length accounting for last partial page. */
|
||||
if (entry_len > length)
|
||||
length = 0;
|
||||
else
|
||||
length -= entry_len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mpr_check_pcie_native_sgl - This function is called for PCIe end devices to
|
||||
* determine if the driver needs to build a native SGL. If so, that native SGL
|
||||
* is built in the contiguous buffers allocated especially for PCIe SGL
|
||||
* creation. If the driver will not build a native SGL, return TRUE and a
|
||||
* normal IEEE SGL will be built. Currently this routine supports NVMe devices
|
||||
* only.
|
||||
*
|
||||
* Returns FALSE (0) if native SGL was built, TRUE (1) if no SGL was built.
|
||||
*/
|
||||
static int
|
||||
mpr_check_pcie_native_sgl(struct mpr_softc *sc, struct mpr_command *cm,
|
||||
bus_dma_segment_t *segs, int segs_left)
|
||||
{
|
||||
uint32_t i, sge_dwords, length, offset, entry_len;
|
||||
uint32_t num_entries, buff_len = 0, sges_in_segment;
|
||||
uint32_t page_mask, page_mask_result, *curr_buff;
|
||||
uint32_t *ptr_sgl, *ptr_first_sgl, first_page_offset;
|
||||
uint32_t first_page_data_size, end_residual;
|
||||
uint64_t *msg_phys;
|
||||
bus_addr_t paddr;
|
||||
int build_native_sgl = 0, first_prp_entry;
|
||||
int prp_size = PRP_ENTRY_SIZE;
|
||||
Mpi25IeeeSgeChain64_t *main_chain_element = NULL;
|
||||
struct mpr_prp_page *prp_page_info = NULL;
|
||||
|
||||
mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
|
||||
|
||||
/*
|
||||
* Add up the sizes of each segment length to get the total transfer
|
||||
* size, which will be checked against the Maximum Data Transfer Size.
|
||||
* If the data transfer length exceeds the MDTS for this device, just
|
||||
* return 1 so a normal IEEE SGL will be built. F/W will break the I/O
|
||||
* up into multiple I/O's. [nvme_mdts = 0 means unlimited]
|
||||
*/
|
||||
for (i = 0; i < segs_left; i++)
|
||||
buff_len += htole32(segs[i].ds_len);
|
||||
if ((cm->cm_targ->MDTS > 0) && (buff_len > cm->cm_targ->MDTS))
|
||||
return 1;
|
||||
|
||||
/* Create page_mask (to get offset within page) */
|
||||
page_mask = PAGE_SIZE - 1;
|
||||
|
||||
/*
|
||||
* Check if the number of elements exceeds the max number that can be
|
||||
* put in the main message frame (H/W can only translate an SGL that
|
||||
* is contained entirely in the main message frame).
|
||||
*/
|
||||
sges_in_segment = (sc->facts->IOCRequestFrameSize -
|
||||
offsetof(Mpi25SCSIIORequest_t, SGL)) / sizeof(MPI25_SGE_IO_UNION);
|
||||
if (segs_left > sges_in_segment)
|
||||
build_native_sgl = 1;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* NVMe uses one PRP for each physical page (or part of physical
|
||||
* page).
|
||||
* if 4 pages or less then IEEE is OK
|
||||
* if > 5 pages then we need to build a native SGL
|
||||
* if > 4 and <= 5 pages, then check the physical address of
|
||||
* the first SG entry, then if this first size in the page
|
||||
* is >= the residual beyond 4 pages then use IEEE,
|
||||
* otherwise use native SGL
|
||||
*/
|
||||
if (buff_len > (PAGE_SIZE * 5))
|
||||
build_native_sgl = 1;
|
||||
else if ((buff_len > (PAGE_SIZE * 4)) &&
|
||||
(buff_len <= (PAGE_SIZE * 5)) )
|
||||
{
|
||||
msg_phys = (uint64_t *)segs[0].ds_addr;
|
||||
first_page_offset =
|
||||
((uint32_t)(uint64_t)(uintptr_t)msg_phys &
|
||||
page_mask);
|
||||
first_page_data_size = PAGE_SIZE - first_page_offset;
|
||||
end_residual = buff_len % PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* If offset into first page pushes the end of the data
|
||||
* beyond end of the 5th page, we need the extra PRP
|
||||
* list.
|
||||
*/
|
||||
if (first_page_data_size < end_residual)
|
||||
build_native_sgl = 1;
|
||||
|
||||
/*
|
||||
* Check if first SG entry size is < residual beyond 4
|
||||
* pages.
|
||||
*/
|
||||
if (htole32(segs[0].ds_len) <
|
||||
(buff_len - (PAGE_SIZE * 4)))
|
||||
build_native_sgl = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if native SGL is needed */
|
||||
if (!build_native_sgl)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Native SGL is needed.
|
||||
* Put a chain element in main message frame that points to the first
|
||||
* chain buffer.
|
||||
*
|
||||
* NOTE: The ChainOffset field must be 0 when using a chain pointer to
|
||||
* a native SGL.
|
||||
*/
|
||||
|
||||
/* Set main message chain element pointer */
|
||||
main_chain_element = (pMpi25IeeeSgeChain64_t)cm->cm_sge;
|
||||
|
||||
/*
|
||||
* For NVMe the chain element needs to be the 2nd SGL entry in the main
|
||||
* message.
|
||||
*/
|
||||
main_chain_element = (Mpi25IeeeSgeChain64_t *)
|
||||
((uint8_t *)main_chain_element + sizeof(MPI25_IEEE_SGE_CHAIN64));
|
||||
|
||||
/*
|
||||
* For the PRP entries, use the specially allocated buffer of
|
||||
* contiguous memory. PRP Page allocation failures should not happen
|
||||
* because there should be enough PRP page buffers to account for the
|
||||
* possible NVMe QDepth.
|
||||
*/
|
||||
prp_page_info = mpr_alloc_prp_page(sc);
|
||||
KASSERT(prp_page_info != NULL, ("%s: There are no PRP Pages left to be "
|
||||
"used for building a native NVMe SGL.\n", __func__));
|
||||
curr_buff = (uint32_t *)prp_page_info->prp_page;
|
||||
msg_phys = (uint64_t *)(uintptr_t)prp_page_info->prp_page_busaddr;
|
||||
|
||||
/*
|
||||
* Insert the allocated PRP page into the command's PRP page list. This
|
||||
* will be freed when the command is freed.
|
||||
*/
|
||||
TAILQ_INSERT_TAIL(&cm->cm_prp_page_list, prp_page_info, prp_page_link);
|
||||
|
||||
/*
|
||||
* Check if we are within 1 entry of a page boundary we don't want our
|
||||
* first entry to be a PRP List entry.
|
||||
*/
|
||||
page_mask_result = (uintptr_t)((uint8_t *)curr_buff + prp_size) &
|
||||
page_mask;
|
||||
if (!page_mask_result) {
|
||||
/* Bump up to next page boundary. */
|
||||
curr_buff = (uint32_t *)((uint8_t *)curr_buff + prp_size);
|
||||
msg_phys = (uint64_t *)((uint8_t *)msg_phys + prp_size);
|
||||
}
|
||||
|
||||
/* Fill in the chain element and make it an NVMe segment type. */
|
||||
main_chain_element->Address.High =
|
||||
htole32((uint32_t)((uint64_t)(uintptr_t)msg_phys >> 32));
|
||||
main_chain_element->Address.Low =
|
||||
htole32((uint32_t)(uintptr_t)msg_phys);
|
||||
main_chain_element->NextChainOffset = 0;
|
||||
main_chain_element->Flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
|
||||
MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
|
||||
MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP;
|
||||
|
||||
/* Set SGL pointer to start of contiguous PCIe buffer. */
|
||||
ptr_sgl = curr_buff;
|
||||
sge_dwords = 2;
|
||||
num_entries = 0;
|
||||
|
||||
/*
|
||||
* NVMe has a very convoluted PRP format. One PRP is required for each
|
||||
* page or partial page. We need to split up OS SG entries if they are
|
||||
* longer than one page or cross a page boundary. We also have to insert
|
||||
* a PRP list pointer entry as the last entry in each physical page of
|
||||
* the PRP list.
|
||||
*
|
||||
* NOTE: The first PRP "entry" is actually placed in the first SGL entry
|
||||
* in the main message in IEEE 64 format. The 2nd entry in the main
|
||||
* message is the chain element, and the rest of the PRP entries are
|
||||
* built in the contiguous PCIe buffer.
|
||||
*/
|
||||
first_prp_entry = 1;
|
||||
ptr_first_sgl = (uint32_t *)cm->cm_sge;
|
||||
|
||||
for (i = 0; i < segs_left; i++) {
|
||||
/* Get physical address and length of this SG entry. */
|
||||
paddr = segs[i].ds_addr;
|
||||
length = segs[i].ds_len;
|
||||
|
||||
/*
|
||||
* Check whether a given SGE buffer lies on a non-PAGED
|
||||
* boundary if this is not the first page. If so, this is not
|
||||
* expected so have FW build the SGL.
|
||||
*/
|
||||
if (i) {
|
||||
if ((uint32_t)paddr & page_mask) {
|
||||
mpr_dprint(sc, MPR_ERROR, "Unaligned SGE while "
|
||||
"building NVMe PRPs, low address is 0x%x\n",
|
||||
(uint32_t)paddr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apart from last SGE, if any other SGE boundary is not page
|
||||
* aligned then it means that hole exists. Existence of hole
|
||||
* leads to data corruption. So fallback to IEEE SGEs.
|
||||
*/
|
||||
if (i != (segs_left - 1)) {
|
||||
if (((uint32_t)paddr + length) & page_mask) {
|
||||
mpr_dprint(sc, MPR_ERROR, "Unaligned SGE "
|
||||
"boundary while building NVMe PRPs, low "
|
||||
"address: 0x%x and length: %u\n",
|
||||
(uint32_t)paddr, length);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop while the length is not zero. */
|
||||
while (length) {
|
||||
/*
|
||||
* Check if we need to put a list pointer here if we are
|
||||
* at page boundary - prp_size.
|
||||
*/
|
||||
page_mask_result = (uintptr_t)((uint8_t *)ptr_sgl +
|
||||
prp_size) & page_mask;
|
||||
if (!page_mask_result) {
|
||||
/*
|
||||
* Need to put a PRP list pointer here.
|
||||
*/
|
||||
msg_phys = (uint64_t *)((uint8_t *)msg_phys +
|
||||
prp_size);
|
||||
*ptr_sgl = htole32((uintptr_t)msg_phys);
|
||||
*(ptr_sgl+1) = htole32((uint64_t)(uintptr_t)
|
||||
msg_phys >> 32);
|
||||
ptr_sgl += sge_dwords;
|
||||
num_entries++;
|
||||
}
|
||||
|
||||
/* Need to handle if entry will be part of a page. */
|
||||
offset = (uint32_t)paddr & page_mask;
|
||||
entry_len = PAGE_SIZE - offset;
|
||||
if (first_prp_entry) {
|
||||
/*
|
||||
* Put IEEE entry in first SGE in main message.
|
||||
* (Simple element, System addr, not end of
|
||||
* list.)
|
||||
*/
|
||||
*ptr_first_sgl = htole32((uint32_t)paddr);
|
||||
*(ptr_first_sgl + 1) =
|
||||
htole32((uint32_t)((uint64_t)paddr >> 32));
|
||||
*(ptr_first_sgl + 2) = htole32(entry_len);
|
||||
*(ptr_first_sgl + 3) = 0;
|
||||
|
||||
/* No longer the first PRP entry. */
|
||||
first_prp_entry = 0;
|
||||
} else {
|
||||
/* Put entry in list. */
|
||||
*ptr_sgl = htole32((uint32_t)paddr);
|
||||
*(ptr_sgl + 1) =
|
||||
htole32((uint32_t)((uint64_t)paddr >> 32));
|
||||
|
||||
/* Bump ptr_sgl, msg_phys, and num_entries. */
|
||||
ptr_sgl += sge_dwords;
|
||||
msg_phys = (uint64_t *)((uint8_t *)msg_phys +
|
||||
prp_size);
|
||||
num_entries++;
|
||||
}
|
||||
|
||||
/* Bump the phys address by the entry_len. */
|
||||
paddr += entry_len;
|
||||
|
||||
/* Decrement length accounting for last partial page. */
|
||||
if (entry_len > length)
|
||||
length = 0;
|
||||
else
|
||||
length -= entry_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set chain element Length. */
|
||||
main_chain_element->Length = htole32(num_entries * prp_size);
|
||||
|
||||
/* Return 0, indicating we built a native SGL. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a chain element as the next SGE for the specified command.
|
||||
* Reset cm_sge and cm_sgesize to indicate all the available space. Chains are
|
||||
@ -2540,6 +3184,13 @@ mpr_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
} else
|
||||
dir = BUS_DMASYNC_PREREAD;
|
||||
|
||||
/* Check if a native SG list is needed for an NVMe PCIe device. */
|
||||
if (cm->cm_targ && cm->cm_targ->is_nvme &&
|
||||
mpr_check_pcie_native_sgl(sc, cm, segs, nsegs) == 0) {
|
||||
/* A native SG list was built, skip to end. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < nsegs; i++) {
|
||||
if ((cm->cm_flags & MPR_CM_FLAGS_SMP_PASS) && (i != 0)) {
|
||||
sflags &= ~MPI2_SGE_FLAGS_DIRECTION;
|
||||
@ -2557,6 +3208,7 @@ mpr_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
|
||||
mpr_enqueue_request(sc, cm);
|
||||
|
||||
|
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mpr/mpi/mpi2.h>
|
||||
#include <dev/mpr/mpi/mpi2_ioc.h>
|
||||
#include <dev/mpr/mpi/mpi2_sas.h>
|
||||
#include <dev/mpr/mpi/mpi2_pci.h>
|
||||
#include <dev/mpr/mpi/mpi2_cnfg.h>
|
||||
#include <dev/mpr/mpi/mpi2_init.h>
|
||||
#include <dev/mpr/mpi/mpi2_tool.h>
|
||||
@ -91,7 +92,7 @@ mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
|
||||
request->Header.PageNumber = 8;
|
||||
request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
|
||||
request->Header.PageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
@ -137,7 +138,7 @@ mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
|
||||
request->Header.PageNumber = 8;
|
||||
request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
|
||||
request->Header.PageVersion = mpi_reply->Header.PageVersion;
|
||||
request->Header.PageLength = mpi_reply->Header.PageLength;
|
||||
cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
|
||||
cm->cm_sge = &request->PageBufferSGE;
|
||||
@ -221,7 +222,7 @@ mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
|
||||
request->Header.PageNumber = 8;
|
||||
request->Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
|
||||
request->Header.PageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
@ -267,7 +268,7 @@ mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
|
||||
request->Header.PageNumber = 8;
|
||||
request->Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
|
||||
request->Header.PageVersion = mpi_reply->Header.PageVersion;
|
||||
request->Header.PageLength = mpi_reply->Header.PageLength;
|
||||
cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
|
||||
cm->cm_sge = &request->PageBufferSGE;
|
||||
@ -387,7 +388,7 @@ mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
|
||||
request->ExtPageLength = request->Header.PageVersion = 0;
|
||||
request->PageAddress = sc->max_dpm_entries <<
|
||||
MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
@ -436,7 +437,7 @@ mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
|
||||
request->Header.PageVersion = mpi_reply->Header.PageVersion;
|
||||
request->PageAddress = sc->max_dpm_entries <<
|
||||
MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
|
||||
request->ExtPageLength = mpi_reply->ExtPageLength;
|
||||
@ -522,7 +523,7 @@ int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
|
||||
request->ExtPageLength = request->Header.PageVersion = 0;
|
||||
/* We can remove below two lines ????*/
|
||||
request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
|
||||
request->PageAddress |= htole16(entry_idx);
|
||||
@ -572,7 +573,7 @@ int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
|
||||
request->Header.PageVersion = mpi_reply->Header.PageVersion;
|
||||
request->ExtPageLength = mpi_reply->ExtPageLength;
|
||||
request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
|
||||
request->PageAddress |= htole16(entry_idx);
|
||||
@ -660,7 +661,7 @@ mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
|
||||
request->ExtPageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
@ -707,7 +708,7 @@ mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
|
||||
request->Header.PageVersion = mpi_reply->Header.PageVersion;
|
||||
request->ExtPageLength = mpi_reply->ExtPageLength;
|
||||
request->PageAddress = htole32(form | handle);
|
||||
cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
|
||||
@ -758,6 +759,276 @@ mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
|
||||
* @sc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* @form: GET_NEXT_HANDLE or HANDLE
|
||||
* @handle: device handle
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
*mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
|
||||
{
|
||||
MPI2_CONFIG_REQUEST *request;
|
||||
MPI2_CONFIG_REPLY *reply;
|
||||
struct mpr_command *cm;
|
||||
Mpi26PCIeDevicePage0_t *page = NULL;
|
||||
int error = 0;
|
||||
u16 ioc_status;
|
||||
|
||||
mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
|
||||
|
||||
if ((cm = mpr_alloc_command(sc)) == NULL) {
|
||||
printf("%s: command alloc failed @ line %d\n", __func__,
|
||||
__LINE__);
|
||||
error = EBUSY;
|
||||
goto out;
|
||||
}
|
||||
request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
|
||||
bzero(request, sizeof(MPI2_CONFIG_REQUEST));
|
||||
request->Function = MPI2_FUNCTION_CONFIG;
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
|
||||
request->Header.PageNumber = 0;
|
||||
request->ExtPageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
|
||||
if (error || (reply == NULL)) {
|
||||
/* FIXME */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
printf("%s: request for header completed with error %d",
|
||||
__func__, error);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
|
||||
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
/* FIXME */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
printf("%s: header read with error; iocstatus = 0x%x\n",
|
||||
__func__, ioc_status);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
/* We have to do free and alloc for the reply-free and reply-post
|
||||
* counters to match - Need to review the reply FIFO handling.
|
||||
*/
|
||||
mpr_free_command(sc, cm);
|
||||
|
||||
if ((cm = mpr_alloc_command(sc)) == NULL) {
|
||||
printf("%s: command alloc failed @ line %d\n", __func__,
|
||||
__LINE__);
|
||||
error = EBUSY;
|
||||
goto out;
|
||||
}
|
||||
request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
|
||||
bzero(request, sizeof(MPI2_CONFIG_REQUEST));
|
||||
request->Function = MPI2_FUNCTION_CONFIG;
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = mpi_reply->Header.PageVersion;
|
||||
request->ExtPageLength = mpi_reply->ExtPageLength;
|
||||
request->PageAddress = htole32(form | handle);
|
||||
cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
|
||||
cm->cm_sge = &request->PageBufferSGE;
|
||||
cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
|
||||
cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
|
||||
if (!page) {
|
||||
printf("%s: page alloc failed\n", __func__);
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
cm->cm_data = page;
|
||||
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
|
||||
if (error || (reply == NULL)) {
|
||||
/* FIXME */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
printf("%s: request for page completed with error %d",
|
||||
__func__, error);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
|
||||
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
/* FIXME */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
printf("%s: page read with error; iocstatus = 0x%x\n",
|
||||
__func__, ioc_status);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
bcopy(page, config_page, MIN(cm->cm_length,
|
||||
sizeof(Mpi26PCIeDevicePage0_t)));
|
||||
out:
|
||||
free(page, M_MPR);
|
||||
if (cm)
|
||||
mpr_free_command(sc, cm);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
|
||||
* @sc: per adapter object
|
||||
* @mpi_reply: reply mf payload returned from firmware
|
||||
* @config_page: contents of the config page
|
||||
* @form: GET_NEXT_HANDLE or HANDLE
|
||||
* @handle: device handle
|
||||
* Context: sleep.
|
||||
*
|
||||
* Returns 0 for success, non-zero for failure.
|
||||
*/
|
||||
int
|
||||
mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
*mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
|
||||
{
|
||||
MPI2_CONFIG_REQUEST *request;
|
||||
MPI2_CONFIG_REPLY *reply;
|
||||
struct mpr_command *cm;
|
||||
Mpi26PCIeDevicePage2_t *page = NULL;
|
||||
int error = 0;
|
||||
u16 ioc_status;
|
||||
|
||||
mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
|
||||
|
||||
if ((cm = mpr_alloc_command(sc)) == NULL) {
|
||||
printf("%s: command alloc failed @ line %d\n", __func__,
|
||||
__LINE__);
|
||||
error = EBUSY;
|
||||
goto out;
|
||||
}
|
||||
request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
|
||||
bzero(request, sizeof(MPI2_CONFIG_REQUEST));
|
||||
request->Function = MPI2_FUNCTION_CONFIG;
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
|
||||
request->Header.PageNumber = 2;
|
||||
request->ExtPageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
|
||||
if (error || (reply == NULL)) {
|
||||
/* FIXME */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
printf("%s: request for header completed with error %d",
|
||||
__func__, error);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
|
||||
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
/* FIXME */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
printf("%s: header read with error; iocstatus = 0x%x\n",
|
||||
__func__, ioc_status);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
/* We have to do free and alloc for the reply-free and reply-post
|
||||
* counters to match - Need to review the reply FIFO handling.
|
||||
*/
|
||||
mpr_free_command(sc, cm);
|
||||
|
||||
if ((cm = mpr_alloc_command(sc)) == NULL) {
|
||||
printf("%s: command alloc failed @ line %d\n", __func__,
|
||||
__LINE__);
|
||||
error = EBUSY;
|
||||
goto out;
|
||||
}
|
||||
request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
|
||||
bzero(request, sizeof(MPI2_CONFIG_REQUEST));
|
||||
request->Function = MPI2_FUNCTION_CONFIG;
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
|
||||
request->Header.PageNumber = 2;
|
||||
request->Header.PageVersion = mpi_reply->Header.PageVersion;
|
||||
request->ExtPageLength = mpi_reply->ExtPageLength;
|
||||
request->PageAddress = htole32(form | handle);
|
||||
cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
|
||||
cm->cm_sge = &request->PageBufferSGE;
|
||||
cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
|
||||
cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
|
||||
if (!page) {
|
||||
printf("%s: page alloc failed\n", __func__);
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
cm->cm_data = page;
|
||||
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
|
||||
if (error || (reply == NULL)) {
|
||||
/* FIXME */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
printf("%s: request for page completed with error %d",
|
||||
__func__, error);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
|
||||
bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
/* FIXME */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
printf("%s: page read with error; iocstatus = 0x%x\n",
|
||||
__func__, ioc_status);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
bcopy(page, config_page, MIN(cm->cm_length,
|
||||
sizeof(Mpi26PCIeDevicePage2_t)));
|
||||
out:
|
||||
free(page, M_MPR);
|
||||
if (cm)
|
||||
mpr_free_command(sc, cm);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpr_config_get_bios_pg3 - obtain BIOS page 3
|
||||
* @sc: per adapter object
|
||||
@ -792,7 +1063,7 @@ mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
|
||||
request->Header.PageNumber = 3;
|
||||
request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
|
||||
request->Header.PageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
@ -838,7 +1109,7 @@ mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
|
||||
request->Header.PageNumber = 3;
|
||||
request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
|
||||
request->Header.PageVersion = mpi_reply->Header.PageVersion;
|
||||
request->Header.PageLength = mpi_reply->Header.PageLength;
|
||||
cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
|
||||
cm->cm_sge = &request->PageBufferSGE;
|
||||
@ -922,7 +1193,7 @@ mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
|
||||
request->Header.PageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
|
||||
@ -1051,7 +1322,7 @@ mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
|
||||
request->Header.PageNumber = 1;
|
||||
request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
|
||||
request->Header.PageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
@ -1208,7 +1479,7 @@ mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
|
||||
request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
|
||||
request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
|
||||
request->Header.PageNumber = 0;
|
||||
request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
|
||||
request->Header.PageLength = request->Header.PageVersion = 0;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = NULL;
|
||||
|
||||
|
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mpr/mpi/mpi2.h>
|
||||
#include <dev/mpr/mpi/mpi2_ioc.h>
|
||||
#include <dev/mpr/mpi/mpi2_sas.h>
|
||||
#include <dev/mpr/mpi/mpi2_pci.h>
|
||||
#include <dev/mpr/mpi/mpi2_cnfg.h>
|
||||
#include <dev/mpr/mpi/mpi2_init.h>
|
||||
#include <dev/mpr/mpi/mpi2_tool.h>
|
||||
@ -675,6 +676,55 @@ _mapping_add_to_removal_table(struct mpr_softc *sc, u16 handle,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* _mapping_inc_missing_count
|
||||
* @sc: per adapter object
|
||||
* @map_idx: index into the mapping table for the device that is missing
|
||||
*
|
||||
* Increment the missing count in the mapping table for a SAS, SATA, or PCIe
|
||||
* device that is not responding. If Persitent Mapping is used, increment the
|
||||
* DPM entry as well. Also, add this device to the removal table for possible
|
||||
* removal if a new device is added.
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
static void
|
||||
_mapping_inc_missing_count(struct mpr_softc *sc, u32 map_idx)
|
||||
{
|
||||
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
|
||||
struct dev_mapping_table *mt_entry;
|
||||
Mpi2DriverMap0Entry_t *dpm_entry;
|
||||
|
||||
if (map_idx == MPR_MAPTABLE_BAD_IDX) {
|
||||
mpr_dprint(sc, MPR_INFO, "%s: device is already removed from "
|
||||
"mapping table\n", __func__);
|
||||
return;
|
||||
}
|
||||
mt_entry = &sc->mapping_table[map_idx];
|
||||
if (!mt_entry->init_complete) {
|
||||
if (mt_entry->missing_count < MPR_MAX_MISSING_COUNT)
|
||||
mt_entry->missing_count++;
|
||||
else
|
||||
mt_entry->init_complete = 1;
|
||||
}
|
||||
if (!mt_entry->missing_count)
|
||||
mt_entry->missing_count++;
|
||||
_mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0);
|
||||
mt_entry->dev_handle = 0;
|
||||
|
||||
if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
|
||||
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
|
||||
sc->is_dpm_enable && !mt_entry->init_complete &&
|
||||
mt_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
|
||||
dpm_entry = (Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
|
||||
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
|
||||
dpm_entry += mt_entry->dpm_entry_num;
|
||||
dpm_entry->MappingInformation = mt_entry->missing_count;
|
||||
sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1;
|
||||
}
|
||||
mt_entry->init_complete = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* _mapping_update_missing_count - Update missing count for a device
|
||||
* @sc: per adapter object
|
||||
@ -689,12 +739,9 @@ static void
|
||||
_mapping_update_missing_count(struct mpr_softc *sc,
|
||||
struct _map_topology_change *topo_change)
|
||||
{
|
||||
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
|
||||
u8 entry;
|
||||
struct _map_phy_change *phy_change;
|
||||
u32 map_idx;
|
||||
struct dev_mapping_table *mt_entry;
|
||||
Mpi2DriverMap0Entry_t *dpm_entry;
|
||||
|
||||
for (entry = 0; entry < topo_change->num_entries; entry++) {
|
||||
phy_change = &topo_change->phy_details[entry];
|
||||
@ -704,35 +751,37 @@ _mapping_update_missing_count(struct mpr_softc *sc,
|
||||
map_idx = _mapping_get_mt_idx_from_handle(sc, phy_change->
|
||||
dev_handle);
|
||||
phy_change->is_processed = 1;
|
||||
if (map_idx == MPR_MAPTABLE_BAD_IDX) {
|
||||
printf("%s: device is already removed from mapping "
|
||||
"table\n", __func__);
|
||||
continue;
|
||||
}
|
||||
mt_entry = &sc->mapping_table[map_idx];
|
||||
if (!mt_entry->init_complete) {
|
||||
if (mt_entry->missing_count < MPR_MAX_MISSING_COUNT)
|
||||
mt_entry->missing_count++;
|
||||
else
|
||||
mt_entry->init_complete = 1;
|
||||
}
|
||||
if (!mt_entry->missing_count)
|
||||
mt_entry->missing_count++;
|
||||
_mapping_add_to_removal_table(sc, mt_entry->dev_handle, 0);
|
||||
mt_entry->dev_handle = 0;
|
||||
_mapping_inc_missing_count(sc, map_idx);
|
||||
}
|
||||
}
|
||||
|
||||
if (((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
|
||||
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) &&
|
||||
sc->is_dpm_enable && !mt_entry->init_complete &&
|
||||
mt_entry->dpm_entry_num != MPR_DPM_BAD_IDX) {
|
||||
dpm_entry =
|
||||
(Mpi2DriverMap0Entry_t *) ((u8 *)sc->dpm_pg0 +
|
||||
sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
|
||||
dpm_entry += mt_entry->dpm_entry_num;
|
||||
dpm_entry->MappingInformation = mt_entry->missing_count;
|
||||
sc->dpm_flush_entry[mt_entry->dpm_entry_num] = 1;
|
||||
}
|
||||
mt_entry->init_complete = 1;
|
||||
/**
|
||||
* _mapping_update_pcie_missing_count - Update missing count for a PCIe device
|
||||
* @sc: per adapter object
|
||||
* @topo_change: Topology change event entry
|
||||
*
|
||||
* Search through the PCIe topology change list and if any device is found not
|
||||
* responding it's associated map table entry and DPM entry is updated
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
static void
|
||||
_mapping_update_pcie_missing_count(struct mpr_softc *sc,
|
||||
struct _map_pcie_topology_change *topo_change)
|
||||
{
|
||||
u8 entry;
|
||||
struct _map_port_change *port_change;
|
||||
u32 map_idx;
|
||||
|
||||
for (entry = 0; entry < topo_change->num_entries; entry++) {
|
||||
port_change = &topo_change->port_details[entry];
|
||||
if (!port_change->dev_handle || (port_change->reason !=
|
||||
MPI26_EVENT_PCIE_TOPO_PS_NOT_RESPONDING))
|
||||
continue;
|
||||
map_idx = _mapping_get_mt_idx_from_handle(sc, port_change->
|
||||
dev_handle);
|
||||
port_change->is_processed = 1;
|
||||
_mapping_inc_missing_count(sc, map_idx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -940,7 +989,7 @@ _mapping_get_dev_info(struct mpr_softc *sc,
|
||||
|
||||
phy_change->physical_id = sas_address;
|
||||
phy_change->slot = le16toh(sas_device_pg0.Slot);
|
||||
phy_change->device_info = le32toh(sas_device_pg0.DeviceInfo);
|
||||
phy_change->device_info = device_info;
|
||||
|
||||
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
|
||||
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
|
||||
@ -990,12 +1039,118 @@ _mapping_get_dev_info(struct mpr_softc *sc,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found space in enclosure for mapping entry */
|
||||
mt_entry = &sc->mapping_table[map_idx];
|
||||
for (index = map_idx; index < (et_entry->num_slots
|
||||
+ map_idx); index++, mt_entry++) {
|
||||
mt_entry->device_info = MPR_DEV_RESERVED;
|
||||
mt_entry->physical_id = et_entry->enclosure_id;
|
||||
mt_entry->phy_bits = et_entry->phy_bits;
|
||||
mt_entry->missing_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _mapping_get_pcie_dev_info -get information about newly added PCIe devices
|
||||
* @sc: per adapter object
|
||||
* @topo_change: Topology change event entry
|
||||
*
|
||||
* Searches through the PCIe topology change event list and issues PCIe device
|
||||
* pg0 requests for the newly added PCIe device. If the device is in an
|
||||
* enclosure, search for available space in the enclosure mapping table for the
|
||||
* device and reserve that space.
|
||||
*
|
||||
* Returns nothing
|
||||
*/
|
||||
static void
|
||||
_mapping_get_pcie_dev_info(struct mpr_softc *sc,
|
||||
struct _map_pcie_topology_change *topo_change)
|
||||
{
|
||||
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
Mpi26PCIeDevicePage0_t pcie_device_pg0;
|
||||
u8 entry, enc_idx, port_idx;
|
||||
u32 map_idx, index;
|
||||
struct _map_port_change *port_change, *tmp_port_change;
|
||||
uint64_t pcie_wwid;
|
||||
struct enc_mapping_table *et_entry;
|
||||
struct dev_mapping_table *mt_entry;
|
||||
u8 add_code = MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED;
|
||||
|
||||
for (entry = 0; entry < topo_change->num_entries; entry++) {
|
||||
port_change = &topo_change->port_details[entry];
|
||||
if (port_change->is_processed || !port_change->dev_handle ||
|
||||
port_change->reason != MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED)
|
||||
continue;
|
||||
if (mpr_config_get_pcie_device_pg0(sc, &mpi_reply,
|
||||
&pcie_device_pg0, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE,
|
||||
port_change->dev_handle)) {
|
||||
port_change->is_processed = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
pcie_wwid = pcie_device_pg0.WWID.High;
|
||||
pcie_wwid = (pcie_wwid << 32) | pcie_device_pg0.WWID.Low;
|
||||
port_change->physical_id = pcie_wwid;
|
||||
port_change->slot = le16toh(pcie_device_pg0.Slot);
|
||||
port_change->device_info = le32toh(pcie_device_pg0.DeviceInfo);
|
||||
|
||||
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
|
||||
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
|
||||
enc_idx = _mapping_get_enc_idx_from_handle(sc,
|
||||
topo_change->enc_handle);
|
||||
if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
|
||||
port_change->is_processed = 1;
|
||||
mpr_dprint(sc, MPR_MAPPING, "%s: failed to add "
|
||||
"the device with handle 0x%04x because the "
|
||||
"enclosure is not in the mapping table\n",
|
||||
__func__, port_change->dev_handle);
|
||||
continue;
|
||||
}
|
||||
if (!(port_change->device_info &
|
||||
MPI26_PCIE_DEVINFO_NVME)) {
|
||||
port_change->is_processed = 1;
|
||||
continue;
|
||||
}
|
||||
et_entry = &sc->enclosure_table[enc_idx];
|
||||
if (et_entry->start_index != MPR_MAPTABLE_BAD_IDX)
|
||||
continue;
|
||||
if (!topo_change->switch_dev_handle) {
|
||||
map_idx = sc->num_rsvd_entries;
|
||||
et_entry->start_index = map_idx;
|
||||
} else {
|
||||
map_idx = _mapping_find_enc_map_space(sc,
|
||||
et_entry);
|
||||
et_entry->start_index = map_idx;
|
||||
if (et_entry->start_index ==
|
||||
MPR_MAPTABLE_BAD_IDX) {
|
||||
port_change->is_processed = 1;
|
||||
for (port_idx = 0; port_idx <
|
||||
topo_change->num_entries;
|
||||
port_idx++) {
|
||||
tmp_port_change =
|
||||
&topo_change->port_details
|
||||
[port_idx];
|
||||
if (tmp_port_change->reason ==
|
||||
add_code)
|
||||
tmp_port_change->
|
||||
is_processed = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found space in enclosure for mapping entry */
|
||||
mt_entry = &sc->mapping_table[map_idx];
|
||||
for (index = map_idx; index < (et_entry->num_slots
|
||||
+ map_idx); index++, mt_entry++) {
|
||||
mt_entry->device_info = MPR_DEV_RESERVED;
|
||||
mt_entry->physical_id = et_entry->enclosure_id;
|
||||
mt_entry->phy_bits = et_entry->phy_bits;
|
||||
mt_entry->missing_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1106,8 +1261,8 @@ _mapping_clear_removed_entries(struct mpr_softc *sc)
|
||||
* @sc: per adapter object
|
||||
* @topo_change: Topology change event entry
|
||||
*
|
||||
* Search through the topology change event list and updates map table,
|
||||
* enclosure table and DPM pages for for the newly added devices.
|
||||
* Search through the topology change event list and update map table,
|
||||
* enclosure table and DPM pages for the newly added devices.
|
||||
*
|
||||
* Returns nothing
|
||||
*/
|
||||
@ -1144,10 +1299,10 @@ _mapping_add_new_device(struct mpr_softc *sc,
|
||||
(sc, topo_change->enc_handle);
|
||||
if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
|
||||
phy_change->is_processed = 1;
|
||||
printf("%s: failed to add the device with "
|
||||
"handle 0x%04x because the enclosure is "
|
||||
"not in the mapping table\n", __func__,
|
||||
phy_change->dev_handle);
|
||||
mpr_dprint(sc, MPR_ERROR, "%s: failed to add "
|
||||
"the device with handle 0x%04x because the "
|
||||
"enclosure is not in the mapping table\n",
|
||||
__func__, phy_change->dev_handle);
|
||||
continue;
|
||||
}
|
||||
et_entry = &sc->enclosure_table[enc_idx];
|
||||
@ -1157,10 +1312,11 @@ _mapping_add_new_device(struct mpr_softc *sc,
|
||||
sc->mt_add_device_failed = 1;
|
||||
continue;
|
||||
}
|
||||
printf("%s: failed to add the device with "
|
||||
"handle 0x%04x because there is no free "
|
||||
"space available in the mapping table\n",
|
||||
__func__, phy_change->dev_handle);
|
||||
mpr_dprint(sc, MPR_INFO, "%s: failed to add "
|
||||
"the device with handle 0x%04x because "
|
||||
"there is no free space available in the "
|
||||
"mapping table\n", __func__,
|
||||
phy_change->dev_handle);
|
||||
continue;
|
||||
}
|
||||
map_idx = et_entry->start_index + phy_change->slot -
|
||||
@ -1268,10 +1424,11 @@ _mapping_add_new_device(struct mpr_softc *sc,
|
||||
sc->mt_add_device_failed = 1;
|
||||
continue;
|
||||
}
|
||||
printf("%s: failed to add the device with "
|
||||
"handle 0x%04x because there is no free "
|
||||
"space available in the mapping table\n",
|
||||
__func__, phy_change->dev_handle);
|
||||
mpr_dprint(sc, MPR_INFO, "%s: failed to add "
|
||||
"the device with handle 0x%04x because "
|
||||
"there is no free space available in the "
|
||||
"mapping table\n", __func__,
|
||||
phy_change->dev_handle);
|
||||
continue;
|
||||
}
|
||||
if (sc->is_dpm_enable) {
|
||||
@ -1314,14 +1471,13 @@ _mapping_add_new_device(struct mpr_softc *sc,
|
||||
sc->dpm_flush_entry[dpm_idx] = 1;
|
||||
phy_change->is_processed = 1;
|
||||
} else if (dpm_idx == MPR_DPM_BAD_IDX) {
|
||||
phy_change->is_processed = 1;
|
||||
mpr_dprint(sc, MPR_INFO, "%s: "
|
||||
"failed to add the device "
|
||||
"with handle 0x%04x to "
|
||||
"persistent table because "
|
||||
"there is no free space "
|
||||
"available\n", __func__,
|
||||
phy_change->dev_handle);
|
||||
phy_change->is_processed = 1;
|
||||
mpr_dprint(sc, MPR_INFO, "%s: failed "
|
||||
"to add the device with handle "
|
||||
"0x%04x to persistent table "
|
||||
"because there is no free space "
|
||||
"available\n", __func__,
|
||||
phy_change->dev_handle);
|
||||
}
|
||||
}
|
||||
mt_entry->init_complete = 1;
|
||||
@ -1333,6 +1489,241 @@ _mapping_add_new_device(struct mpr_softc *sc,
|
||||
_mapping_clear_removed_entries(sc);
|
||||
}
|
||||
|
||||
/**
|
||||
* _mapping_add_new_pcie_device -Add the new PCIe device into mapping table
|
||||
* @sc: per adapter object
|
||||
* @topo_change: Topology change event entry
|
||||
*
|
||||
* Search through the PCIe topology change event list and update map table,
|
||||
* enclosure table and DPM pages for the newly added devices.
|
||||
*
|
||||
* Returns nothing
|
||||
*/
|
||||
static void
|
||||
_mapping_add_new_pcie_device(struct mpr_softc *sc,
|
||||
struct _map_pcie_topology_change *topo_change)
|
||||
{
|
||||
u8 enc_idx, missing_cnt, is_removed = 0;
|
||||
u16 dpm_idx;
|
||||
u32 search_idx, map_idx;
|
||||
u32 entry;
|
||||
struct dev_mapping_table *mt_entry;
|
||||
struct enc_mapping_table *et_entry;
|
||||
struct _map_port_change *port_change;
|
||||
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
|
||||
Mpi2DriverMap0Entry_t *dpm_entry;
|
||||
uint64_t temp64_var;
|
||||
u8 map_shift = MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT;
|
||||
u8 hdr_sz = sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER);
|
||||
u16 max_num_phy_ids = le16toh(sc->ioc_pg8.MaxNumPhysicalMappedIDs);
|
||||
|
||||
for (entry = 0; entry < topo_change->num_entries; entry++) {
|
||||
port_change = &topo_change->port_details[entry];
|
||||
if (port_change->is_processed)
|
||||
continue;
|
||||
if (port_change->reason != MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED ||
|
||||
!port_change->dev_handle) {
|
||||
port_change->is_processed = 1;
|
||||
continue;
|
||||
}
|
||||
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
|
||||
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
|
||||
enc_idx = _mapping_get_enc_idx_from_handle
|
||||
(sc, topo_change->enc_handle);
|
||||
if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
|
||||
port_change->is_processed = 1;
|
||||
mpr_dprint(sc, MPR_ERROR, "%s: failed to add "
|
||||
"the device with handle 0x%04x because the "
|
||||
"enclosure is not in the mapping table\n",
|
||||
__func__, port_change->dev_handle);
|
||||
continue;
|
||||
}
|
||||
et_entry = &sc->enclosure_table[enc_idx];
|
||||
if (et_entry->start_index == MPR_MAPTABLE_BAD_IDX) {
|
||||
port_change->is_processed = 1;
|
||||
if (!sc->mt_full_retry) {
|
||||
sc->mt_add_device_failed = 1;
|
||||
continue;
|
||||
}
|
||||
mpr_dprint(sc, MPR_INFO, "%s: failed to add "
|
||||
"the device with handle 0x%04x because "
|
||||
"there is no free space available in the "
|
||||
"mapping table\n", __func__,
|
||||
port_change->dev_handle);
|
||||
continue;
|
||||
}
|
||||
map_idx = et_entry->start_index + port_change->slot -
|
||||
et_entry->start_slot;
|
||||
mt_entry = &sc->mapping_table[map_idx];
|
||||
mt_entry->physical_id = port_change->physical_id;
|
||||
mt_entry->channel = 0;
|
||||
mt_entry->id = map_idx;
|
||||
mt_entry->dev_handle = port_change->dev_handle;
|
||||
mt_entry->missing_count = 0;
|
||||
mt_entry->dpm_entry_num = et_entry->dpm_entry_num;
|
||||
mt_entry->device_info = port_change->device_info |
|
||||
(MPR_DEV_RESERVED | MPR_MAP_IN_USE);
|
||||
if (sc->is_dpm_enable) {
|
||||
dpm_idx = et_entry->dpm_entry_num;
|
||||
if (dpm_idx == MPR_DPM_BAD_IDX)
|
||||
dpm_idx = _mapping_get_dpm_idx_from_id
|
||||
(sc, et_entry->enclosure_id,
|
||||
et_entry->phy_bits);
|
||||
if (dpm_idx == MPR_DPM_BAD_IDX) {
|
||||
dpm_idx = _mapping_get_free_dpm_idx(sc);
|
||||
if (dpm_idx != MPR_DPM_BAD_IDX) {
|
||||
dpm_entry =
|
||||
(Mpi2DriverMap0Entry_t *)
|
||||
((u8 *) sc->dpm_pg0 +
|
||||
hdr_sz);
|
||||
dpm_entry += dpm_idx;
|
||||
dpm_entry->
|
||||
PhysicalIdentifier.Low =
|
||||
(0xFFFFFFFF &
|
||||
et_entry->enclosure_id);
|
||||
dpm_entry->
|
||||
PhysicalIdentifier.High =
|
||||
( et_entry->enclosure_id
|
||||
>> 32);
|
||||
dpm_entry->DeviceIndex =
|
||||
(U16)et_entry->start_index;
|
||||
dpm_entry->MappingInformation =
|
||||
et_entry->num_slots;
|
||||
dpm_entry->MappingInformation
|
||||
<<= map_shift;
|
||||
dpm_entry->PhysicalBitsMapping
|
||||
= et_entry->phy_bits;
|
||||
et_entry->dpm_entry_num =
|
||||
dpm_idx;
|
||||
/* FIXME Do I need to set the dpm_idxin mt_entry too */
|
||||
sc->dpm_entry_used[dpm_idx] = 1;
|
||||
sc->dpm_flush_entry[dpm_idx] =
|
||||
1;
|
||||
port_change->is_processed = 1;
|
||||
} else {
|
||||
port_change->is_processed = 1;
|
||||
mpr_dprint(sc, MPR_INFO, "%s: "
|
||||
"failed to add the device "
|
||||
"with handle 0x%04x to "
|
||||
"persistent table because "
|
||||
"there is no free space "
|
||||
"available\n", __func__,
|
||||
port_change->dev_handle);
|
||||
}
|
||||
} else {
|
||||
et_entry->dpm_entry_num = dpm_idx;
|
||||
mt_entry->dpm_entry_num = dpm_idx;
|
||||
}
|
||||
}
|
||||
/* FIXME Why not mt_entry too? */
|
||||
et_entry->init_complete = 1;
|
||||
} else if ((ioc_pg8_flags &
|
||||
MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
|
||||
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
|
||||
map_idx = _mapping_get_mt_idx_from_id
|
||||
(sc, port_change->physical_id);
|
||||
if (map_idx == MPR_MAPTABLE_BAD_IDX) {
|
||||
search_idx = sc->num_rsvd_entries;
|
||||
if (topo_change->switch_dev_handle)
|
||||
search_idx += max_num_phy_ids;
|
||||
map_idx = _mapping_get_free_mt_idx(sc,
|
||||
search_idx);
|
||||
}
|
||||
if (map_idx == MPR_MAPTABLE_BAD_IDX) {
|
||||
map_idx = _mapping_get_high_missing_mt_idx(sc);
|
||||
if (map_idx != MPR_MAPTABLE_BAD_IDX) {
|
||||
mt_entry = &sc->mapping_table[map_idx];
|
||||
if (mt_entry->dev_handle) {
|
||||
_mapping_add_to_removal_table
|
||||
(sc, mt_entry->dev_handle,
|
||||
0);
|
||||
is_removed = 1;
|
||||
}
|
||||
mt_entry->init_complete = 0;
|
||||
}
|
||||
}
|
||||
if (map_idx != MPR_MAPTABLE_BAD_IDX) {
|
||||
mt_entry = &sc->mapping_table[map_idx];
|
||||
mt_entry->physical_id =
|
||||
port_change->physical_id;
|
||||
mt_entry->channel = 0;
|
||||
mt_entry->id = map_idx;
|
||||
mt_entry->dev_handle = port_change->dev_handle;
|
||||
mt_entry->missing_count = 0;
|
||||
mt_entry->device_info =
|
||||
port_change->device_info |
|
||||
(MPR_DEV_RESERVED | MPR_MAP_IN_USE);
|
||||
} else {
|
||||
port_change->is_processed = 1;
|
||||
if (!sc->mt_full_retry) {
|
||||
sc->mt_add_device_failed = 1;
|
||||
continue;
|
||||
}
|
||||
mpr_dprint(sc, MPR_INFO, "%s: failed to add "
|
||||
"the device with handle 0x%04x because "
|
||||
"there is no free space available in the "
|
||||
"mapping table\n", __func__,
|
||||
port_change->dev_handle);
|
||||
continue;
|
||||
}
|
||||
if (sc->is_dpm_enable) {
|
||||
if (mt_entry->dpm_entry_num !=
|
||||
MPR_DPM_BAD_IDX) {
|
||||
dpm_idx = mt_entry->dpm_entry_num;
|
||||
dpm_entry = (Mpi2DriverMap0Entry_t *)
|
||||
((u8 *)sc->dpm_pg0 + hdr_sz);
|
||||
dpm_entry += dpm_idx;
|
||||
missing_cnt = dpm_entry->
|
||||
MappingInformation &
|
||||
MPI2_DRVMAP0_MAPINFO_MISSING_MASK;
|
||||
temp64_var = dpm_entry->
|
||||
PhysicalIdentifier.High;
|
||||
temp64_var = (temp64_var << 32) |
|
||||
dpm_entry->PhysicalIdentifier.Low;
|
||||
if ((mt_entry->physical_id ==
|
||||
temp64_var) && !missing_cnt)
|
||||
mt_entry->init_complete = 1;
|
||||
} else {
|
||||
dpm_idx = _mapping_get_free_dpm_idx(sc);
|
||||
mt_entry->init_complete = 0;
|
||||
}
|
||||
if (dpm_idx != MPR_DPM_BAD_IDX &&
|
||||
!mt_entry->init_complete) {
|
||||
mt_entry->init_complete = 1;
|
||||
mt_entry->dpm_entry_num = dpm_idx;
|
||||
dpm_entry = (Mpi2DriverMap0Entry_t *)
|
||||
((u8 *)sc->dpm_pg0 + hdr_sz);
|
||||
dpm_entry += dpm_idx;
|
||||
dpm_entry->PhysicalIdentifier.Low =
|
||||
(0xFFFFFFFF &
|
||||
mt_entry->physical_id);
|
||||
dpm_entry->PhysicalIdentifier.High =
|
||||
(mt_entry->physical_id >> 32);
|
||||
dpm_entry->DeviceIndex = (U16) map_idx;
|
||||
dpm_entry->MappingInformation = 0;
|
||||
dpm_entry->PhysicalBitsMapping = 0;
|
||||
sc->dpm_entry_used[dpm_idx] = 1;
|
||||
sc->dpm_flush_entry[dpm_idx] = 1;
|
||||
port_change->is_processed = 1;
|
||||
} else if (dpm_idx == MPR_DPM_BAD_IDX) {
|
||||
port_change->is_processed = 1;
|
||||
mpr_dprint(sc, MPR_INFO, "%s: failed "
|
||||
"to add the device with handle "
|
||||
"0x%04x to persistent table "
|
||||
"because there is no free space "
|
||||
"available\n", __func__,
|
||||
port_change->dev_handle);
|
||||
}
|
||||
}
|
||||
mt_entry->init_complete = 1;
|
||||
}
|
||||
|
||||
port_change->is_processed = 1;
|
||||
}
|
||||
if (is_removed)
|
||||
_mapping_clear_removed_entries(sc);
|
||||
}
|
||||
|
||||
/**
|
||||
* _mapping_flush_dpm_pages -Flush the DPM pages to NVRAM
|
||||
* @sc: per adapter object
|
||||
@ -2072,6 +2463,56 @@ mpr_mapping_topology_change_event(struct mpr_softc *sc,
|
||||
sc->pending_map_events--;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpr_mapping_pcie_topology_change_event - handle PCIe topology change events
|
||||
* @sc: per adapter object
|
||||
* @event_data: event data payload
|
||||
*
|
||||
* Returns nothing.
|
||||
*/
|
||||
void
|
||||
mpr_mapping_pcie_topology_change_event(struct mpr_softc *sc,
|
||||
Mpi26EventDataPCIeTopologyChangeList_t *event_data)
|
||||
{
|
||||
struct _map_pcie_topology_change topo_change;
|
||||
struct _map_port_change *port_change;
|
||||
Mpi26EventPCIeTopoPortEntry_t *event_port_change;
|
||||
u8 i, num_entries;
|
||||
|
||||
topo_change.switch_dev_handle = le16toh(event_data->SwitchDevHandle);
|
||||
topo_change.enc_handle = le16toh(event_data->EnclosureHandle);
|
||||
num_entries = event_data->NumEntries;
|
||||
topo_change.num_entries = num_entries;
|
||||
topo_change.start_port_num = event_data->StartPortNum;
|
||||
topo_change.num_ports = event_data->NumPorts;
|
||||
topo_change.switch_status = event_data->SwitchStatus;
|
||||
event_port_change = event_data->PortEntry;
|
||||
topo_change.port_details = NULL;
|
||||
|
||||
if (!num_entries)
|
||||
goto out;
|
||||
port_change = malloc(sizeof(struct _map_port_change) * num_entries,
|
||||
M_MPR, M_NOWAIT|M_ZERO);
|
||||
topo_change.port_details = port_change;
|
||||
if (!port_change)
|
||||
goto out;
|
||||
for (i = 0; i < num_entries; i++, event_port_change++, port_change++) {
|
||||
port_change->dev_handle = le16toh(event_port_change->
|
||||
AttachedDevHandle);
|
||||
port_change->reason = event_port_change->PortStatus;
|
||||
}
|
||||
_mapping_update_pcie_missing_count(sc, &topo_change);
|
||||
_mapping_get_pcie_dev_info(sc, &topo_change);
|
||||
_mapping_clear_removed_entries(sc);
|
||||
_mapping_add_new_pcie_device(sc, &topo_change);
|
||||
|
||||
out:
|
||||
free(topo_change.port_details, M_MPR);
|
||||
_mapping_flush_dpm_pages(sc);
|
||||
if (sc->pending_map_events)
|
||||
sc->pending_map_events--;
|
||||
}
|
||||
|
||||
/**
|
||||
* _mapping_check_update_ir_mt_idx - Check and update IR map table index
|
||||
* @sc: per adapter object
|
||||
|
@ -53,9 +53,36 @@ struct _map_phy_change {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct _map_topology_change - entries to be removed from mapping table
|
||||
* @dpm_entry_num: index of this device in device persistent map table
|
||||
* struct _map_port_change - PCIe Port entries received in PCIe Topology change
|
||||
* list event
|
||||
* @physical_id: WWID of the device attached to the associated port
|
||||
* @device_info: bitfield provides detailed info about the device
|
||||
* @MDTS: Maximum Data Transfer Size for the device
|
||||
* @dev_handle: device handle for the device pointed by this entry
|
||||
* @slot: slot ID
|
||||
* @is_processed: Flag to indicate whether this entry is processed or not
|
||||
*/
|
||||
struct _map_port_change {
|
||||
uint64_t physical_id;
|
||||
uint32_t device_info;
|
||||
uint32_t MDTS;
|
||||
uint16_t dev_handle;
|
||||
uint16_t slot;
|
||||
uint8_t reason;
|
||||
uint8_t is_processed;
|
||||
uint8_t reserved[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct _map_topology_change - SAS/SATA entries to be removed from mapping
|
||||
* table
|
||||
* @enc_handle: enclosure handle where this device is located
|
||||
* @exp_handle: expander handle where this device is located
|
||||
* @num_entries: number of entries in the SAS Topology Change List event
|
||||
* @start_phy_num: PHY number of the first PHY in the event data
|
||||
* @num_phys: number of PHYs in the expander where this device is located
|
||||
* @exp_status: status for the expander where this device is located
|
||||
* @phy_details: more details about each PHY in the event data
|
||||
*/
|
||||
struct _map_topology_change {
|
||||
uint16_t enc_handle;
|
||||
@ -67,6 +94,26 @@ struct _map_topology_change {
|
||||
struct _map_phy_change *phy_details;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct _map_pcie_topology_change - PCIe entries to be removed from mapping
|
||||
* table
|
||||
* @enc_handle: enclosure handle where this device is located
|
||||
* @switch_dev_handle: PCIe switch device handle where this device is located
|
||||
* @num_entries: number of entries in the PCIe Topology Change List event
|
||||
* @start_port_num: port number of the first port in the event data
|
||||
* @num_ports: number of ports in the PCIe switch device
|
||||
* @switch_status: status for the PCIe switch where this device is located
|
||||
* @port_details: more details about each Port in the event data
|
||||
*/
|
||||
struct _map_pcie_topology_change {
|
||||
uint16_t enc_handle;
|
||||
uint16_t switch_dev_handle;
|
||||
uint8_t num_entries;
|
||||
uint8_t start_port_num;
|
||||
uint8_t num_ports;
|
||||
uint8_t switch_status;
|
||||
struct _map_port_change *port_details;
|
||||
};
|
||||
|
||||
extern int
|
||||
mprsas_get_sas_address_for_sata_disk(struct mpr_softc *ioc,
|
||||
|
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mpr/mpi/mpi2_ioc.h>
|
||||
#include <dev/mpr/mpi/mpi2_cnfg.h>
|
||||
#include <dev/mpr/mpi/mpi2_tool.h>
|
||||
#include <dev/mpr/mpi/mpi2_pci.h>
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/kthread.h>
|
||||
@ -110,6 +111,10 @@ struct mpr_ident {
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3216,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3216" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3224,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3224" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_1,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3316_1" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_2,
|
||||
@ -118,10 +123,24 @@ struct mpr_ident {
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3324_1" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_2,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3324_2" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3216,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3216" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3224,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3224" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3408,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3408" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3416,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3416" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3508,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3508" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3508_1,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3508_1" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3516,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3516" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3516_1,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3516_1" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3616,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3616" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3708,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3708" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3716,
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3716" },
|
||||
{ 0, 0, 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
@ -164,7 +183,7 @@ mpr_pci_attach(device_t dev)
|
||||
{
|
||||
struct mpr_softc *sc;
|
||||
struct mpr_ident *m;
|
||||
int error;
|
||||
int error, i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
bzero(sc, sizeof(*sc));
|
||||
@ -175,13 +194,32 @@ mpr_pci_attach(device_t dev)
|
||||
/* Twiddle basic PCI config bits for a sanity check */
|
||||
pci_enable_busmaster(dev);
|
||||
|
||||
/* Allocate the System Interface Register Set */
|
||||
sc->mpr_regs_rid = PCIR_BAR(1);
|
||||
if ((sc->mpr_regs_resource = bus_alloc_resource_any(dev,
|
||||
SYS_RES_MEMORY, &sc->mpr_regs_rid, RF_ACTIVE)) == NULL) {
|
||||
/* Set flag if this is a Gen3.5 IOC */
|
||||
if ((m->device == MPI26_MFGPAGE_DEVID_SAS3508) ||
|
||||
(m->device == MPI26_MFGPAGE_DEVID_SAS3508_1) ||
|
||||
(m->device == MPI26_MFGPAGE_DEVID_SAS3408) ||
|
||||
(m->device == MPI26_MFGPAGE_DEVID_SAS3516) ||
|
||||
(m->device == MPI26_MFGPAGE_DEVID_SAS3516_1) ||
|
||||
(m->device == MPI26_MFGPAGE_DEVID_SAS3416) ||
|
||||
(m->device == MPI26_MFGPAGE_DEVID_SAS3716) ||
|
||||
(m->device == MPI26_MFGPAGE_DEVID_SAS3616) ||
|
||||
(m->device == MPI26_MFGPAGE_DEVID_SAS3708)) {
|
||||
sc->mpr_flags |= MPR_FLAGS_GEN35_IOC;
|
||||
}
|
||||
|
||||
for (i = 0; i < PCI_MAXMAPS_0; i++) {
|
||||
sc->mpr_regs_rid = PCIR_BAR(i);
|
||||
|
||||
if ((sc->mpr_regs_resource = bus_alloc_resource_any(dev,
|
||||
SYS_RES_MEMORY, &sc->mpr_regs_rid, RF_ACTIVE)) != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sc->mpr_regs_resource == NULL) {
|
||||
mpr_printf(sc, "Cannot allocate PCI registers\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->mpr_btag = rman_get_bustag(sc->mpr_regs_resource);
|
||||
sc->mpr_bhandle = rman_get_bushandle(sc->mpr_regs_resource);
|
||||
|
||||
|
@ -72,10 +72,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/scsi/smp_all.h>
|
||||
#endif
|
||||
|
||||
#include <dev/nvme/nvme.h>
|
||||
|
||||
#include <dev/mpr/mpi/mpi2_type.h>
|
||||
#include <dev/mpr/mpi/mpi2.h>
|
||||
#include <dev/mpr/mpi/mpi2_ioc.h>
|
||||
#include <dev/mpr/mpi/mpi2_sas.h>
|
||||
#include <dev/mpr/mpi/mpi2_pci.h>
|
||||
#include <dev/mpr/mpi/mpi2_cnfg.h>
|
||||
#include <dev/mpr/mpi/mpi2_init.h>
|
||||
#include <dev/mpr/mpi/mpi2_tool.h>
|
||||
@ -477,13 +480,13 @@ mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle)
|
||||
}
|
||||
|
||||
/*
|
||||
* The MPT3 firmware performs debounce on the link to avoid transient link
|
||||
* errors and false removals. When it does decide that link has been lost
|
||||
* and a device needs to go away, it expects that the host will perform a
|
||||
* target reset and then an op remove. The reset has the side-effect of
|
||||
* aborting any outstanding requests for the device, which is required for
|
||||
* the op-remove to succeed. It's not clear if the host should check for
|
||||
* the device coming back alive after the reset.
|
||||
* The firmware performs debounce on the link to avoid transient link errors
|
||||
* and false removals. When it does decide that link has been lost and a
|
||||
* device needs to go away, it expects that the host will perform a target reset
|
||||
* and then an op remove. The reset has the side-effect of aborting any
|
||||
* outstanding requests for the device, which is required for the op-remove to
|
||||
* succeed. It's not clear if the host should check for the device coming back
|
||||
* alive after the reset.
|
||||
*/
|
||||
void
|
||||
mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle)
|
||||
@ -705,7 +708,14 @@ mprsas_register_events(struct mpr_softc *sc)
|
||||
setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK);
|
||||
setbit(events, MPI2_EVENT_IR_OPERATION_STATUS);
|
||||
setbit(events, MPI2_EVENT_TEMP_THRESHOLD);
|
||||
setbit(events, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
|
||||
if (sc->facts->MsgVersion >= MPI2_VERSION_02_06) {
|
||||
setbit(events, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
|
||||
if (sc->mpr_flags & MPR_FLAGS_GEN35_IOC) {
|
||||
setbit(events, MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE);
|
||||
setbit(events, MPI2_EVENT_PCIE_ENUMERATION);
|
||||
setbit(events, MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST);
|
||||
}
|
||||
}
|
||||
|
||||
mpr_register_events(sc, events, mprsas_evt_handler, NULL,
|
||||
&sc->sassc->mprsas_eh);
|
||||
@ -1018,6 +1028,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb)
|
||||
if ((sc->max_io_pages > 0) && (sc->max_io_pages * PAGE_SIZE <
|
||||
cpi->maxio))
|
||||
cpi->maxio = sc->max_io_pages * PAGE_SIZE;
|
||||
sc->maxio = cpi->maxio;
|
||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
|
||||
break;
|
||||
}
|
||||
@ -1636,7 +1647,7 @@ mprsas_scsiio_timeout(void *data)
|
||||
targ->timeouts++;
|
||||
|
||||
mprsas_log_command(cm, MPR_ERROR, "command timeout %d cm %p target "
|
||||
"%u, handle(0x%04x)\n", cm->cm_ccb->ccb_h.timeout, cm, targ->tid,
|
||||
"%u, handle(0x%04x)\n", cm->cm_ccb->ccb_h.timeout, cm, targ->tid,
|
||||
targ->handle);
|
||||
if (targ->encl_level_valid) {
|
||||
mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, "
|
||||
@ -1680,6 +1691,160 @@ mprsas_scsiio_timeout(void *data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mprsas_build_nvme_unmap - Build Native NVMe DSM command equivalent
|
||||
* to SCSI Unmap.
|
||||
* Return 0 - for success,
|
||||
* 1 - to immediately return back the command with success status to CAM
|
||||
* negative value - to fallback to firmware path i.e. issue scsi unmap
|
||||
* to FW without any translation.
|
||||
*/
|
||||
static int
|
||||
mprsas_build_nvme_unmap(struct mpr_softc *sc, struct mpr_command *cm,
|
||||
union ccb *ccb, struct mprsas_target *targ)
|
||||
{
|
||||
Mpi26NVMeEncapsulatedRequest_t *req = NULL;
|
||||
struct ccb_scsiio *csio;
|
||||
struct unmap_parm_list *plist;
|
||||
struct nvme_dsm_range *nvme_dsm_ranges = NULL;
|
||||
struct nvme_command *c;
|
||||
int i, res;
|
||||
uint16_t ndesc, list_len, data_length;
|
||||
struct mpr_prp_page *prp_page_info;
|
||||
uint64_t nvme_dsm_ranges_dma_handle;
|
||||
|
||||
csio = &ccb->csio;
|
||||
#if __FreeBSD_version >= 1100103
|
||||
list_len = (scsiio_cdb_ptr(csio)[7] << 8 | scsiio_cdb_ptr(csio)[8]);
|
||||
#else
|
||||
if (csio->ccb_h.flags & CAM_CDB_POINTER) {
|
||||
list_len = (ccb->csio.cdb_io.cdb_ptr[7] << 8 |
|
||||
ccb->csio.cdb_io.cdb_ptr[8]);
|
||||
} else {
|
||||
list_len = (ccb->csio.cdb_io.cdb_bytes[7] << 8 |
|
||||
ccb->csio.cdb_io.cdb_bytes[8]);
|
||||
}
|
||||
#endif
|
||||
if (!list_len) {
|
||||
mpr_dprint(sc, MPR_ERROR, "Parameter list length is Zero\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
plist = malloc(csio->dxfer_len, M_MPR, M_ZERO|M_NOWAIT);
|
||||
if (!plist) {
|
||||
mpr_dprint(sc, MPR_ERROR, "Unable to allocate memory to "
|
||||
"save UNMAP data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Copy SCSI unmap data to a local buffer */
|
||||
bcopy(csio->data_ptr, plist, csio->dxfer_len);
|
||||
|
||||
/* return back the unmap command to CAM with success status,
|
||||
* if number of descripts is zero.
|
||||
*/
|
||||
ndesc = be16toh(plist->unmap_blk_desc_data_len) >> 4;
|
||||
if (!ndesc) {
|
||||
mpr_dprint(sc, MPR_XINFO, "Number of descriptors in "
|
||||
"UNMAP cmd is Zero\n");
|
||||
res = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data_length = ndesc * sizeof(struct nvme_dsm_range);
|
||||
if (data_length > targ->MDTS) {
|
||||
mpr_dprint(sc, MPR_ERROR, "data length: %d is greater than "
|
||||
"Device's MDTS: %d\n", data_length, targ->MDTS);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
prp_page_info = mpr_alloc_prp_page(sc);
|
||||
KASSERT(prp_page_info != NULL, ("%s: There is no PRP Page for "
|
||||
"UNMAP command.\n", __func__));
|
||||
|
||||
/*
|
||||
* Insert the allocated PRP page into the command's PRP page list. This
|
||||
* will be freed when the command is freed.
|
||||
*/
|
||||
TAILQ_INSERT_TAIL(&cm->cm_prp_page_list, prp_page_info, prp_page_link);
|
||||
|
||||
nvme_dsm_ranges = (struct nvme_dsm_range *)prp_page_info->prp_page;
|
||||
nvme_dsm_ranges_dma_handle = prp_page_info->prp_page_busaddr;
|
||||
|
||||
bzero(nvme_dsm_ranges, data_length);
|
||||
|
||||
/* Convert SCSI unmap's descriptor data to NVMe DSM specific Range data
|
||||
* for each descriptors contained in SCSI UNMAP data.
|
||||
*/
|
||||
for (i = 0; i < ndesc; i++) {
|
||||
nvme_dsm_ranges[i].length =
|
||||
htole32(be32toh(plist->desc[i].nlb));
|
||||
nvme_dsm_ranges[i].starting_lba =
|
||||
htole64(be64toh(plist->desc[i].slba));
|
||||
nvme_dsm_ranges[i].attributes = 0;
|
||||
}
|
||||
|
||||
/* Build MPI2.6's NVMe Encapsulated Request Message */
|
||||
req = (Mpi26NVMeEncapsulatedRequest_t *)cm->cm_req;
|
||||
bzero(req, sizeof(*req));
|
||||
req->DevHandle = htole16(targ->handle);
|
||||
req->Function = MPI2_FUNCTION_NVME_ENCAPSULATED;
|
||||
req->Flags = MPI26_NVME_FLAGS_WRITE;
|
||||
req->ErrorResponseBaseAddress.High =
|
||||
htole32((uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32));
|
||||
req->ErrorResponseBaseAddress.Low =
|
||||
htole32(cm->cm_sense_busaddr);
|
||||
req->ErrorResponseAllocationLength =
|
||||
htole16(sizeof(struct nvme_completion));
|
||||
req->EncapsulatedCommandLength =
|
||||
htole16(sizeof(struct nvme_command));
|
||||
req->DataLength = htole32(data_length);
|
||||
|
||||
/* Build NVMe DSM command */
|
||||
c = (struct nvme_command *) req->NVMe_Command;
|
||||
c->opc = NVME_OPC_DATASET_MANAGEMENT;
|
||||
c->nsid = htole32(csio->ccb_h.target_lun + 1);
|
||||
c->cdw10 = htole32(ndesc - 1);
|
||||
c->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE);
|
||||
|
||||
cm->cm_length = data_length;
|
||||
cm->cm_data = NULL;
|
||||
|
||||
cm->cm_complete = mprsas_scsiio_complete;
|
||||
cm->cm_complete_data = ccb;
|
||||
cm->cm_targ = targ;
|
||||
cm->cm_lun = csio->ccb_h.target_lun;
|
||||
cm->cm_ccb = ccb;
|
||||
|
||||
cm->cm_desc.Default.RequestFlags =
|
||||
MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
|
||||
|
||||
#if __FreeBSD_version >= 1000029
|
||||
callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0,
|
||||
mprsas_scsiio_timeout, cm, 0);
|
||||
#else //__FreeBSD_version < 1000029
|
||||
callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000,
|
||||
mprsas_scsiio_timeout, cm);
|
||||
#endif //__FreeBSD_version >= 1000029
|
||||
|
||||
targ->issued++;
|
||||
targ->outstanding++;
|
||||
TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link);
|
||||
ccb->ccb_h.status |= CAM_SIM_QUEUED;
|
||||
|
||||
mprsas_log_command(cm, MPR_XINFO, "%s cm %p ccb %p outstanding %u\n",
|
||||
__func__, cm, ccb, targ->outstanding);
|
||||
|
||||
mpr_build_nvme_prp(sc, cm, req, (void *)nvme_dsm_ranges_dma_handle, 0,
|
||||
data_length);
|
||||
mpr_map_command(sc, cm);
|
||||
|
||||
out:
|
||||
free(plist, M_MPR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
|
||||
{
|
||||
@ -1689,9 +1854,10 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
|
||||
struct mprsas_target *targ;
|
||||
struct mprsas_lun *lun;
|
||||
struct mpr_command *cm;
|
||||
uint8_t i, lba_byte, *ref_tag_addr;
|
||||
uint8_t i, lba_byte, *ref_tag_addr, scsi_opcode;
|
||||
uint16_t eedp_flags;
|
||||
uint32_t mpi_control;
|
||||
int rc;
|
||||
|
||||
sc = sassc->sc;
|
||||
MPR_FUNCTRACE(sc);
|
||||
@ -1777,6 +1943,30 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
|
||||
return;
|
||||
}
|
||||
|
||||
/* For NVME device's issue UNMAP command directly to NVME drives by
|
||||
* constructing equivalent native NVMe DataSetManagement command.
|
||||
*/
|
||||
#if __FreeBSD_version >= 1100103
|
||||
scsi_opcode = scsiio_cdb_ptr(csio)[0];
|
||||
#else
|
||||
if (csio->ccb_h.flags & CAM_CDB_POINTER)
|
||||
scsi_opcode = csio->cdb_io.cdb_ptr[0];
|
||||
else
|
||||
scsi_opcode = csio->cdb_io.cdb_bytes[0];
|
||||
#endif
|
||||
if (scsi_opcode == UNMAP &&
|
||||
targ->is_nvme &&
|
||||
(csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
|
||||
rc = mprsas_build_nvme_unmap(sc, cm, ccb, targ);
|
||||
if (rc == 1) { /* return command to CAM with success status */
|
||||
mpr_free_command(sc, cm);
|
||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
|
||||
xpt_done(ccb);
|
||||
return;
|
||||
} else if (!rc) /* Issued NVMe Encapsulated Request Message */
|
||||
return;
|
||||
}
|
||||
|
||||
req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req;
|
||||
bzero(req, sizeof(*req));
|
||||
req->DevHandle = htole16(targ->handle);
|
||||
@ -1849,8 +2039,8 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
|
||||
bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len);
|
||||
else {
|
||||
KASSERT(csio->cdb_len <= IOCDBLEN,
|
||||
("cdb_len %d is greater than IOCDBLEN but CAM_CDB_POINTER is not set",
|
||||
csio->cdb_len));
|
||||
("cdb_len %d is greater than IOCDBLEN but CAM_CDB_POINTER "
|
||||
"is not set", csio->cdb_len));
|
||||
bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len);
|
||||
}
|
||||
req->IoFlags = htole16(csio->cdb_len);
|
||||
@ -1874,6 +2064,10 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
|
||||
eedp_flags |= (MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
|
||||
MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
|
||||
MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD);
|
||||
if (sc->mpr_flags & MPR_FLAGS_GEN35_IOC) {
|
||||
eedp_flags |=
|
||||
MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE;
|
||||
}
|
||||
req->EEDPFlags = htole16(eedp_flags);
|
||||
|
||||
/*
|
||||
@ -1933,11 +2127,15 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
|
||||
req->IoFlags |= MPI25_SCSIIO_IOFLAGS_FAST_PATH;
|
||||
cm->cm_desc.FastPathSCSIIO.RequestFlags =
|
||||
MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
|
||||
cm->cm_desc.FastPathSCSIIO.DevHandle = htole16(targ->handle);
|
||||
if (!sc->atomic_desc_capable) {
|
||||
cm->cm_desc.FastPathSCSIIO.DevHandle =
|
||||
htole16(targ->handle);
|
||||
}
|
||||
} else {
|
||||
cm->cm_desc.SCSIIO.RequestFlags =
|
||||
MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
|
||||
cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle);
|
||||
if (!sc->atomic_desc_capable)
|
||||
cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle);
|
||||
}
|
||||
|
||||
#if __FreeBSD_version >= 1000029
|
||||
@ -2160,6 +2358,200 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio,
|
||||
}
|
||||
}
|
||||
|
||||
/** mprsas_nvme_trans_status_code
|
||||
*
|
||||
* Convert Native NVMe command error status to
|
||||
* equivalent SCSI error status.
|
||||
*
|
||||
* Returns appropriate scsi_status
|
||||
*/
|
||||
static u8
|
||||
mprsas_nvme_trans_status_code(struct nvme_status nvme_status,
|
||||
struct mpr_command *cm)
|
||||
{
|
||||
u8 status = MPI2_SCSI_STATUS_GOOD;
|
||||
int skey, asc, ascq;
|
||||
union ccb *ccb = cm->cm_complete_data;
|
||||
int returned_sense_len;
|
||||
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_ILLEGAL_REQUEST;
|
||||
asc = SCSI_ASC_NO_SENSE;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
|
||||
switch (nvme_status.sct) {
|
||||
case NVME_SCT_GENERIC:
|
||||
switch (nvme_status.sc) {
|
||||
case NVME_SC_SUCCESS:
|
||||
status = MPI2_SCSI_STATUS_GOOD;
|
||||
skey = SSD_KEY_NO_SENSE;
|
||||
asc = SCSI_ASC_NO_SENSE;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_INVALID_OPCODE:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_ILLEGAL_REQUEST;
|
||||
asc = SCSI_ASC_ILLEGAL_COMMAND;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_INVALID_FIELD:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_ILLEGAL_REQUEST;
|
||||
asc = SCSI_ASC_INVALID_CDB;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_DATA_TRANSFER_ERROR:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_MEDIUM_ERROR;
|
||||
asc = SCSI_ASC_NO_SENSE;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_ABORTED_POWER_LOSS:
|
||||
status = MPI2_SCSI_STATUS_TASK_ABORTED;
|
||||
skey = SSD_KEY_ABORTED_COMMAND;
|
||||
asc = SCSI_ASC_WARNING;
|
||||
ascq = SCSI_ASCQ_POWER_LOSS_EXPECTED;
|
||||
break;
|
||||
case NVME_SC_INTERNAL_DEVICE_ERROR:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_HARDWARE_ERROR;
|
||||
asc = SCSI_ASC_INTERNAL_TARGET_FAILURE;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_ABORTED_BY_REQUEST:
|
||||
case NVME_SC_ABORTED_SQ_DELETION:
|
||||
case NVME_SC_ABORTED_FAILED_FUSED:
|
||||
case NVME_SC_ABORTED_MISSING_FUSED:
|
||||
status = MPI2_SCSI_STATUS_TASK_ABORTED;
|
||||
skey = SSD_KEY_ABORTED_COMMAND;
|
||||
asc = SCSI_ASC_NO_SENSE;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_INVALID_NAMESPACE_OR_FORMAT:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_ILLEGAL_REQUEST;
|
||||
asc = SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID;
|
||||
ascq = SCSI_ASCQ_INVALID_LUN_ID;
|
||||
break;
|
||||
case NVME_SC_LBA_OUT_OF_RANGE:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_ILLEGAL_REQUEST;
|
||||
asc = SCSI_ASC_ILLEGAL_BLOCK;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_CAPACITY_EXCEEDED:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_MEDIUM_ERROR;
|
||||
asc = SCSI_ASC_NO_SENSE;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_NAMESPACE_NOT_READY:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_NOT_READY;
|
||||
asc = SCSI_ASC_LUN_NOT_READY;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NVME_SCT_COMMAND_SPECIFIC:
|
||||
switch (nvme_status.sc) {
|
||||
case NVME_SC_INVALID_FORMAT:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_ILLEGAL_REQUEST;
|
||||
asc = SCSI_ASC_FORMAT_COMMAND_FAILED;
|
||||
ascq = SCSI_ASCQ_FORMAT_COMMAND_FAILED;
|
||||
break;
|
||||
case NVME_SC_CONFLICTING_ATTRIBUTES:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_ILLEGAL_REQUEST;
|
||||
asc = SCSI_ASC_INVALID_CDB;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NVME_SCT_MEDIA_ERROR:
|
||||
switch (nvme_status.sc) {
|
||||
case NVME_SC_WRITE_FAULTS:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_MEDIUM_ERROR;
|
||||
asc = SCSI_ASC_PERIPHERAL_DEV_WRITE_FAULT;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_UNRECOVERED_READ_ERROR:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_MEDIUM_ERROR;
|
||||
asc = SCSI_ASC_UNRECOVERED_READ_ERROR;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_GUARD_CHECK_ERROR:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_MEDIUM_ERROR;
|
||||
asc = SCSI_ASC_LOG_BLOCK_GUARD_CHECK_FAILED;
|
||||
ascq = SCSI_ASCQ_LOG_BLOCK_GUARD_CHECK_FAILED;
|
||||
break;
|
||||
case NVME_SC_APPLICATION_TAG_CHECK_ERROR:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_MEDIUM_ERROR;
|
||||
asc = SCSI_ASC_LOG_BLOCK_APPTAG_CHECK_FAILED;
|
||||
ascq = SCSI_ASCQ_LOG_BLOCK_APPTAG_CHECK_FAILED;
|
||||
break;
|
||||
case NVME_SC_REFERENCE_TAG_CHECK_ERROR:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_MEDIUM_ERROR;
|
||||
asc = SCSI_ASC_LOG_BLOCK_REFTAG_CHECK_FAILED;
|
||||
ascq = SCSI_ASCQ_LOG_BLOCK_REFTAG_CHECK_FAILED;
|
||||
break;
|
||||
case NVME_SC_COMPARE_FAILURE:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_MISCOMPARE;
|
||||
asc = SCSI_ASC_MISCOMPARE_DURING_VERIFY;
|
||||
ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case NVME_SC_ACCESS_DENIED:
|
||||
status = MPI2_SCSI_STATUS_CHECK_CONDITION;
|
||||
skey = SSD_KEY_ILLEGAL_REQUEST;
|
||||
asc = SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID;
|
||||
ascq = SCSI_ASCQ_INVALID_LUN_ID;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
returned_sense_len = sizeof(struct scsi_sense_data);
|
||||
if (returned_sense_len < ccb->csio.sense_len)
|
||||
ccb->csio.sense_resid = ccb->csio.sense_len -
|
||||
returned_sense_len;
|
||||
else
|
||||
ccb->csio.sense_resid = 0;
|
||||
|
||||
scsi_set_sense_data(&ccb->csio.sense_data, SSD_TYPE_FIXED,
|
||||
1, skey, asc, ascq, SSD_ELEM_NONE);
|
||||
ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** mprsas_complete_nvme_unmap
|
||||
*
|
||||
* Complete native NVMe command issued using NVMe Encapsulated
|
||||
* Request Message.
|
||||
*/
|
||||
static u8
|
||||
mprsas_complete_nvme_unmap(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
{
|
||||
Mpi26NVMeEncapsulatedErrorReply_t *mpi_reply;
|
||||
struct nvme_completion *nvme_completion = NULL;
|
||||
u8 scsi_status = MPI2_SCSI_STATUS_GOOD;
|
||||
|
||||
mpi_reply =(Mpi26NVMeEncapsulatedErrorReply_t *)cm->cm_reply;
|
||||
if (le16toh(mpi_reply->ErrorResponseCount)){
|
||||
nvme_completion = (struct nvme_completion *)cm->cm_sense;
|
||||
scsi_status = mprsas_nvme_trans_status_code(
|
||||
nvme_completion->status, cm);
|
||||
}
|
||||
return scsi_status;
|
||||
}
|
||||
|
||||
static void
|
||||
mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
{
|
||||
@ -2168,7 +2560,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
struct ccb_scsiio *csio;
|
||||
struct mprsas_softc *sassc;
|
||||
struct scsi_vpd_supported_page_list *vpd_list = NULL;
|
||||
u8 *TLR_bits, TLR_on;
|
||||
u8 *TLR_bits, TLR_on, *scsi_cdb;
|
||||
int dir = 0, i;
|
||||
u16 alloc_len;
|
||||
struct mprsas_target *target;
|
||||
@ -2266,6 +2658,20 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Point to the SCSI CDB, which is dependent on the CAM_CDB_POINTER
|
||||
* flag, and use it in a few places in the rest of this function for
|
||||
* convenience. Use the macro if available.
|
||||
*/
|
||||
#if __FreeBSD_version >= 1100103
|
||||
scsi_cdb = scsiio_cdb_ptr(csio);
|
||||
#else
|
||||
if (csio->ccb_h.flags & CAM_CDB_POINTER)
|
||||
scsi_cdb = csio->cdb_io.cdb_ptr;
|
||||
else
|
||||
scsi_cdb = csio->cdb_io.cdb_bytes;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If this is a Start Stop Unit command and it was issued by the driver
|
||||
* during shutdown, decrement the refcount to account for all of the
|
||||
@ -2273,7 +2679,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
* shutdown completes, meaning SSU_refcount will be 0 after SSU_started
|
||||
* is TRUE.
|
||||
*/
|
||||
if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) {
|
||||
if (sc->SSU_started && (scsi_cdb[0] == START_STOP_UNIT)) {
|
||||
mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n");
|
||||
sc->SSU_refcount--;
|
||||
}
|
||||
@ -2314,6 +2720,14 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
return;
|
||||
}
|
||||
|
||||
target = &sassc->targets[target_id];
|
||||
if (scsi_cdb[0] == UNMAP &&
|
||||
target->is_nvme &&
|
||||
(csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
|
||||
rep->SCSIStatus = mprsas_complete_nvme_unmap(sc, cm);
|
||||
csio->scsi_status = rep->SCSIStatus;
|
||||
}
|
||||
|
||||
mprsas_log_command(cm, MPR_XINFO,
|
||||
"ioc %x scsi %x state %x xfer %u\n",
|
||||
le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
|
||||
@ -2325,7 +2739,6 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
/* FALLTHROUGH */
|
||||
case MPI2_IOCSTATUS_SUCCESS:
|
||||
case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
|
||||
|
||||
if ((le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) ==
|
||||
MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR)
|
||||
mprsas_log_command(cm, MPR_XINFO, "recovered error\n");
|
||||
@ -2403,9 +2816,9 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
* controller, turn the TLR_bits value ON if page 0x90 is
|
||||
* supported.
|
||||
*/
|
||||
if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) &&
|
||||
(csio->cdb_io.cdb_bytes[1] & SI_EVPD) &&
|
||||
(csio->cdb_io.cdb_bytes[2] == SVPD_SUPPORTED_PAGE_LIST) &&
|
||||
if ((scsi_cdb[0] == INQUIRY) &&
|
||||
(scsi_cdb[1] & SI_EVPD) &&
|
||||
(scsi_cdb[2] == SVPD_SUPPORTED_PAGE_LIST) &&
|
||||
((csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) &&
|
||||
(csio->data_ptr != NULL) &&
|
||||
((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) &&
|
||||
@ -2417,8 +2830,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
TLR_bits = &sc->mapping_table[target_id].TLR_bits;
|
||||
*TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
|
||||
TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON;
|
||||
alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) +
|
||||
csio->cdb_io.cdb_bytes[4];
|
||||
alloc_len = ((u16)scsi_cdb[3] << 8) + scsi_cdb[4];
|
||||
alloc_len -= csio->resid;
|
||||
for (i = 0; i < MIN(vpd_list->length, alloc_len); i++) {
|
||||
if (vpd_list->list[i] == 0x90) {
|
||||
@ -2433,7 +2845,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
* a SCSI StartStopUnit command will be sent to it when the
|
||||
* driver is being shutdown.
|
||||
*/
|
||||
if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) &&
|
||||
if ((scsi_cdb[0] == INQUIRY) &&
|
||||
(csio->data_ptr != NULL) &&
|
||||
((csio->data_ptr[0] & 0x1f) == T_DIRECT) &&
|
||||
(sc->mapping_table[target_id].device_info &
|
||||
@ -2524,7 +2936,14 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
rep->SCSIStatus, rep->SCSIState,
|
||||
le32toh(rep->TransferCount));
|
||||
csio->resid = cm->cm_length;
|
||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
|
||||
|
||||
if (scsi_cdb[0] == UNMAP &&
|
||||
target->is_nvme &&
|
||||
(csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR)
|
||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
|
||||
else
|
||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,8 @@ struct mprsas_target {
|
||||
uint8_t scsi_req_desc_type;
|
||||
uint8_t stop_at_shutdown;
|
||||
uint8_t supports_SSU;
|
||||
uint8_t is_nvme;
|
||||
uint32_t MDTS;
|
||||
};
|
||||
|
||||
struct mprsas_softc {
|
||||
|
@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mpr/mpi/mpi2.h>
|
||||
#include <dev/mpr/mpi/mpi2_ioc.h>
|
||||
#include <dev/mpr/mpi/mpi2_sas.h>
|
||||
#include <dev/mpr/mpi/mpi2_pci.h>
|
||||
#include <dev/mpr/mpi/mpi2_cnfg.h>
|
||||
#include <dev/mpr/mpi/mpi2_init.h>
|
||||
#include <dev/mpr/mpi/mpi2_raid.h>
|
||||
@ -116,6 +117,8 @@ static void mprsas_fw_work(struct mpr_softc *sc,
|
||||
static void mprsas_fw_event_free(struct mpr_softc *,
|
||||
struct mpr_fw_event_work *);
|
||||
static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate);
|
||||
static int mprsas_add_pcie_device(struct mpr_softc *sc, u16 handle,
|
||||
u8 linkrate);
|
||||
static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
|
||||
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
|
||||
u32 devinfo);
|
||||
@ -156,6 +159,7 @@ mprsas_evt_handler(struct mpr_softc *sc, uintptr_t data,
|
||||
bcopy(event->EventData, fw_event->event_data, sz);
|
||||
fw_event->event = event->Event;
|
||||
if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
|
||||
event->Event == MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ||
|
||||
event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE ||
|
||||
event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
|
||||
sc->track_mapping_events)
|
||||
@ -167,13 +171,13 @@ mprsas_evt_handler(struct mpr_softc *sc, uintptr_t data,
|
||||
* events are processed.
|
||||
*/
|
||||
if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
|
||||
event->Event == MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ||
|
||||
event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
|
||||
sc->wait_for_port_enable)
|
||||
mprsas_startup_increment(sc->sassc);
|
||||
|
||||
TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link);
|
||||
taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -205,7 +209,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
|
||||
{
|
||||
MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data;
|
||||
MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy;
|
||||
int i;
|
||||
uint8_t i;
|
||||
|
||||
data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
|
||||
fw_event->event_data;
|
||||
@ -674,6 +678,60 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
|
||||
{
|
||||
MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST *data;
|
||||
MPI26_EVENT_PCIE_TOPO_PORT_ENTRY *port_entry;
|
||||
uint8_t i, link_rate;
|
||||
uint16_t handle;
|
||||
|
||||
data = (MPI26_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST *)
|
||||
fw_event->event_data;
|
||||
|
||||
mpr_mapping_pcie_topology_change_event(sc,
|
||||
fw_event->event_data);
|
||||
|
||||
for (i = 0; i < data->NumEntries; i++) {
|
||||
port_entry = &data->PortEntry[i];
|
||||
handle = le16toh(port_entry->AttachedDevHandle);
|
||||
link_rate = port_entry->CurrentPortInfo &
|
||||
MPI26_EVENT_PCIE_TOPO_PI_RATE_MASK;
|
||||
switch (port_entry->PortStatus) {
|
||||
case MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED:
|
||||
if (link_rate <
|
||||
MPI26_EVENT_PCIE_TOPO_PI_RATE_2_5) {
|
||||
mpr_dprint(sc, MPR_ERROR, "%s: Cannot "
|
||||
"add PCIe device with handle 0x%x "
|
||||
"with unknown link rate.\n",
|
||||
__func__, handle);
|
||||
break;
|
||||
}
|
||||
if (mprsas_add_pcie_device(sc, handle,
|
||||
link_rate)) {
|
||||
mpr_dprint(sc, MPR_ERROR, "%s: failed "
|
||||
"to add PCIe device with handle "
|
||||
"0x%x\n", __func__, handle);
|
||||
mprsas_prepare_remove(sassc, handle);
|
||||
}
|
||||
break;
|
||||
case MPI26_EVENT_PCIE_TOPO_PS_NOT_RESPONDING:
|
||||
mprsas_prepare_remove(sassc, handle);
|
||||
break;
|
||||
case MPI26_EVENT_PCIE_TOPO_PS_PORT_CHANGED:
|
||||
case MPI26_EVENT_PCIE_TOPO_PS_NO_CHANGE:
|
||||
case MPI26_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* refcount was incremented for this event in
|
||||
* mprsas_evt_handler. Decrement it here because the event has
|
||||
* been processed.
|
||||
*/
|
||||
mprsas_startup_decrement(sassc);
|
||||
break;
|
||||
}
|
||||
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
|
||||
case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
|
||||
default:
|
||||
@ -703,7 +761,8 @@ mprsas_firmware_event_work(void *arg, int pending)
|
||||
}
|
||||
|
||||
static int
|
||||
mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate)
|
||||
{
|
||||
char devstring[80];
|
||||
struct mprsas_softc *sassc;
|
||||
struct mprsas_target *targ;
|
||||
@ -779,8 +838,8 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
if (sc->use_phynum != -1)
|
||||
id = mpr_mapping_get_sas_id(sc, sas_address, handle);
|
||||
if (id == MPR_MAP_BAD_ID) {
|
||||
if ((sc->use_phynum == 0)
|
||||
|| ((id = config_page.PhyNum) > sassc->maxtargets)) {
|
||||
if ((sc->use_phynum == 0) ||
|
||||
((id = config_page.PhyNum) > sassc->maxtargets)) {
|
||||
mpr_dprint(sc, MPR_INFO, "failure at %s:%d/%s()! "
|
||||
"Could not get ID for device with handle 0x%04x\n",
|
||||
__FILE__, __LINE__, __func__, handle);
|
||||
@ -827,8 +886,10 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
if (is_SATA_SSD) {
|
||||
targ->flags = MPR_TARGET_IS_SATA_SSD;
|
||||
}
|
||||
if (le16toh(config_page.Flags) &
|
||||
MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) {
|
||||
if ((le16toh(config_page.Flags) &
|
||||
MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) &&
|
||||
(le16toh(config_page.Flags) &
|
||||
MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE)) {
|
||||
targ->scsi_req_desc_type =
|
||||
MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
|
||||
}
|
||||
@ -908,7 +969,7 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
mprsas_startup_decrement(sassc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
|
||||
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD)
|
||||
@ -1139,6 +1200,141 @@ mprsas_ata_id_timeout(void *data)
|
||||
wakeup(cm);
|
||||
}
|
||||
|
||||
static int
|
||||
mprsas_add_pcie_device(struct mpr_softc *sc, u16 handle, u8 linkrate)
|
||||
{
|
||||
char devstring[80];
|
||||
struct mprsas_softc *sassc;
|
||||
struct mprsas_target *targ;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
Mpi26PCIeDevicePage0_t config_page;
|
||||
Mpi26PCIeDevicePage2_t config_page2;
|
||||
uint64_t pcie_wwid, parent_wwid = 0;
|
||||
u32 device_info, parent_devinfo = 0;
|
||||
unsigned int id;
|
||||
int error = 0;
|
||||
struct mprsas_lun *lun;
|
||||
|
||||
sassc = sc->sassc;
|
||||
mprsas_startup_increment(sassc);
|
||||
if ((mpr_config_get_pcie_device_pg0(sc, &mpi_reply, &config_page,
|
||||
MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, handle))) {
|
||||
printf("%s: error reading PCIe device page0\n", __func__);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
device_info = le32toh(config_page.DeviceInfo);
|
||||
|
||||
if (((device_info & MPI26_PCIE_DEVINFO_PCI_SWITCH) == 0)
|
||||
&& (le16toh(config_page.ParentDevHandle) != 0)) {
|
||||
Mpi2ConfigReply_t tmp_mpi_reply;
|
||||
Mpi26PCIeDevicePage0_t parent_config_page;
|
||||
|
||||
if ((mpr_config_get_pcie_device_pg0(sc, &tmp_mpi_reply,
|
||||
&parent_config_page, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE,
|
||||
le16toh(config_page.ParentDevHandle)))) {
|
||||
printf("%s: error reading PCIe device %#x page0\n",
|
||||
__func__, le16toh(config_page.ParentDevHandle));
|
||||
} else {
|
||||
parent_wwid = parent_config_page.WWID.High;
|
||||
parent_wwid = (parent_wwid << 32) |
|
||||
parent_config_page.WWID.Low;
|
||||
parent_devinfo = le32toh(parent_config_page.DeviceInfo);
|
||||
}
|
||||
}
|
||||
/* TODO Check proper endianness */
|
||||
pcie_wwid = config_page.WWID.High;
|
||||
pcie_wwid = (pcie_wwid << 32) | config_page.WWID.Low;
|
||||
mpr_dprint(sc, MPR_INFO, "PCIe WWID from PCIe device page0 = %jx\n",
|
||||
pcie_wwid);
|
||||
|
||||
if ((mpr_config_get_pcie_device_pg2(sc, &mpi_reply, &config_page2,
|
||||
MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, handle))) {
|
||||
printf("%s: error reading PCIe device page2\n", __func__);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
id = mpr_mapping_get_sas_id(sc, pcie_wwid, handle);
|
||||
if (id == MPR_MAP_BAD_ID) {
|
||||
printf("failure at %s:%d/%s()! Could not get ID for device "
|
||||
"with handle 0x%04x\n", __FILE__, __LINE__, __func__,
|
||||
handle);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mprsas_check_id(sassc, id) != 0) {
|
||||
device_printf(sc->mpr_dev, "Excluding target id %d\n", id);
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mpr_dprint(sc, MPR_MAPPING, "WWID from PCIe device page0 = %jx\n",
|
||||
pcie_wwid);
|
||||
targ = &sassc->targets[id];
|
||||
targ->devinfo = device_info;
|
||||
targ->encl_handle = le16toh(config_page.EnclosureHandle);
|
||||
targ->encl_slot = le16toh(config_page.Slot);
|
||||
targ->encl_level = config_page.EnclosureLevel;
|
||||
targ->connector_name[0] = ((char *)&config_page.ConnectorName)[0];
|
||||
targ->connector_name[1] = ((char *)&config_page.ConnectorName)[1];
|
||||
targ->connector_name[2] = ((char *)&config_page.ConnectorName)[2];
|
||||
targ->connector_name[3] = ((char *)&config_page.ConnectorName)[3];
|
||||
targ->is_nvme = device_info & MPI26_PCIE_DEVINFO_NVME;
|
||||
targ->MDTS = config_page2.MaximumDataTransferSize;
|
||||
/*
|
||||
* Assume always TRUE for encl_level_valid because there is no valid
|
||||
* flag for PCIe.
|
||||
*/
|
||||
targ->encl_level_valid = TRUE;
|
||||
targ->handle = handle;
|
||||
targ->parent_handle = le16toh(config_page.ParentDevHandle);
|
||||
targ->sasaddr = mpr_to_u64(&config_page.WWID);
|
||||
targ->parent_sasaddr = le64toh(parent_wwid);
|
||||
targ->parent_devinfo = parent_devinfo;
|
||||
targ->tid = id;
|
||||
targ->linkrate = linkrate;
|
||||
targ->flags = 0;
|
||||
if ((le16toh(config_page.Flags) &
|
||||
MPI26_PCIEDEV0_FLAGS_ENABLED_FAST_PATH) &&
|
||||
(le16toh(config_page.Flags) &
|
||||
MPI26_PCIEDEV0_FLAGS_FAST_PATH_CAPABLE)) {
|
||||
targ->scsi_req_desc_type =
|
||||
MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
|
||||
}
|
||||
TAILQ_INIT(&targ->commands);
|
||||
TAILQ_INIT(&targ->timedout_commands);
|
||||
while (!SLIST_EMPTY(&targ->luns)) {
|
||||
lun = SLIST_FIRST(&targ->luns);
|
||||
SLIST_REMOVE_HEAD(&targ->luns, lun_link);
|
||||
free(lun, M_MPR);
|
||||
}
|
||||
SLIST_INIT(&targ->luns);
|
||||
|
||||
mpr_describe_devinfo(targ->devinfo, devstring, 80);
|
||||
mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found PCIe device <%s> <%s> "
|
||||
"handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring,
|
||||
mpr_describe_table(mpr_pcie_linkrate_names, targ->linkrate),
|
||||
targ->handle, targ->encl_handle, targ->encl_slot);
|
||||
if (targ->encl_level_valid) {
|
||||
mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d "
|
||||
"and connector name (%4s)\n", targ->encl_level,
|
||||
targ->connector_name);
|
||||
}
|
||||
#if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \
|
||||
(__FreeBSD_version < 902502)
|
||||
if ((sassc->flags & MPRSAS_IN_STARTUP) == 0)
|
||||
#endif
|
||||
mprsas_rescan_target(sc, targ);
|
||||
mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid);
|
||||
|
||||
out:
|
||||
mprsas_startup_decrement(sassc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
mprsas_volume_add(struct mpr_softc *sc, u16 handle)
|
||||
{
|
||||
@ -1235,8 +1431,8 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
|
||||
if (target->stop_at_shutdown) {
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb == NULL) {
|
||||
mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB to stop "
|
||||
"unit.\n");
|
||||
mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB "
|
||||
"to stop unit.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mpr/mpi/mpi2_cnfg.h>
|
||||
#include <dev/mpr/mpi/mpi2_init.h>
|
||||
#include <dev/mpr/mpi/mpi2_tool.h>
|
||||
#include <dev/mpr/mpi/mpi2_pci.h>
|
||||
#include <dev/mpr/mpr_ioctl.h>
|
||||
#include <dev/mpr/mprvar.h>
|
||||
#include <dev/mpr/mpr_table.h>
|
||||
@ -74,6 +75,7 @@ mpr_describe_table(struct mpr_table_lookup *table, u_int code)
|
||||
return(table[i+1].string);
|
||||
}
|
||||
|
||||
//SLM-Add new PCIe info to all of these tables
|
||||
struct mpr_table_lookup mpr_event_names[] = {
|
||||
{"LogData", 0x01},
|
||||
{"StateChange", 0x02},
|
||||
@ -100,6 +102,10 @@ struct mpr_table_lookup mpr_event_names[] = {
|
||||
{"TempThreshold", 0x27},
|
||||
{"HostMessage", 0x28},
|
||||
{"PowerPerformanceChange", 0x29},
|
||||
{"PCIeDeviceStatusChange", 0x30},
|
||||
{"PCIeEnumeration", 0x31},
|
||||
{"PCIeTopologyChangeList", 0x32},
|
||||
{"PCIeLinkCounter", 0x33},
|
||||
{"CableEvent", 0x34},
|
||||
{NULL, 0},
|
||||
{"Unknown Event", 0}
|
||||
@ -192,6 +198,16 @@ struct mpr_table_lookup mpr_sasdev_reason[] = {
|
||||
{"Unknown", 0x00}
|
||||
};
|
||||
|
||||
struct mpr_table_lookup mpr_pcie_linkrate_names[] = {
|
||||
{"Port disabled", 0x01},
|
||||
{"2.5GT/sec", 0x02},
|
||||
{"5.0GT/sec", 0x03},
|
||||
{"8.0GT/sec", 0x04},
|
||||
{"16.0GT/sec", 0x05},
|
||||
{NULL, 0},
|
||||
{"LinkRate Unknown", 0x00}
|
||||
};
|
||||
|
||||
void
|
||||
mpr_describe_devinfo(uint32_t devinfo, char *string, int len)
|
||||
{
|
||||
@ -321,6 +337,7 @@ _mpr_print_evt_sas(struct mpr_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event)
|
||||
"\40MaxEnclosures");
|
||||
break;
|
||||
}
|
||||
//SLM-add for PCIE EVENT too
|
||||
case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
|
||||
{
|
||||
MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data;
|
||||
|
@ -40,6 +40,7 @@ void mpr_describe_devinfo(uint32_t devinfo, char *string, int len);
|
||||
extern struct mpr_table_lookup mpr_event_names[];
|
||||
extern struct mpr_table_lookup mpr_phystatus_names[];
|
||||
extern struct mpr_table_lookup mpr_linkrate_names[];
|
||||
extern struct mpr_table_lookup mpr_pcie_linkrate_names[];
|
||||
|
||||
void _mpr_print_iocfacts(struct mpr_softc *, MPI2_IOC_FACTS_REPLY *);
|
||||
void _mpr_print_portfacts(struct mpr_softc *, MPI2_PORT_FACTS_REPLY *);
|
||||
|
@ -99,6 +99,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mpr/mpi/mpi2_cnfg.h>
|
||||
#include <dev/mpr/mpi/mpi2_init.h>
|
||||
#include <dev/mpr/mpi/mpi2_tool.h>
|
||||
#include <dev/mpr/mpi/mpi2_pci.h>
|
||||
#include <dev/mpr/mpr_ioctl.h>
|
||||
#include <dev/mpr/mprvar.h>
|
||||
#include <dev/mpr/mpr_table.h>
|
||||
@ -747,6 +748,8 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
|
||||
{
|
||||
MPI2_REQUEST_HEADER *hdr, tmphdr;
|
||||
MPI2_DEFAULT_REPLY *rpl;
|
||||
Mpi26NVMeEncapsulatedErrorReply_t *nvme_error_reply = NULL;
|
||||
Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL;
|
||||
struct mpr_command *cm = NULL;
|
||||
int i, err = 0, dir = 0, sz;
|
||||
uint8_t tool, function = 0;
|
||||
@ -923,8 +926,8 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
|
||||
cm->cm_data, data->DataSize);
|
||||
}
|
||||
if (err != 0)
|
||||
mpr_dprint(sc, MPR_FAULT, "%s: failed to copy "
|
||||
"IOCTL data from user space\n", __func__);
|
||||
mpr_dprint(sc, MPR_FAULT, "%s: failed to copy IOCTL "
|
||||
"data from user space\n", __func__);
|
||||
}
|
||||
/*
|
||||
* Set this flag only if processing a command that does not need an
|
||||
@ -946,6 +949,35 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
|
||||
}
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
|
||||
if (function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
|
||||
nvme_encap_request =
|
||||
(Mpi26NVMeEncapsulatedRequest_t *)cm->cm_req;
|
||||
cm->cm_desc.Default.RequestFlags =
|
||||
MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
|
||||
|
||||
/*
|
||||
* Get the Physical Address of the sense buffer.
|
||||
* Save the user's Error Response buffer address and use that
|
||||
* field to hold the sense buffer address.
|
||||
* Clear the internal sense buffer, which will potentially hold
|
||||
* the Completion Queue Entry on return, or 0 if no Entry.
|
||||
* Build the PRPs and set direction bits.
|
||||
* Send the request.
|
||||
*/
|
||||
cm->nvme_error_response =
|
||||
(uint64_t *)(uintptr_t)(((uint64_t)nvme_encap_request->
|
||||
ErrorResponseBaseAddress.High << 32) |
|
||||
(uint64_t)nvme_encap_request->
|
||||
ErrorResponseBaseAddress.Low);
|
||||
nvme_encap_request->ErrorResponseBaseAddress.High =
|
||||
htole32((uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32));
|
||||
nvme_encap_request->ErrorResponseBaseAddress.Low =
|
||||
htole32(cm->cm_sense_busaddr);
|
||||
memset(cm->cm_sense, 0, NVME_ERROR_RESPONSE_SIZE);
|
||||
mpr_build_nvme_prp(sc, cm, nvme_encap_request, cm->cm_data,
|
||||
data->DataSize, data->DataOutSize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up Sense buffer and SGL offset for IO passthru. SCSI IO request
|
||||
* uses SCSI IO or Fast Path SCSI IO descriptor.
|
||||
@ -994,15 +1026,19 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
|
||||
MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO) {
|
||||
cm->cm_desc.FastPathSCSIIO.RequestFlags =
|
||||
MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
|
||||
cm->cm_desc.FastPathSCSIIO.DevHandle =
|
||||
scsi_io_req->DevHandle;
|
||||
if (!sc->atomic_desc_capable) {
|
||||
cm->cm_desc.FastPathSCSIIO.DevHandle =
|
||||
scsi_io_req->DevHandle;
|
||||
}
|
||||
scsi_io_req->IoFlags |=
|
||||
MPI25_SCSIIO_IOFLAGS_FAST_PATH;
|
||||
} else {
|
||||
cm->cm_desc.SCSIIO.RequestFlags =
|
||||
MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
|
||||
cm->cm_desc.SCSIIO.DevHandle =
|
||||
scsi_io_req->DevHandle;
|
||||
if (!sc->atomic_desc_capable) {
|
||||
cm->cm_desc.SCSIIO.DevHandle =
|
||||
scsi_io_req->DevHandle;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1079,6 +1115,38 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
|
||||
mpr_lock(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy out the NVMe Error Reponse to user. The Error Response
|
||||
* buffer is given by the user, but a sense buffer is used to
|
||||
* get that data from the IOC. The user's
|
||||
* ErrorResponseBaseAddress is saved in the
|
||||
* 'nvme_error_response' field before the command because that
|
||||
* field is set to a sense buffer. When the command is
|
||||
* complete, the Error Response data from the IOC is copied to
|
||||
* that user address after it is checked for validity.
|
||||
* Also note that 'sense' buffers are not defined for
|
||||
* NVMe commands. Sense terminalogy is only used here so that
|
||||
* the same IOCTL structure and sense buffers can be used for
|
||||
* NVMe.
|
||||
*/
|
||||
if (function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
|
||||
if (cm->nvme_error_response == NULL) {
|
||||
mpr_dprint(sc, MPR_INFO, "NVMe Error Response "
|
||||
"buffer is NULL. Response data will not be "
|
||||
"returned.\n");
|
||||
mpr_unlock(sc);
|
||||
goto RetFreeUnlocked;
|
||||
}
|
||||
|
||||
nvme_error_reply =
|
||||
(Mpi26NVMeEncapsulatedErrorReply_t *)cm->cm_reply;
|
||||
sz = MIN(le32toh(nvme_error_reply->ErrorResponseCount),
|
||||
NVME_ERROR_RESPONSE_SIZE);
|
||||
mpr_unlock(sc);
|
||||
copyout(cm->cm_sense, cm->nvme_error_response, sz);
|
||||
mpr_lock(sc);
|
||||
}
|
||||
}
|
||||
mpr_unlock(sc);
|
||||
|
||||
@ -2068,7 +2136,7 @@ mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data)
|
||||
return (EINVAL);
|
||||
|
||||
if (target > sc->max_devices) {
|
||||
mpr_dprint(sc, MPR_FAULT, "Target ID is out of range "
|
||||
mpr_dprint(sc, MPR_XINFO, "Target ID is out of range "
|
||||
"for Bus/Target to DevHandle mapping.");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
#ifndef _MPRVAR_H
|
||||
#define _MPRVAR_H
|
||||
|
||||
#define MPR_DRIVER_VERSION "15.01.00.00-fbsd"
|
||||
#define MPR_DRIVER_VERSION "15.02.00.00-fbsd"
|
||||
|
||||
#define MPR_DB_MAX_WAIT 2500
|
||||
|
||||
@ -50,6 +50,17 @@
|
||||
#define MPR_DEFAULT_CHAIN_SEG_SIZE 8
|
||||
#define MPR_MAX_CHAIN_ELEMENT_SIZE 16
|
||||
|
||||
/*
|
||||
* PCIe NVMe Specific defines
|
||||
*/
|
||||
//SLM-for now just use the same value as a SAS disk
|
||||
#define NVME_QDEPTH MPR_REQ_FRAMES
|
||||
#define PRP_ENTRY_SIZE 8
|
||||
#define NVME_CMD_PRP1_OFFSET 24 /* PRP1 offset in NVMe cmd */
|
||||
#define NVME_CMD_PRP2_OFFSET 32 /* PRP2 offset in NVMe cmd */
|
||||
#define NVME_ERROR_RESPONSE_SIZE 16 /* Max NVME Error Response */
|
||||
#define HOST_PAGE_SIZE_4K 12
|
||||
|
||||
#define MPR_FUNCTRACE(sc) \
|
||||
mpr_dprint((sc), MPR_TRACE, "%s\n", __func__)
|
||||
|
||||
@ -184,6 +195,12 @@ struct mpr_chain {
|
||||
uint64_t chain_busaddr;
|
||||
};
|
||||
|
||||
struct mpr_prp_page {
|
||||
TAILQ_ENTRY(mpr_prp_page) prp_page_link;
|
||||
uint64_t *prp_page;
|
||||
uint64_t prp_page_busaddr;
|
||||
};
|
||||
|
||||
/*
|
||||
* This needs to be at least 2 to support SMP passthrough.
|
||||
*/
|
||||
@ -229,9 +246,11 @@ struct mpr_command {
|
||||
#define MPR_CM_STATE_TIMEDOUT 2
|
||||
bus_dmamap_t cm_dmamap;
|
||||
struct scsi_sense_data *cm_sense;
|
||||
uint64_t *nvme_error_response;
|
||||
TAILQ_HEAD(, mpr_chain) cm_chain_list;
|
||||
TAILQ_HEAD(, mpr_prp_page) cm_prp_page_list;
|
||||
uint32_t cm_req_busaddr;
|
||||
uint32_t cm_sense_busaddr;
|
||||
bus_addr_t cm_sense_busaddr;
|
||||
struct callout cm_callout;
|
||||
};
|
||||
|
||||
@ -257,27 +276,35 @@ struct mpr_softc {
|
||||
#define MPR_FLAGS_SHUTDOWN (1 << 3)
|
||||
#define MPR_FLAGS_DIAGRESET (1 << 4)
|
||||
#define MPR_FLAGS_ATTACH_DONE (1 << 5)
|
||||
#define MPR_FLAGS_GEN35_IOC (1 << 6)
|
||||
u_int mpr_debug;
|
||||
u_int disable_msix;
|
||||
u_int disable_msi;
|
||||
u_int atomic_desc_capable;
|
||||
int tm_cmds_active;
|
||||
int io_cmds_active;
|
||||
int io_cmds_highwater;
|
||||
int chain_free;
|
||||
int max_chains;
|
||||
int max_io_pages;
|
||||
u_int maxio;
|
||||
int chain_free_lowwater;
|
||||
uint32_t chain_frame_size;
|
||||
uint16_t chain_seg_size;
|
||||
int prp_buffer_size;
|
||||
int prp_pages_free;
|
||||
int prp_pages_free_lowwater;
|
||||
u_int enable_ssu;
|
||||
int spinup_wait_time;
|
||||
int use_phynum;
|
||||
uint64_t chain_alloc_fail;
|
||||
uint64_t prp_page_alloc_fail;
|
||||
struct sysctl_ctx_list sysctl_ctx;
|
||||
struct sysctl_oid *sysctl_tree;
|
||||
char fw_version[16];
|
||||
struct mpr_command *commands;
|
||||
struct mpr_chain *chains;
|
||||
struct mpr_prp_page *prps;
|
||||
struct callout periodic;
|
||||
|
||||
struct mprsas_softc *sassc;
|
||||
@ -285,6 +312,7 @@ struct mpr_softc {
|
||||
TAILQ_HEAD(, mpr_command) req_list;
|
||||
TAILQ_HEAD(, mpr_command) high_priority_req_list;
|
||||
TAILQ_HEAD(, mpr_chain) chain_list;
|
||||
TAILQ_HEAD(, mpr_prp_page) prp_page_list;
|
||||
TAILQ_HEAD(, mpr_command) tm_list;
|
||||
int replypostindex;
|
||||
int replyfreeindex;
|
||||
@ -333,6 +361,11 @@ struct mpr_softc {
|
||||
bus_dma_tag_t chain_dmat;
|
||||
bus_dmamap_t chain_map;
|
||||
|
||||
uint8_t *prp_pages;
|
||||
bus_addr_t prp_page_busaddr;
|
||||
bus_dma_tag_t prp_page_dmat;
|
||||
bus_dmamap_t prp_page_map;
|
||||
|
||||
MPI2_REPLY_DESCRIPTORS_UNION *post_queue;
|
||||
bus_addr_t post_busaddr;
|
||||
uint32_t *free_queue;
|
||||
@ -471,10 +504,33 @@ mpr_free_chain(struct mpr_softc *sc, struct mpr_chain *chain)
|
||||
TAILQ_INSERT_TAIL(&sc->chain_list, chain, chain_link);
|
||||
}
|
||||
|
||||
static __inline struct mpr_prp_page *
|
||||
mpr_alloc_prp_page(struct mpr_softc *sc)
|
||||
{
|
||||
struct mpr_prp_page *prp_page;
|
||||
|
||||
if ((prp_page = TAILQ_FIRST(&sc->prp_page_list)) != NULL) {
|
||||
TAILQ_REMOVE(&sc->prp_page_list, prp_page, prp_page_link);
|
||||
sc->prp_pages_free--;
|
||||
if (sc->prp_pages_free < sc->prp_pages_free_lowwater)
|
||||
sc->prp_pages_free_lowwater = sc->prp_pages_free;
|
||||
} else
|
||||
sc->prp_page_alloc_fail++;
|
||||
return (prp_page);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
mpr_free_prp_page(struct mpr_softc *sc, struct mpr_prp_page *prp_page)
|
||||
{
|
||||
sc->prp_pages_free++;
|
||||
TAILQ_INSERT_TAIL(&sc->prp_page_list, prp_page, prp_page_link);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
mpr_free_command(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
{
|
||||
struct mpr_chain *chain, *chain_temp;
|
||||
struct mpr_prp_page *prp_page, *prp_page_temp;
|
||||
|
||||
if (cm->cm_reply != NULL)
|
||||
mpr_free_reply(sc, cm->cm_reply_data);
|
||||
@ -497,6 +553,11 @@ mpr_free_command(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link);
|
||||
mpr_free_chain(sc, chain);
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(prp_page, &cm->cm_prp_page_list, prp_page_link,
|
||||
prp_page_temp) {
|
||||
TAILQ_REMOVE(&cm->cm_prp_page_list, prp_page, prp_page_link);
|
||||
mpr_free_prp_page(sc, prp_page);
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&sc->req_list, cm, cm_link);
|
||||
}
|
||||
|
||||
@ -510,7 +571,8 @@ mpr_alloc_command(struct mpr_softc *sc)
|
||||
return (NULL);
|
||||
|
||||
TAILQ_REMOVE(&sc->req_list, cm, cm_link);
|
||||
KASSERT(cm->cm_state == MPR_CM_STATE_FREE, ("mpr: Allocating busy command\n"));
|
||||
KASSERT(cm->cm_state == MPR_CM_STATE_FREE, ("mpr: Allocating busy "
|
||||
"command\n"));
|
||||
cm->cm_state = MPR_CM_STATE_BUSY;
|
||||
return (cm);
|
||||
}
|
||||
@ -547,7 +609,8 @@ mpr_alloc_high_priority_command(struct mpr_softc *sc)
|
||||
return (NULL);
|
||||
|
||||
TAILQ_REMOVE(&sc->high_priority_req_list, cm, cm_link);
|
||||
KASSERT(cm->cm_state == MPR_CM_STATE_FREE, ("mpr: Allocating busy command\n"));
|
||||
KASSERT(cm->cm_state == MPR_CM_STATE_FREE, ("mpr: Allocating busy "
|
||||
"command\n"));
|
||||
cm->cm_state = MPR_CM_STATE_BUSY;
|
||||
return (cm);
|
||||
}
|
||||
@ -653,6 +716,9 @@ int mpr_register_events(struct mpr_softc *, uint8_t *, mpr_evt_callback_t *,
|
||||
int mpr_restart(struct mpr_softc *);
|
||||
int mpr_update_events(struct mpr_softc *, struct mpr_event_handle *, uint8_t *);
|
||||
int mpr_deregister_events(struct mpr_softc *, struct mpr_event_handle *);
|
||||
void mpr_build_nvme_prp(struct mpr_softc *sc, struct mpr_command *cm,
|
||||
Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request, void *data,
|
||||
uint32_t data_in_sz, uint32_t data_out_sz);
|
||||
int mpr_push_sge(struct mpr_command *, MPI2_SGE_SIMPLE64 *, size_t, int);
|
||||
int mpr_push_ieee_sge(struct mpr_command *, void *, int);
|
||||
int mpr_add_dmaseg(struct mpr_command *, vm_paddr_t, size_t, u_int, int);
|
||||
@ -682,6 +748,10 @@ int mpr_config_get_iounit_pg8(struct mpr_softc *sc,
|
||||
Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page);
|
||||
int mpr_config_get_sas_device_pg0(struct mpr_softc *, Mpi2ConfigReply_t *,
|
||||
Mpi2SasDevicePage0_t *, u32 , u16 );
|
||||
int mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
*mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle);
|
||||
int mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
|
||||
*mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle);
|
||||
int mpr_config_get_dpm_pg0(struct mpr_softc *, Mpi2ConfigReply_t *,
|
||||
Mpi2DriverMappingPage0_t *, u16 );
|
||||
int mpr_config_get_raid_volume_pg1(struct mpr_softc *sc,
|
||||
@ -702,6 +772,8 @@ void mpr_base_static_config_pages(struct mpr_softc *sc);
|
||||
int mpr_mapping_initialize(struct mpr_softc *);
|
||||
void mpr_mapping_topology_change_event(struct mpr_softc *,
|
||||
Mpi2EventDataSasTopologyChangeList_t *);
|
||||
void mpr_mapping_pcie_topology_change_event(struct mpr_softc *sc,
|
||||
Mpi26EventDataPCIeTopologyChangeList_t *event_data);
|
||||
int mpr_mapping_is_reinit_required(struct mpr_softc *);
|
||||
void mpr_mapping_free_memory(struct mpr_softc *sc);
|
||||
int mpr_config_set_dpm_pg0(struct mpr_softc *, Mpi2ConfigReply_t *,
|
||||
@ -769,5 +841,52 @@ SYSCTL_DECL(_hw_mpr);
|
||||
#define CAM_PRIORITY_NORMAL CAM_PRIORITY_NONE
|
||||
#endif
|
||||
|
||||
/* Definitions for SCSI unmap translation to NVMe DSM command */
|
||||
|
||||
/* UNMAP block descriptor structure */
|
||||
struct unmap_blk_desc {
|
||||
uint64_t slba;
|
||||
uint32_t nlb;
|
||||
uint32_t resv;
|
||||
};
|
||||
|
||||
/* UNMAP command's data */
|
||||
struct unmap_parm_list {
|
||||
uint16_t unmap_data_len;
|
||||
uint16_t unmap_blk_desc_data_len;
|
||||
uint32_t resv;
|
||||
struct unmap_blk_desc desc[0];
|
||||
};
|
||||
|
||||
/* SCSI ADDITIONAL SENSE Codes */
|
||||
#define FIXED_SENSE_DATA 0x70
|
||||
#define SCSI_ASC_NO_SENSE 0x00
|
||||
#define SCSI_ASC_PERIPHERAL_DEV_WRITE_FAULT 0x03
|
||||
#define SCSI_ASC_LUN_NOT_READY 0x04
|
||||
#define SCSI_ASC_WARNING 0x0B
|
||||
#define SCSI_ASC_LOG_BLOCK_GUARD_CHECK_FAILED 0x10
|
||||
#define SCSI_ASC_LOG_BLOCK_APPTAG_CHECK_FAILED 0x10
|
||||
#define SCSI_ASC_LOG_BLOCK_REFTAG_CHECK_FAILED 0x10
|
||||
#define SCSI_ASC_UNRECOVERED_READ_ERROR 0x11
|
||||
#define SCSI_ASC_MISCOMPARE_DURING_VERIFY 0x1D
|
||||
#define SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID 0x20
|
||||
#define SCSI_ASC_ILLEGAL_COMMAND 0x20
|
||||
#define SCSI_ASC_ILLEGAL_BLOCK 0x21
|
||||
#define SCSI_ASC_INVALID_CDB 0x24
|
||||
#define SCSI_ASC_INVALID_LUN 0x25
|
||||
#define SCSI_ASC_INVALID_PARAMETER 0x26
|
||||
#define SCSI_ASC_FORMAT_COMMAND_FAILED 0x31
|
||||
#define SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44
|
||||
|
||||
/* SCSI ADDITIONAL SENSE Code Qualifiers */
|
||||
#define SCSI_ASCQ_CAUSE_NOT_REPORTABLE 0x00
|
||||
#define SCSI_ASCQ_FORMAT_COMMAND_FAILED 0x01
|
||||
#define SCSI_ASCQ_LOG_BLOCK_GUARD_CHECK_FAILED 0x01
|
||||
#define SCSI_ASCQ_LOG_BLOCK_APPTAG_CHECK_FAILED 0x02
|
||||
#define SCSI_ASCQ_LOG_BLOCK_REFTAG_CHECK_FAILED 0x03
|
||||
#define SCSI_ASCQ_FORMAT_IN_PROGRESS 0x04
|
||||
#define SCSI_ASCQ_POWER_LOSS_EXPECTED 0x08
|
||||
#define SCSI_ASCQ_INVALID_LUN_ID 0x09
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user