aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Moore <eric.moore@lsi.com>2009-03-09 03:21:12 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-13 17:08:49 -0400
commit635374e7eb110e80d9918b8611198edd56a32975 (patch)
tree1c96f9dac921b0b26ee4e93ecd9c79a96fbc7ba6
parentdec3f95959bff957f5bcbf16c2a2823f7e33d1e7 (diff)
[SCSI] mpt2sas v00.100.11.15
* This is new scsi lld device driver from LSI supporting the SAS 2.0 standard. I have split patchs by filename. * Here is list of new 6gb host controllers: LSI SAS2004 LSI SAS2008 LSI SAS2108 LSI SAS2116 * Here are the changes in the 4th posting of this patch set: (1) fix compile errors when SCSI_MPT2SAS_LOGGING is not enabled (2) add mpt2sas to the SCSI Mid Layer Makefile (3) append mpt2sas_ to the naming of all non-static functions (4) fix oops for SMP_PASSTHRU (5) doorbell algorithm imported changes from windows driver * Here are the changes in the 3rd posting of this patch set: (1) add readl following writel from the function that disables interrupts (2) replace 0xFFFFFFFFFFFFFFFFULL with ~0ULL (3) when calling pci_enable_msix, only pass one msix entry (instead of 15). (4) remove the "current HW implementation uses..... " comment in the sources (5) merged bug fix for SIGIO/POLLIN notifcation; reported by the storlib team. * Here are the changes in the 2nd posting of this patch set: (1) use little endian types in the mpi headers (2) merged in bug fix's from inhouse drivers. Signed-off-by: Eric Moore <eric.moore@lsi.com> Tested-by: peter Bogdanovic <pbog@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/mpt2sas/Kconfig66
-rw-r--r--drivers/scsi/mpt2sas/Makefile7
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h1067
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h2151
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_init.h420
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_ioc.h1295
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_raid.h295
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_sas.h282
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_tool.h249
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_type.h61
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c3435
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h779
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_config.c1873
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c2516
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.h416
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_debug.h181
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c5687
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c1211
20 files changed, 21993 insertions, 0 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index e420ad0acebf..e2f44e6c0bcb 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -571,6 +571,7 @@ config SCSI_ARCMSR_AER
571 To enable this function, choose Y here. 571 To enable this function, choose Y here.
572 572
573source "drivers/scsi/megaraid/Kconfig.megaraid" 573source "drivers/scsi/megaraid/Kconfig.megaraid"
574source "drivers/scsi/mpt2sas/Kconfig"
574 575
575config SCSI_HPTIOP 576config SCSI_HPTIOP
576 tristate "HighPoint RocketRAID 3xxx/4xxx Controller support" 577 tristate "HighPoint RocketRAID 3xxx/4xxx Controller support"
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 05558b170419..cf7929634668 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
99obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o 99obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
100obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ 100obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
101obj-$(CONFIG_MEGARAID_SAS) += megaraid/ 101obj-$(CONFIG_MEGARAID_SAS) += megaraid/
102obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas/
102obj-$(CONFIG_SCSI_ACARD) += atp870u.o 103obj-$(CONFIG_SCSI_ACARD) += atp870u.o
103obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o 104obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o
104obj-$(CONFIG_SCSI_GDTH) += gdth.o 105obj-$(CONFIG_SCSI_GDTH) += gdth.o
diff --git a/drivers/scsi/mpt2sas/Kconfig b/drivers/scsi/mpt2sas/Kconfig
new file mode 100644
index 000000000000..4a86855c23b3
--- /dev/null
+++ b/drivers/scsi/mpt2sas/Kconfig
@@ -0,0 +1,66 @@
1#
2# Kernel configuration file for the MPT2SAS
3#
4# This code is based on drivers/scsi/mpt2sas/Kconfig
5# Copyright (C) 2007-2008 LSI Corporation
6# (mailto:DL-MPTFusionLinux@lsi.com)
7
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License
10# as published by the Free Software Foundation; either version 2
11# of the License, or (at your option) any later version.
12
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17
18# NO WARRANTY
19# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23# solely responsible for determining the appropriateness of using and
24# distributing the Program and assumes all risks associated with its
25# exercise of rights under this Agreement, including but not limited to
26# the risks and costs of program errors, damage to or loss of data,
27# programs or equipment, and unavailability or interruption of operations.
28
29# DISCLAIMER OF LIABILITY
30# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38# You should have received a copy of the GNU General Public License
39# along with this program; if not, write to the Free Software
40# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
41# USA.
42
43config SCSI_MPT2SAS
44 tristate "LSI MPT Fusion SAS 2.0 Device Driver"
45 depends on PCI && SCSI
46 select SCSI_SAS_ATTRS
47 ---help---
48 This driver supports PCI-Express SAS 6Gb/s Host Adapters.
49
50config SCSI_MPT2SAS_MAX_SGE
51 int "LSI MPT Fusion Max number of SG Entries (16 - 128)"
52 depends on PCI && SCSI && SCSI_MPT2SAS
53 default "128"
54 range 16 128
55 ---help---
56 This option allows you to specify the maximum number of scatter-
57 gather entries per I/O. The driver default is 128, which matches
58 SAFE_PHYS_SEGMENTS. However, it may decreased down to 16.
59 Decreasing this parameter will reduce memory requirements
60 on a per controller instance.
61
62config SCSI_MPT2SAS_LOGGING
63 bool "LSI MPT Fusion logging facility"
64 depends on PCI && SCSI && SCSI_MPT2SAS
65 ---help---
66 This turns on a logging facility.
diff --git a/drivers/scsi/mpt2sas/Makefile b/drivers/scsi/mpt2sas/Makefile
new file mode 100644
index 000000000000..728f0475711d
--- /dev/null
+++ b/drivers/scsi/mpt2sas/Makefile
@@ -0,0 +1,7 @@
1# mpt2sas makefile
2obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas.o
3mpt2sas-y += mpt2sas_base.o \
4 mpt2sas_config.o \
5 mpt2sas_scsih.o \
6 mpt2sas_transport.o \
7 mpt2sas_ctl.o
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
new file mode 100644
index 000000000000..7bb2ece8b2e4
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -0,0 +1,1067 @@
1/*
2 * Copyright (c) 2000-2009 LSI Corporation.
3 *
4 *
5 * Name: mpi2.h
6 * Title: MPI Message independent structures and definitions
7 * including System Interface Register Set and
8 * scatter/gather formats.
9 * Creation Date: June 21, 2006
10 *
11 * mpi2.h Version: 02.00.11
12 *
13 * Version History
14 * ---------------
15 *
16 * Date Version Description
17 * -------- -------- ------------------------------------------------------
18 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
19 * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT.
20 * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT.
21 * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT.
22 * Moved ReplyPostHostIndex register to offset 0x6C of the
23 * MPI2_SYSTEM_INTERFACE_REGS and modified the define for
24 * MPI2_REPLY_POST_HOST_INDEX_OFFSET.
25 * Added union of request descriptors.
26 * Added union of reply descriptors.
27 * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT.
28 * Added define for MPI2_VERSION_02_00.
29 * Fixed the size of the FunctionDependent5 field in the
30 * MPI2_DEFAULT_REPLY structure.
31 * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT.
32 * Removed the MPI-defined Fault Codes and extended the
33 * product specific codes up to 0xEFFF.
34 * Added a sixth key value for the WriteSequence register
35 * and changed the flush value to 0x0.
36 * Added message function codes for Diagnostic Buffer Post
37 * and Diagnsotic Release.
38 * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
39 * Moved MPI2_VERSION_UNION from mpi2_ioc.h.
40 * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT.
41 * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT.
42 * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT.
43 * Added #defines for marking a reply descriptor as unused.
44 * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT.
45 * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT.
46 * Moved LUN field defines from mpi2_init.h.
47 * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT.
48 * --------------------------------------------------------------------------
49 */
50
51#ifndef MPI2_H
52#define MPI2_H
53
54
55/*****************************************************************************
56*
57* MPI Version Definitions
58*
59*****************************************************************************/
60
61#define MPI2_VERSION_MAJOR (0x02)
62#define MPI2_VERSION_MINOR (0x00)
63#define MPI2_VERSION_MAJOR_MASK (0xFF00)
64#define MPI2_VERSION_MAJOR_SHIFT (8)
65#define MPI2_VERSION_MINOR_MASK (0x00FF)
66#define MPI2_VERSION_MINOR_SHIFT (0)
67#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
68 MPI2_VERSION_MINOR)
69
70#define MPI2_VERSION_02_00 (0x0200)
71
72/* versioning for this MPI header set */
73#define MPI2_HEADER_VERSION_UNIT (0x0B)
74#define MPI2_HEADER_VERSION_DEV (0x00)
75#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
76#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
77#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF)
78#define MPI2_HEADER_VERSION_DEV_SHIFT (0)
79#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV)
80
81
82/*****************************************************************************
83*
84* IOC State Definitions
85*
86*****************************************************************************/
87
88#define MPI2_IOC_STATE_RESET (0x00000000)
89#define MPI2_IOC_STATE_READY (0x10000000)
90#define MPI2_IOC_STATE_OPERATIONAL (0x20000000)
91#define MPI2_IOC_STATE_FAULT (0x40000000)
92
93#define MPI2_IOC_STATE_MASK (0xF0000000)
94#define MPI2_IOC_STATE_SHIFT (28)
95
96/* Fault state range for prodcut specific codes */
97#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000)
98#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF)
99
100
101/*****************************************************************************
102*
103* System Interface Register Definitions
104*
105*****************************************************************************/
106
107typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
108{
109 U32 Doorbell; /* 0x00 */
110 U32 WriteSequence; /* 0x04 */
111 U32 HostDiagnostic; /* 0x08 */
112 U32 Reserved1; /* 0x0C */
113 U32 DiagRWData; /* 0x10 */
114 U32 DiagRWAddressLow; /* 0x14 */
115 U32 DiagRWAddressHigh; /* 0x18 */
116 U32 Reserved2[5]; /* 0x1C */
117 U32 HostInterruptStatus; /* 0x30 */
118 U32 HostInterruptMask; /* 0x34 */
119 U32 DCRData; /* 0x38 */
120 U32 DCRAddress; /* 0x3C */
121 U32 Reserved3[2]; /* 0x40 */
122 U32 ReplyFreeHostIndex; /* 0x48 */
123 U32 Reserved4[8]; /* 0x4C */
124 U32 ReplyPostHostIndex; /* 0x6C */
125 U32 Reserved5; /* 0x70 */
126 U32 HCBSize; /* 0x74 */
127 U32 HCBAddressLow; /* 0x78 */
128 U32 HCBAddressHigh; /* 0x7C */
129 U32 Reserved6[16]; /* 0x80 */
130 U32 RequestDescriptorPostLow; /* 0xC0 */
131 U32 RequestDescriptorPostHigh; /* 0xC4 */
132 U32 Reserved7[14]; /* 0xC8 */
133} MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS,
134 Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t;
135
136/*
137 * Defines for working with the Doorbell register.
138 */
139#define MPI2_DOORBELL_OFFSET (0x00000000)
140
141/* IOC --> System values */
142#define MPI2_DOORBELL_USED (0x08000000)
143#define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000)
144#define MPI2_DOORBELL_WHO_INIT_SHIFT (24)
145#define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF)
146#define MPI2_DOORBELL_DATA_MASK (0x0000FFFF)
147
148/* System --> IOC values */
149#define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000)
150#define MPI2_DOORBELL_FUNCTION_SHIFT (24)
151#define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000)
152#define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16)
153
154
155/*
156 * Defines for the WriteSequence register
157 */
158#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004)
159#define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F)
160#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0)
161#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF)
162#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4)
163#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB)
164#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2)
165#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7)
166#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD)
167
168/*
169 * Defines for the HostDiagnostic register
170 */
171#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008)
172
173#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800)
174#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000)
175#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800)
176
177#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400)
178#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200)
179#define MPI2_DIAG_HCB_MODE (0x00000100)
180#define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080)
181#define MPI2_DIAG_FLASH_BAD_SIG (0x00000040)
182#define MPI2_DIAG_RESET_HISTORY (0x00000020)
183#define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010)
184#define MPI2_DIAG_RESET_ADAPTER (0x00000004)
185#define MPI2_DIAG_HOLD_IOC_RESET (0x00000002)
186
187/*
188 * Offsets for DiagRWData and address
189 */
190#define MPI2_DIAG_RW_DATA_OFFSET (0x00000010)
191#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014)
192#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018)
193
194/*
195 * Defines for the HostInterruptStatus register
196 */
197#define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030)
198#define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000)
199#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS
200#define MPI2_HIS_RESET_IRQ_STATUS (0x40000000)
201#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008)
202#define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001)
203#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS
204
205/*
206 * Defines for the HostInterruptMask register
207 */
208#define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034)
209#define MPI2_HIM_RESET_IRQ_MASK (0x40000000)
210#define MPI2_HIM_REPLY_INT_MASK (0x00000008)
211#define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK
212#define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001)
213#define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK
214
215/*
216 * Offsets for DCRData and address
217 */
218#define MPI2_DCR_DATA_OFFSET (0x00000038)
219#define MPI2_DCR_ADDRESS_OFFSET (0x0000003C)
220
221/*
222 * Offset for the Reply Free Queue
223 */
224#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048)
225
226/*
227 * Offset for the Reply Descriptor Post Queue
228 */
229#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C)
230
231/*
232 * Defines for the HCBSize and address
233 */
234#define MPI2_HCB_SIZE_OFFSET (0x00000074)
235#define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000)
236#define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001)
237
238#define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078)
239#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C)
240
241/*
242 * Offsets for the Request Queue
243 */
244#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0)
245#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4)
246
247
248/*****************************************************************************
249*
250* Message Descriptors
251*
252*****************************************************************************/
253
254/* Request Descriptors */
255
256/* Default Request Descriptor */
257typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
258{
259 U8 RequestFlags; /* 0x00 */
260 U8 VF_ID; /* 0x01 */
261 U16 SMID; /* 0x02 */
262 U16 LMID; /* 0x04 */
263 U16 DescriptorTypeDependent; /* 0x06 */
264} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
265 MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
266 Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t;
267
268/* defines for the RequestFlags field */
269#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E)
270#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
271#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02)
272#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
273#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08)
274
275#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
276
277
278/* High Priority Request Descriptor */
279typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
280{
281 U8 RequestFlags; /* 0x00 */
282 U8 VF_ID; /* 0x01 */
283 U16 SMID; /* 0x02 */
284 U16 LMID; /* 0x04 */
285 U16 Reserved1; /* 0x06 */
286} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
287 MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
288 Mpi2HighPriorityRequestDescriptor_t,
289 MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t;
290
291
292/* SCSI IO Request Descriptor */
293typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
294{
295 U8 RequestFlags; /* 0x00 */
296 U8 VF_ID; /* 0x01 */
297 U16 SMID; /* 0x02 */
298 U16 LMID; /* 0x04 */
299 U16 DevHandle; /* 0x06 */
300} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
301 MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
302 Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t;
303
304
305/* SCSI Target Request Descriptor */
306typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
307{
308 U8 RequestFlags; /* 0x00 */
309 U8 VF_ID; /* 0x01 */
310 U16 SMID; /* 0x02 */
311 U16 LMID; /* 0x04 */
312 U16 IoIndex; /* 0x06 */
313} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
314 MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
315 Mpi2SCSITargetRequestDescriptor_t,
316 MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t;
317
318/* union of Request Descriptors */
319typedef union _MPI2_REQUEST_DESCRIPTOR_UNION
320{
321 MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
322 MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority;
323 MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO;
324 MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
325 U64 Words;
326} MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
327 Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t;
328
329
330/* Reply Descriptors */
331
332/* Default Reply Descriptor */
333typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
334{
335 U8 ReplyFlags; /* 0x00 */
336 U8 VF_ID; /* 0x01 */
337 U16 DescriptorTypeDependent1; /* 0x02 */
338 U32 DescriptorTypeDependent2; /* 0x04 */
339} MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
340 Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t;
341
342/* defines for the ReplyFlags field */
343#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F)
344#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
345#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01)
346#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02)
347#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03)
348#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
349
350/* values for marking a reply descriptor as unused */
351#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF)
352#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF)
353
354/* Address Reply Descriptor */
355typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
356{
357 U8 ReplyFlags; /* 0x00 */
358 U8 VF_ID; /* 0x01 */
359 U16 SMID; /* 0x02 */
360 U32 ReplyFrameAddress; /* 0x04 */
361} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
362 Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t;
363
364#define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00)
365
366
367/* SCSI IO Success Reply Descriptor */
368typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
369{
370 U8 ReplyFlags; /* 0x00 */
371 U8 VF_ID; /* 0x01 */
372 U16 SMID; /* 0x02 */
373 U16 TaskTag; /* 0x04 */
374 U16 DevHandle; /* 0x06 */
375} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
376 MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
377 Mpi2SCSIIOSuccessReplyDescriptor_t,
378 MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t;
379
380
381/* TargetAssist Success Reply Descriptor */
382typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
383{
384 U8 ReplyFlags; /* 0x00 */
385 U8 VF_ID; /* 0x01 */
386 U16 SMID; /* 0x02 */
387 U8 SequenceNumber; /* 0x04 */
388 U8 Reserved1; /* 0x05 */
389 U16 IoIndex; /* 0x06 */
390} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
391 MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
392 Mpi2TargetAssistSuccessReplyDescriptor_t,
393 MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t;
394
395
396/* Target Command Buffer Reply Descriptor */
397typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
398{
399 U8 ReplyFlags; /* 0x00 */
400 U8 VF_ID; /* 0x01 */
401 U8 VP_ID; /* 0x02 */
402 U8 Flags; /* 0x03 */
403 U16 InitiatorDevHandle; /* 0x04 */
404 U16 IoIndex; /* 0x06 */
405} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
406 MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
407 Mpi2TargetCommandBufferReplyDescriptor_t,
408 MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t;
409
410/* defines for Flags field */
411#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F)
412
413
414/* union of Reply Descriptors */
415typedef union _MPI2_REPLY_DESCRIPTORS_UNION
416{
417 MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
418 MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply;
419 MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess;
420 MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
421 MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
422 U64 Words;
423} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
424 Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
425
426
427
428/*****************************************************************************
429*
430* Message Functions
431* 0x80 -> 0x8F reserved for private message use per product
432*
433*
434*****************************************************************************/
435
436#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */
437#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) /* SCSI Task Management */
438#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */
439#define MPI2_FUNCTION_IOC_FACTS (0x03) /* IOC Facts */
440#define MPI2_FUNCTION_CONFIG (0x04) /* Configuration */
441#define MPI2_FUNCTION_PORT_FACTS (0x05) /* Port Facts */
442#define MPI2_FUNCTION_PORT_ENABLE (0x06) /* Port Enable */
443#define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) /* Event Notification */
444#define MPI2_FUNCTION_EVENT_ACK (0x08) /* Event Acknowledge */
445#define MPI2_FUNCTION_FW_DOWNLOAD (0x09) /* FW Download */
446#define MPI2_FUNCTION_TARGET_ASSIST (0x0B) /* Target Assist */
447#define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) /* Target Status Send */
448#define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) /* Target Mode Abort */
449#define MPI2_FUNCTION_FW_UPLOAD (0x12) /* FW Upload */
450#define MPI2_FUNCTION_RAID_ACTION (0x15) /* RAID Action */
451#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) /* SCSI IO RAID Passthrough */
452#define MPI2_FUNCTION_TOOLBOX (0x17) /* Toolbox */
453#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) /* SCSI Enclosure Processor */
454#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) /* SMP Passthrough */
455#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) /* SAS IO Unit Control */
456#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) /* SATA Passthrough */
457#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) /* Diagnostic Buffer Post */
458#define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */
459#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) /* Target Command Buffer Post Base */
460#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) /* Target Command Buffer Post List */
461
462
463
464/* Doorbell functions */
465#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40)
466/* #define MPI2_FUNCTION_IO_UNIT_RESET (0x41) */
467#define MPI2_FUNCTION_HANDSHAKE (0x42)
468
469
470/*****************************************************************************
471*
472* IOC Status Values
473*
474*****************************************************************************/
475
476/* mask for IOCStatus status value */
477#define MPI2_IOCSTATUS_MASK (0x7FFF)
478
479/****************************************************************************
480* Common IOCStatus values for all replies
481****************************************************************************/
482
483#define MPI2_IOCSTATUS_SUCCESS (0x0000)
484#define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001)
485#define MPI2_IOCSTATUS_BUSY (0x0002)
486#define MPI2_IOCSTATUS_INVALID_SGL (0x0003)
487#define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004)
488#define MPI2_IOCSTATUS_INVALID_VPID (0x0005)
489#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006)
490#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007)
491#define MPI2_IOCSTATUS_INVALID_STATE (0x0008)
492#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009)
493
494/****************************************************************************
495* Config IOCStatus values
496****************************************************************************/
497
498#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020)
499#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021)
500#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022)
501#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023)
502#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024)
503#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025)
504
505/****************************************************************************
506* SCSI IO Reply
507****************************************************************************/
508
509#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040)
510#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042)
511#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043)
512#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044)
513#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045)
514#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046)
515#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047)
516#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048)
517#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049)
518#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A)
519#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B)
520#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C)
521
522/****************************************************************************
523* For use by SCSI Initiator and SCSI Target end-to-end data protection
524****************************************************************************/
525
526#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D)
527#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E)
528#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F)
529
530/****************************************************************************
531* SCSI Target values
532****************************************************************************/
533
534#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062)
535#define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063)
536#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064)
537#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065)
538#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
539#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
540#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
541#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
542#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)
543#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)
544
545/****************************************************************************
546* Serial Attached SCSI values
547****************************************************************************/
548
549#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
550#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091)
551
552/****************************************************************************
553* Diagnostic Buffer Post / Diagnostic Release values
554****************************************************************************/
555
556#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0)
557
558
559/****************************************************************************
560* IOCStatus flag to indicate that log info is available
561****************************************************************************/
562
563#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000)
564
565/****************************************************************************
566* IOCLogInfo Types
567****************************************************************************/
568
569#define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000)
570#define MPI2_IOCLOGINFO_TYPE_SHIFT (28)
571#define MPI2_IOCLOGINFO_TYPE_NONE (0x0)
572#define MPI2_IOCLOGINFO_TYPE_SCSI (0x1)
573#define MPI2_IOCLOGINFO_TYPE_FC (0x2)
574#define MPI2_IOCLOGINFO_TYPE_SAS (0x3)
575#define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4)
576#define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF)
577
578
579/*****************************************************************************
580*
581* Standard Message Structures
582*
583*****************************************************************************/
584
585/****************************************************************************
586* Request Message Header for all request messages
587****************************************************************************/
588
589typedef struct _MPI2_REQUEST_HEADER
590{
591 U16 FunctionDependent1; /* 0x00 */
592 U8 ChainOffset; /* 0x02 */
593 U8 Function; /* 0x03 */
594 U16 FunctionDependent2; /* 0x04 */
595 U8 FunctionDependent3; /* 0x06 */
596 U8 MsgFlags; /* 0x07 */
597 U8 VP_ID; /* 0x08 */
598 U8 VF_ID; /* 0x09 */
599 U16 Reserved1; /* 0x0A */
600} MPI2_REQUEST_HEADER, MPI2_POINTER PTR_MPI2_REQUEST_HEADER,
601 MPI2RequestHeader_t, MPI2_POINTER pMPI2RequestHeader_t;
602
603
604/****************************************************************************
605* Default Reply
606****************************************************************************/
607
608typedef struct _MPI2_DEFAULT_REPLY
609{
610 U16 FunctionDependent1; /* 0x00 */
611 U8 MsgLength; /* 0x02 */
612 U8 Function; /* 0x03 */
613 U16 FunctionDependent2; /* 0x04 */
614 U8 FunctionDependent3; /* 0x06 */
615 U8 MsgFlags; /* 0x07 */
616 U8 VP_ID; /* 0x08 */
617 U8 VF_ID; /* 0x09 */
618 U16 Reserved1; /* 0x0A */
619 U16 FunctionDependent5; /* 0x0C */
620 U16 IOCStatus; /* 0x0E */
621 U32 IOCLogInfo; /* 0x10 */
622} MPI2_DEFAULT_REPLY, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY,
623 MPI2DefaultReply_t, MPI2_POINTER pMPI2DefaultReply_t;
624
625
626/* common version structure/union used in messages and configuration pages */
627
628typedef struct _MPI2_VERSION_STRUCT
629{
630 U8 Dev; /* 0x00 */
631 U8 Unit; /* 0x01 */
632 U8 Minor; /* 0x02 */
633 U8 Major; /* 0x03 */
634} MPI2_VERSION_STRUCT;
635
636typedef union _MPI2_VERSION_UNION
637{
638 MPI2_VERSION_STRUCT Struct;
639 U32 Word;
640} MPI2_VERSION_UNION;
641
642
643/* LUN field defines, common to many structures */
644#define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF)
645#define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000)
646#define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF)
647#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000)
648#define MPI2_LUN_LEVEL_1_WORD (0xFF00)
649#define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00)
650
651
652/*****************************************************************************
653*
654* Fusion-MPT MPI Scatter Gather Elements
655*
656*****************************************************************************/
657
658/****************************************************************************
659* MPI Simple Element structures
660****************************************************************************/
661
662typedef struct _MPI2_SGE_SIMPLE32
663{
664 U32 FlagsLength;
665 U32 Address;
666} MPI2_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_SGE_SIMPLE32,
667 Mpi2SGESimple32_t, MPI2_POINTER pMpi2SGESimple32_t;
668
669typedef struct _MPI2_SGE_SIMPLE64
670{
671 U32 FlagsLength;
672 U64 Address;
673} MPI2_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_SGE_SIMPLE64,
674 Mpi2SGESimple64_t, MPI2_POINTER pMpi2SGESimple64_t;
675
676typedef struct _MPI2_SGE_SIMPLE_UNION
677{
678 U32 FlagsLength;
679 union
680 {
681 U32 Address32;
682 U64 Address64;
683 } u;
684} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION,
685 Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t;
686
687
688/****************************************************************************
689* MPI Chain Element structures
690****************************************************************************/
691
692typedef struct _MPI2_SGE_CHAIN32
693{
694 U16 Length;
695 U8 NextChainOffset;
696 U8 Flags;
697 U32 Address;
698} MPI2_SGE_CHAIN32, MPI2_POINTER PTR_MPI2_SGE_CHAIN32,
699 Mpi2SGEChain32_t, MPI2_POINTER pMpi2SGEChain32_t;
700
701typedef struct _MPI2_SGE_CHAIN64
702{
703 U16 Length;
704 U8 NextChainOffset;
705 U8 Flags;
706 U64 Address;
707} MPI2_SGE_CHAIN64, MPI2_POINTER PTR_MPI2_SGE_CHAIN64,
708 Mpi2SGEChain64_t, MPI2_POINTER pMpi2SGEChain64_t;
709
710typedef struct _MPI2_SGE_CHAIN_UNION
711{
712 U16 Length;
713 U8 NextChainOffset;
714 U8 Flags;
715 union
716 {
717 U32 Address32;
718 U64 Address64;
719 } u;
720} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION,
721 Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t;
722
723
724/****************************************************************************
725* MPI Transaction Context Element structures
726****************************************************************************/
727
728typedef struct _MPI2_SGE_TRANSACTION32
729{
730 U8 Reserved;
731 U8 ContextSize;
732 U8 DetailsLength;
733 U8 Flags;
734 U32 TransactionContext[1];
735 U32 TransactionDetails[1];
736} MPI2_SGE_TRANSACTION32, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION32,
737 Mpi2SGETransaction32_t, MPI2_POINTER pMpi2SGETransaction32_t;
738
739typedef struct _MPI2_SGE_TRANSACTION64
740{
741 U8 Reserved;
742 U8 ContextSize;
743 U8 DetailsLength;
744 U8 Flags;
745 U32 TransactionContext[2];
746 U32 TransactionDetails[1];
747} MPI2_SGE_TRANSACTION64, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION64,
748 Mpi2SGETransaction64_t, MPI2_POINTER pMpi2SGETransaction64_t;
749
750typedef struct _MPI2_SGE_TRANSACTION96
751{
752 U8 Reserved;
753 U8 ContextSize;
754 U8 DetailsLength;
755 U8 Flags;
756 U32 TransactionContext[3];
757 U32 TransactionDetails[1];
758} MPI2_SGE_TRANSACTION96, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION96,
759 Mpi2SGETransaction96_t, MPI2_POINTER pMpi2SGETransaction96_t;
760
761typedef struct _MPI2_SGE_TRANSACTION128
762{
763 U8 Reserved;
764 U8 ContextSize;
765 U8 DetailsLength;
766 U8 Flags;
767 U32 TransactionContext[4];
768 U32 TransactionDetails[1];
769} MPI2_SGE_TRANSACTION128, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION128,
770 Mpi2SGETransaction_t128, MPI2_POINTER pMpi2SGETransaction_t128;
771
772typedef struct _MPI2_SGE_TRANSACTION_UNION
773{
774 U8 Reserved;
775 U8 ContextSize;
776 U8 DetailsLength;
777 U8 Flags;
778 union
779 {
780 U32 TransactionContext32[1];
781 U32 TransactionContext64[2];
782 U32 TransactionContext96[3];
783 U32 TransactionContext128[4];
784 } u;
785 U32 TransactionDetails[1];
786} MPI2_SGE_TRANSACTION_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION_UNION,
787 Mpi2SGETransactionUnion_t, MPI2_POINTER pMpi2SGETransactionUnion_t;
788
789
790/****************************************************************************
791* MPI SGE union for IO SGL's
792****************************************************************************/
793
794typedef struct _MPI2_MPI_SGE_IO_UNION
795{
796 union
797 {
798 MPI2_SGE_SIMPLE_UNION Simple;
799 MPI2_SGE_CHAIN_UNION Chain;
800 } u;
801} MPI2_MPI_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_IO_UNION,
802 Mpi2MpiSGEIOUnion_t, MPI2_POINTER pMpi2MpiSGEIOUnion_t;
803
804
805/****************************************************************************
806* MPI SGE union for SGL's with Simple and Transaction elements
807****************************************************************************/
808
809typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION
810{
811 union
812 {
813 MPI2_SGE_SIMPLE_UNION Simple;
814 MPI2_SGE_TRANSACTION_UNION Transaction;
815 } u;
816} MPI2_SGE_TRANS_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANS_SIMPLE_UNION,
817 Mpi2SGETransSimpleUnion_t, MPI2_POINTER pMpi2SGETransSimpleUnion_t;
818
819
820/****************************************************************************
821* All MPI SGE types union
822****************************************************************************/
823
824typedef struct _MPI2_MPI_SGE_UNION
825{
826 union
827 {
828 MPI2_SGE_SIMPLE_UNION Simple;
829 MPI2_SGE_CHAIN_UNION Chain;
830 MPI2_SGE_TRANSACTION_UNION Transaction;
831 } u;
832} MPI2_MPI_SGE_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_UNION,
833 Mpi2MpiSgeUnion_t, MPI2_POINTER pMpi2MpiSgeUnion_t;
834
835
836/****************************************************************************
837* MPI SGE field definition and masks
838****************************************************************************/
839
840/* Flags field bit definitions */
841
842#define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80)
843#define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40)
844#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30)
845#define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08)
846#define MPI2_SGE_FLAGS_DIRECTION (0x04)
847#define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02)
848#define MPI2_SGE_FLAGS_END_OF_LIST (0x01)
849
850#define MPI2_SGE_FLAGS_SHIFT (24)
851
852#define MPI2_SGE_LENGTH_MASK (0x00FFFFFF)
853#define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF)
854
855/* Element Type */
856
857#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00)
858#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10)
859#define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30)
860#define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30)
861
862/* Address location */
863
864#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00)
865
866/* Direction */
867
868#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00)
869#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04)
870
871/* Address Size */
872
873#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00)
874#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02)
875
876/* Context Size */
877
878#define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00)
879#define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02)
880#define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04)
881#define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06)
882
883#define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000)
884#define MPI2_SGE_CHAIN_OFFSET_SHIFT (16)
885
886/****************************************************************************
887* MPI SGE operation Macros
888****************************************************************************/
889
890/* SIMPLE FlagsLength manipulations... */
891#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT)
892#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> MPI2_SGE_FLAGS_SHIFT)
893#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK)
894#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK)
895
896#define MPI2_SGE_SET_FLAGS_LENGTH(f,l) (MPI2_SGE_SET_FLAGS(f) | MPI2_SGE_LENGTH(l))
897
898#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength)
899#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength)
900#define MPI2_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_SGE_SET_FLAGS_LENGTH(f,l)
901
902/* CAUTION - The following are READ-MODIFY-WRITE! */
903#define MPI2_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_SGE_SET_FLAGS(f)
904#define MPI2_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_SGE_LENGTH(l)
905
906#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> MPI2_SGE_CHAIN_OFFSET_SHIFT)
907
908
909/*****************************************************************************
910*
911* Fusion-MPT IEEE Scatter Gather Elements
912*
913*****************************************************************************/
914
915/****************************************************************************
916* IEEE Simple Element structures
917****************************************************************************/
918
919typedef struct _MPI2_IEEE_SGE_SIMPLE32
920{
921 U32 Address;
922 U32 FlagsLength;
923} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32,
924 Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t;
925
926typedef struct _MPI2_IEEE_SGE_SIMPLE64
927{
928 U64 Address;
929 U32 Length;
930 U16 Reserved1;
931 U8 Reserved2;
932 U8 Flags;
933} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64,
934 Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t;
935
936typedef union _MPI2_IEEE_SGE_SIMPLE_UNION
937{
938 MPI2_IEEE_SGE_SIMPLE32 Simple32;
939 MPI2_IEEE_SGE_SIMPLE64 Simple64;
940} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
941 Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t;
942
943
944/****************************************************************************
945* IEEE Chain Element structures
946****************************************************************************/
947
948typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32;
949
950typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64;
951
952typedef union _MPI2_IEEE_SGE_CHAIN_UNION
953{
954 MPI2_IEEE_SGE_CHAIN32 Chain32;
955 MPI2_IEEE_SGE_CHAIN64 Chain64;
956} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION,
957 Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t;
958
959
960/****************************************************************************
961* All IEEE SGE types union
962****************************************************************************/
963
964typedef struct _MPI2_IEEE_SGE_UNION
965{
966 union
967 {
968 MPI2_IEEE_SGE_SIMPLE_UNION Simple;
969 MPI2_IEEE_SGE_CHAIN_UNION Chain;
970 } u;
971} MPI2_IEEE_SGE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_UNION,
972 Mpi2IeeeSgeUnion_t, MPI2_POINTER pMpi2IeeeSgeUnion_t;
973
974
975/****************************************************************************
976* IEEE SGE field definitions and masks
977****************************************************************************/
978
979/* Flags field bit definitions */
980
981#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80)
982
983#define MPI2_IEEE32_SGE_FLAGS_SHIFT (24)
984
985#define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF)
986
987/* Element Type */
988
989#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00)
990#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
991
992/* Data Location Address Space */
993
994#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03)
995#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
996#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
997#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
998#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
999
1000
1001/****************************************************************************
1002* IEEE SGE operation Macros
1003****************************************************************************/
1004
1005/* SIMPLE FlagsLength manipulations... */
1006#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT)
1007#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) >> MPI2_IEEE32_SGE_FLAGS_SHIFT)
1008#define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK)
1009
1010#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) | MPI2_IEEE32_SGE_LENGTH(l))
1011
1012#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength)
1013#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength)
1014#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f,l)
1015
1016/* CAUTION - The following are READ-MODIFY-WRITE! */
1017#define MPI2_IEEE32_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_IEEE32_SGE_SET_FLAGS(f)
1018#define MPI2_IEEE32_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_IEEE32_SGE_LENGTH(l)
1019
1020
1021
1022
1023/*****************************************************************************
1024*
1025* Fusion-MPT MPI/IEEE Scatter Gather Unions
1026*
1027*****************************************************************************/
1028
1029typedef union _MPI2_SIMPLE_SGE_UNION
1030{
1031 MPI2_SGE_SIMPLE_UNION MpiSimple;
1032 MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
1033} MPI2_SIMPLE_SGE_UNION, MPI2_POINTER PTR_MPI2_SIMPLE_SGE_UNION,
1034 Mpi2SimpleSgeUntion_t, MPI2_POINTER pMpi2SimpleSgeUntion_t;
1035
1036
1037typedef union _MPI2_SGE_IO_UNION
1038{
1039 MPI2_SGE_SIMPLE_UNION MpiSimple;
1040 MPI2_SGE_CHAIN_UNION MpiChain;
1041 MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
1042 MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;
1043} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION,
1044 Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t;
1045
1046
1047/****************************************************************************
1048*
1049* Values for SGLFlags field, used in many request messages with an SGL
1050*
1051****************************************************************************/
1052
1053/* values for MPI SGL Data Location Address Space subfield */
1054#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C)
1055#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00)
1056#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04)
1057#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08)
1058#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C)
1059/* values for SGL Type subfield */
1060#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03)
1061#define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00)
1062#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01)
1063#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02)
1064
1065
1066#endif
1067
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
new file mode 100644
index 000000000000..2f27cf6d6c65
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -0,0 +1,2151 @@
1/*
2 * Copyright (c) 2000-2009 LSI Corporation.
3 *
4 *
5 * Name: mpi2_cnfg.h
6 * Title: MPI Configuration messages and pages
7 * Creation Date: November 10, 2006
8 *
9 * mpi2_cnfg.h Version: 02.00.10
10 *
11 * Version History
12 * ---------------
13 *
14 * Date Version Description
15 * -------- -------- ------------------------------------------------------
16 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
17 * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags.
18 * Added Manufacturing Page 11.
19 * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
20 * define.
21 * 06-26-07 02.00.02 Adding generic structure for product-specific
22 * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
23 * Rework of BIOS Page 2 configuration page.
24 * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
25 * forms.
26 * Added configuration pages IOC Page 8 and Driver
27 * Persistent Mapping Page 0.
28 * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated
29 * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
30 * RAID Physical Disk Pages 0 and 1, RAID Configuration
31 * Page 0).
32 * Added new value for AccessStatus field of SAS Device
33 * Page 0 (_SATA_NEEDS_INITIALIZATION).
34 * 10-31-07 02.00.04 Added missing SEPDevHandle field to
35 * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
36 * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for
37 * NVDATA.
38 * Modified IOC Page 7 to use masks and added field for
39 * SASBroadcastPrimitiveMasks.
40 * Added MPI2_CONFIG_PAGE_BIOS_4.
41 * Added MPI2_CONFIG_PAGE_LOG_0.
42 * 02-29-08 02.00.06 Modified various names to make them 32-character unique.
43 * Added SAS Device IDs.
44 * Updated Integrated RAID configuration pages including
45 * Manufacturing Page 4, IOC Page 6, and RAID Configuration
46 * Page 0.
47 * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
48 * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
49 * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
50 * Added missing MaxNumRoutedSasAddresses field to
51 * MPI2_CONFIG_PAGE_EXPANDER_0.
52 * Added SAS Port Page 0.
53 * Modified structure layout for
54 * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
55 * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
56 * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
57 * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
58 * to 0x000000FF.
59 * Added two new values for the Physical Disk Coercion Size
60 * bits in the Flags field of Manufacturing Page 4.
61 * Added product-specific Manufacturing pages 16 to 31.
62 * Modified Flags bits for controlling write cache on SATA
63 * drives in IO Unit Page 1.
64 * Added new bit to AdditionalControlFlags of SAS IO Unit
65 * Page 1 to control Invalid Topology Correction.
66 * Added additional defines for RAID Volume Page 0
67 * VolumeStatusFlags field.
68 * Modified meaning of RAID Volume Page 0 VolumeSettings
69 * define for auto-configure of hot-swap drives.
70 * Added SupportedPhysDisks field to RAID Volume Page 1 and
71 * added related defines.
72 * Added PhysDiskAttributes field (and related defines) to
73 * RAID Physical Disk Page 0.
74 * Added MPI2_SAS_PHYINFO_PHY_VACANT define.
75 * Added three new DiscoveryStatus bits for SAS IO Unit
76 * Page 0 and SAS Expander Page 0.
77 * Removed multiplexing information from SAS IO Unit pages.
78 * Added BootDeviceWaitTime field to SAS IO Unit Page 4.
79 * Removed Zone Address Resolved bit from PhyInfo and from
80 * Expander Page 0 Flags field.
81 * Added two new AccessStatus values to SAS Device Page 0
82 * for indicating routing problems. Added 3 reserved words
83 * to this page.
84 * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3.
85 * Inserted missing reserved field into structure for IOC
86 * Page 6.
87 * Added more pending task bits to RAID Volume Page 0
88 * VolumeStatusFlags defines.
89 * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
90 * Added a new DiscoveryStatus bit for SAS IO Unit Page 0
91 * and SAS Expander Page 0 to flag a downstream initiator
92 * when in simplified routing mode.
93 * Removed SATA Init Failure defines for DiscoveryStatus
94 * fields of SAS IO Unit Page 0 and SAS Expander Page 0.
95 * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
96 * Added PortGroups, DmaGroup, and ControlGroup fields to
97 * SAS Device Page 0.
98 * --------------------------------------------------------------------------
99 */
100
101#ifndef MPI2_CNFG_H
102#define MPI2_CNFG_H
103
104/*****************************************************************************
105* Configuration Page Header and defines
106*****************************************************************************/
107
108/* Config Page Header */
109typedef struct _MPI2_CONFIG_PAGE_HEADER
110{
111 U8 PageVersion; /* 0x00 */
112 U8 PageLength; /* 0x01 */
113 U8 PageNumber; /* 0x02 */
114 U8 PageType; /* 0x03 */
115} MPI2_CONFIG_PAGE_HEADER, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER,
116 Mpi2ConfigPageHeader_t, MPI2_POINTER pMpi2ConfigPageHeader_t;
117
118typedef union _MPI2_CONFIG_PAGE_HEADER_UNION
119{
120 MPI2_CONFIG_PAGE_HEADER Struct;
121 U8 Bytes[4];
122 U16 Word16[2];
123 U32 Word32;
124} MPI2_CONFIG_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER_UNION,
125 Mpi2ConfigPageHeaderUnion, MPI2_POINTER pMpi2ConfigPageHeaderUnion;
126
127/* Extended Config Page Header */
128typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER
129{
130 U8 PageVersion; /* 0x00 */
131 U8 Reserved1; /* 0x01 */
132 U8 PageNumber; /* 0x02 */
133 U8 PageType; /* 0x03 */
134 U16 ExtPageLength; /* 0x04 */
135 U8 ExtPageType; /* 0x06 */
136 U8 Reserved2; /* 0x07 */
137} MPI2_CONFIG_EXTENDED_PAGE_HEADER,
138 MPI2_POINTER PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER,
139 Mpi2ConfigExtendedPageHeader_t, MPI2_POINTER pMpi2ConfigExtendedPageHeader_t;
140
141typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
142{
143 MPI2_CONFIG_PAGE_HEADER Struct;
144 MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext;
145 U8 Bytes[8];
146 U16 Word16[4];
147 U32 Word32[2];
148} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
149 Mpi2ConfigPageExtendedHeaderUnion, MPI2_POINTER pMpi2ConfigPageExtendedHeaderUnion;
150
151
152/* PageType field values */
153#define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00)
154#define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10)
155#define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20)
156#define MPI2_CONFIG_PAGEATTR_MASK (0xF0)
157
158#define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00)
159#define MPI2_CONFIG_PAGETYPE_IOC (0x01)
160#define MPI2_CONFIG_PAGETYPE_BIOS (0x02)
161#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08)
162#define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09)
163#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A)
164#define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F)
165#define MPI2_CONFIG_PAGETYPE_MASK (0x0F)
166
167#define MPI2_CONFIG_TYPENUM_MASK (0x0FFF)
168
169
170/* ExtPageType field values */
171#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10)
172#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11)
173#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12)
174#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13)
175#define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14)
176#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15)
177#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16)
178#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17)
179#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
180
181
182/*****************************************************************************
183* PageAddress defines
184*****************************************************************************/
185
186/* RAID Volume PageAddress format */
187#define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000)
188#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
189#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000)
190
191#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF)
192
193
194/* RAID Physical Disk PageAddress format */
195#define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000)
196#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000)
197#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000)
198#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000)
199
200#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF)
201#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF)
202
203
204/* SAS Expander PageAddress format */
205#define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000)
206#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000)
207#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000)
208#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000)
209
210#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF)
211#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000)
212#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16)
213
214
215/* SAS Device PageAddress format */
216#define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000)
217#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
218#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000)
219
220#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF)
221
222
223/* SAS PHY PageAddress format */
224#define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000)
225#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000)
226#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000)
227
228#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF)
229#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF)
230
231
232/* SAS Port PageAddress format */
233#define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000)
234#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000)
235#define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000)
236
237#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF)
238
239
240/* SAS Enclosure PageAddress format */
241#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000)
242#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
243#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000)
244
245#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF)
246
247
248/* RAID Configuration PageAddress format */
249#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000)
250#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000)
251#define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000)
252#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000)
253
254#define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF)
255
256
257/* Driver Persistent Mapping PageAddress format */
258#define MPI2_DPM_PGAD_FORM_MASK (0xF0000000)
259#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000)
260
261#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000)
262#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16)
263#define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF)
264
265
266/****************************************************************************
267* Configuration messages
268****************************************************************************/
269
270/* Configuration Request Message */
271typedef struct _MPI2_CONFIG_REQUEST
272{
273 U8 Action; /* 0x00 */
274 U8 SGLFlags; /* 0x01 */
275 U8 ChainOffset; /* 0x02 */
276 U8 Function; /* 0x03 */
277 U16 ExtPageLength; /* 0x04 */
278 U8 ExtPageType; /* 0x06 */
279 U8 MsgFlags; /* 0x07 */
280 U8 VP_ID; /* 0x08 */
281 U8 VF_ID; /* 0x09 */
282 U16 Reserved1; /* 0x0A */
283 U32 Reserved2; /* 0x0C */
284 U32 Reserved3; /* 0x10 */
285 MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */
286 U32 PageAddress; /* 0x18 */
287 MPI2_SGE_IO_UNION PageBufferSGE; /* 0x1C */
288} MPI2_CONFIG_REQUEST, MPI2_POINTER PTR_MPI2_CONFIG_REQUEST,
289 Mpi2ConfigRequest_t, MPI2_POINTER pMpi2ConfigRequest_t;
290
291/* values for the Action field */
292#define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00)
293#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01)
294#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02)
295#define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03)
296#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04)
297#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05)
298#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06)
299#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07)
300
301/* values for SGLFlags field are in the SGL section of mpi2.h */
302
303
304/* Config Reply Message */
305typedef struct _MPI2_CONFIG_REPLY
306{
307 U8 Action; /* 0x00 */
308 U8 SGLFlags; /* 0x01 */
309 U8 MsgLength; /* 0x02 */
310 U8 Function; /* 0x03 */
311 U16 ExtPageLength; /* 0x04 */
312 U8 ExtPageType; /* 0x06 */
313 U8 MsgFlags; /* 0x07 */
314 U8 VP_ID; /* 0x08 */
315 U8 VF_ID; /* 0x09 */
316 U16 Reserved1; /* 0x0A */
317 U16 Reserved2; /* 0x0C */
318 U16 IOCStatus; /* 0x0E */
319 U32 IOCLogInfo; /* 0x10 */
320 MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */
321} MPI2_CONFIG_REPLY, MPI2_POINTER PTR_MPI2_CONFIG_REPLY,
322 Mpi2ConfigReply_t, MPI2_POINTER pMpi2ConfigReply_t;
323
324
325
326/*****************************************************************************
327*
328* C o n f i g u r a t i o n P a g e s
329*
330*****************************************************************************/
331
332/****************************************************************************
333* Manufacturing Config pages
334****************************************************************************/
335
336#define MPI2_MFGPAGE_VENDORID_LSI (0x1000)
337
338/* SAS */
339#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070)
340#define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072)
341#define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074)
342#define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076)
343#define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077)
344#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064)
345#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065)
346
347
348/* Manufacturing Page 0 */
349
350typedef struct _MPI2_CONFIG_PAGE_MAN_0
351{
352 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
353 U8 ChipName[16]; /* 0x04 */
354 U8 ChipRevision[8]; /* 0x14 */
355 U8 BoardName[16]; /* 0x1C */
356 U8 BoardAssembly[16]; /* 0x2C */
357 U8 BoardTracerNumber[16]; /* 0x3C */
358} MPI2_CONFIG_PAGE_MAN_0,
359 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_0,
360 Mpi2ManufacturingPage0_t, MPI2_POINTER pMpi2ManufacturingPage0_t;
361
362#define MPI2_MANUFACTURING0_PAGEVERSION (0x00)
363
364
365/* Manufacturing Page 1 */
366
367typedef struct _MPI2_CONFIG_PAGE_MAN_1
368{
369 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
370 U8 VPD[256]; /* 0x04 */
371} MPI2_CONFIG_PAGE_MAN_1,
372 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_1,
373 Mpi2ManufacturingPage1_t, MPI2_POINTER pMpi2ManufacturingPage1_t;
374
375#define MPI2_MANUFACTURING1_PAGEVERSION (0x00)
376
377
378typedef struct _MPI2_CHIP_REVISION_ID
379{
380 U16 DeviceID; /* 0x00 */
381 U8 PCIRevisionID; /* 0x02 */
382 U8 Reserved; /* 0x03 */
383} MPI2_CHIP_REVISION_ID, MPI2_POINTER PTR_MPI2_CHIP_REVISION_ID,
384 Mpi2ChipRevisionId_t, MPI2_POINTER pMpi2ChipRevisionId_t;
385
386
387/* Manufacturing Page 2 */
388
389/*
390 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
391 * one and check Header.PageLength at runtime.
392 */
393#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
394#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1)
395#endif
396
397typedef struct _MPI2_CONFIG_PAGE_MAN_2
398{
399 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
400 MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */
401 U32 HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 0x08 */
402} MPI2_CONFIG_PAGE_MAN_2,
403 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_2,
404 Mpi2ManufacturingPage2_t, MPI2_POINTER pMpi2ManufacturingPage2_t;
405
406#define MPI2_MANUFACTURING2_PAGEVERSION (0x00)
407
408
409/* Manufacturing Page 3 */
410
411/*
412 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
413 * one and check Header.PageLength at runtime.
414 */
415#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
416#define MPI2_MAN_PAGE_3_INFO_WORDS (1)
417#endif
418
419typedef struct _MPI2_CONFIG_PAGE_MAN_3
420{
421 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
422 MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */
423 U32 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/* 0x08 */
424} MPI2_CONFIG_PAGE_MAN_3,
425 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_3,
426 Mpi2ManufacturingPage3_t, MPI2_POINTER pMpi2ManufacturingPage3_t;
427
428#define MPI2_MANUFACTURING3_PAGEVERSION (0x00)
429
430
431/* Manufacturing Page 4 */
432
433typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS
434{
435 U8 PowerSaveFlags; /* 0x00 */
436 U8 InternalOperationsSleepTime; /* 0x01 */
437 U8 InternalOperationsRunTime; /* 0x02 */
438 U8 HostIdleTime; /* 0x03 */
439} MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
440 MPI2_POINTER PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
441 Mpi2ManPage4PwrSaveSettings_t, MPI2_POINTER pMpi2ManPage4PwrSaveSettings_t;
442
443/* defines for the PowerSaveFlags field */
444#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03)
445#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00)
446#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01)
447#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02)
448
449typedef struct _MPI2_CONFIG_PAGE_MAN_4
450{
451 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
452 U32 Reserved1; /* 0x04 */
453 U32 Flags; /* 0x08 */
454 U8 InquirySize; /* 0x0C */
455 U8 Reserved2; /* 0x0D */
456 U16 Reserved3; /* 0x0E */
457 U8 InquiryData[56]; /* 0x10 */
458 U32 RAID0VolumeSettings; /* 0x48 */
459 U32 RAID1EVolumeSettings; /* 0x4C */
460 U32 RAID1VolumeSettings; /* 0x50 */
461 U32 RAID10VolumeSettings; /* 0x54 */
462 U32 Reserved4; /* 0x58 */
463 U32 Reserved5; /* 0x5C */
464 MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /* 0x60 */
465 U8 MaxOCEDisks; /* 0x64 */
466 U8 ResyncRate; /* 0x65 */
467 U16 DataScrubDuration; /* 0x66 */
468 U8 MaxHotSpares; /* 0x68 */
469 U8 MaxPhysDisksPerVol; /* 0x69 */
470 U8 MaxPhysDisks; /* 0x6A */
471 U8 MaxVolumes; /* 0x6B */
472} MPI2_CONFIG_PAGE_MAN_4,
473 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_4,
474 Mpi2ManufacturingPage4_t, MPI2_POINTER pMpi2ManufacturingPage4_t;
475
476#define MPI2_MANUFACTURING4_PAGEVERSION (0x0A)
477
478/* Manufacturing Page 4 Flags field */
479#define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000)
480#define MPI2_MANPAGE4_METADATA_512MB (0x00000000)
481
482#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000)
483#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000)
484#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000)
485
486#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00)
487#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000)
488#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400)
489#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800)
490#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00)
491
492#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300)
493#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000)
494#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100)
495#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200)
496
497#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080)
498#define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040)
499#define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020)
500#define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010)
501#define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008)
502#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004)
503#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002)
504#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001)
505
506
507/* Manufacturing Page 5 */
508
509/*
510 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
511 * one and check Header.PageLength or NumPhys at runtime.
512 */
513#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
514#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1)
515#endif
516
517typedef struct _MPI2_MANUFACTURING5_ENTRY
518{
519 U64 WWID; /* 0x00 */
520 U64 DeviceName; /* 0x08 */
521} MPI2_MANUFACTURING5_ENTRY, MPI2_POINTER PTR_MPI2_MANUFACTURING5_ENTRY,
522 Mpi2Manufacturing5Entry_t, MPI2_POINTER pMpi2Manufacturing5Entry_t;
523
524typedef struct _MPI2_CONFIG_PAGE_MAN_5
525{
526 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
527 U8 NumPhys; /* 0x04 */
528 U8 Reserved1; /* 0x05 */
529 U16 Reserved2; /* 0x06 */
530 U32 Reserved3; /* 0x08 */
531 U32 Reserved4; /* 0x0C */
532 MPI2_MANUFACTURING5_ENTRY Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/* 0x08 */
533} MPI2_CONFIG_PAGE_MAN_5,
534 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_5,
535 Mpi2ManufacturingPage5_t, MPI2_POINTER pMpi2ManufacturingPage5_t;
536
537#define MPI2_MANUFACTURING5_PAGEVERSION (0x03)
538
539
540/* Manufacturing Page 6 */
541
542typedef struct _MPI2_CONFIG_PAGE_MAN_6
543{
544 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
545 U32 ProductSpecificInfo;/* 0x04 */
546} MPI2_CONFIG_PAGE_MAN_6,
547 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_6,
548 Mpi2ManufacturingPage6_t, MPI2_POINTER pMpi2ManufacturingPage6_t;
549
550#define MPI2_MANUFACTURING6_PAGEVERSION (0x00)
551
552
553/* Manufacturing Page 7 */
554
555typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
556{
557 U32 Pinout; /* 0x00 */
558 U8 Connector[16]; /* 0x04 */
559 U8 Location; /* 0x14 */
560 U8 Reserved1; /* 0x15 */
561 U16 Slot; /* 0x16 */
562 U32 Reserved2; /* 0x18 */
563} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
564 Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
565
566/* defines for the Pinout field */
567#define MPI2_MANPAGE7_PINOUT_SFF_8484_L4 (0x00080000)
568#define MPI2_MANPAGE7_PINOUT_SFF_8484_L3 (0x00040000)
569#define MPI2_MANPAGE7_PINOUT_SFF_8484_L2 (0x00020000)
570#define MPI2_MANPAGE7_PINOUT_SFF_8484_L1 (0x00010000)
571#define MPI2_MANPAGE7_PINOUT_SFF_8470_L4 (0x00000800)
572#define MPI2_MANPAGE7_PINOUT_SFF_8470_L3 (0x00000400)
573#define MPI2_MANPAGE7_PINOUT_SFF_8470_L2 (0x00000200)
574#define MPI2_MANPAGE7_PINOUT_SFF_8470_L1 (0x00000100)
575#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x00000002)
576#define MPI2_MANPAGE7_PINOUT_CONNECTION_UNKNOWN (0x00000001)
577
578/* defines for the Location field */
579#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
580#define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02)
581#define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04)
582#define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08)
583#define MPI2_MANPAGE7_LOCATION_AUTO (0x10)
584#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20)
585#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80)
586
587/*
588 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
589 * one and check NumPhys at runtime.
590 */
591#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
592#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1)
593#endif
594
595typedef struct _MPI2_CONFIG_PAGE_MAN_7
596{
597 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
598 U32 Reserved1; /* 0x04 */
599 U32 Reserved2; /* 0x08 */
600 U32 Flags; /* 0x0C */
601 U8 EnclosureName[16]; /* 0x10 */
602 U8 NumPhys; /* 0x20 */
603 U8 Reserved3; /* 0x21 */
604 U16 Reserved4; /* 0x22 */
605 MPI2_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /* 0x24 */
606} MPI2_CONFIG_PAGE_MAN_7,
607 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
608 Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
609
610#define MPI2_MANUFACTURING7_PAGEVERSION (0x00)
611
612/* defines for the Flags field */
613#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
614
615
616/*
617 * Generic structure to use for product-specific manufacturing pages
618 * (currently Manufacturing Page 8 through Manufacturing Page 31).
619 */
620
621typedef struct _MPI2_CONFIG_PAGE_MAN_PS
622{
623 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
624 U32 ProductSpecificInfo;/* 0x04 */
625} MPI2_CONFIG_PAGE_MAN_PS,
626 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_PS,
627 Mpi2ManufacturingPagePS_t, MPI2_POINTER pMpi2ManufacturingPagePS_t;
628
629#define MPI2_MANUFACTURING8_PAGEVERSION (0x00)
630#define MPI2_MANUFACTURING9_PAGEVERSION (0x00)
631#define MPI2_MANUFACTURING10_PAGEVERSION (0x00)
632#define MPI2_MANUFACTURING11_PAGEVERSION (0x00)
633#define MPI2_MANUFACTURING12_PAGEVERSION (0x00)
634#define MPI2_MANUFACTURING13_PAGEVERSION (0x00)
635#define MPI2_MANUFACTURING14_PAGEVERSION (0x00)
636#define MPI2_MANUFACTURING15_PAGEVERSION (0x00)
637#define MPI2_MANUFACTURING16_PAGEVERSION (0x00)
638#define MPI2_MANUFACTURING17_PAGEVERSION (0x00)
639#define MPI2_MANUFACTURING18_PAGEVERSION (0x00)
640#define MPI2_MANUFACTURING19_PAGEVERSION (0x00)
641#define MPI2_MANUFACTURING20_PAGEVERSION (0x00)
642#define MPI2_MANUFACTURING21_PAGEVERSION (0x00)
643#define MPI2_MANUFACTURING22_PAGEVERSION (0x00)
644#define MPI2_MANUFACTURING23_PAGEVERSION (0x00)
645#define MPI2_MANUFACTURING24_PAGEVERSION (0x00)
646#define MPI2_MANUFACTURING25_PAGEVERSION (0x00)
647#define MPI2_MANUFACTURING26_PAGEVERSION (0x00)
648#define MPI2_MANUFACTURING27_PAGEVERSION (0x00)
649#define MPI2_MANUFACTURING28_PAGEVERSION (0x00)
650#define MPI2_MANUFACTURING29_PAGEVERSION (0x00)
651#define MPI2_MANUFACTURING30_PAGEVERSION (0x00)
652#define MPI2_MANUFACTURING31_PAGEVERSION (0x00)
653
654
655/****************************************************************************
656* IO Unit Config Pages
657****************************************************************************/
658
659/* IO Unit Page 0 */
660
661typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0
662{
663 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
664 U64 UniqueValue; /* 0x04 */
665 MPI2_VERSION_UNION NvdataVersionDefault; /* 0x08 */
666 MPI2_VERSION_UNION NvdataVersionPersistent; /* 0x0A */
667} MPI2_CONFIG_PAGE_IO_UNIT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_0,
668 Mpi2IOUnitPage0_t, MPI2_POINTER pMpi2IOUnitPage0_t;
669
670#define MPI2_IOUNITPAGE0_PAGEVERSION (0x02)
671
672
673/* IO Unit Page 1 */
674
675typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1
676{
677 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
678 U32 Flags; /* 0x04 */
679} MPI2_CONFIG_PAGE_IO_UNIT_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_1,
680 Mpi2IOUnitPage1_t, MPI2_POINTER pMpi2IOUnitPage1_t;
681
682#define MPI2_IOUNITPAGE1_PAGEVERSION (0x04)
683
684/* IO Unit Page 1 Flags defines */
685#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600)
686#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000)
687#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200)
688#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400)
689#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100)
690#define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040)
691#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
692#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004)
693#define MPI2_IOUNITPAGE1_MULTI_PATHING (0x00000002)
694#define MPI2_IOUNITPAGE1_SINGLE_PATHING (0x00000000)
695
696
697/* IO Unit Page 3 */
698
699/*
700 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
701 * one and check Header.PageLength at runtime.
702 */
703#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
704#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1)
705#endif
706
707typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3
708{
709 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
710 U8 GPIOCount; /* 0x04 */
711 U8 Reserved1; /* 0x05 */
712 U16 Reserved2; /* 0x06 */
713 U16 GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/* 0x08 */
714} MPI2_CONFIG_PAGE_IO_UNIT_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
715 Mpi2IOUnitPage3_t, MPI2_POINTER pMpi2IOUnitPage3_t;
716
717#define MPI2_IOUNITPAGE3_PAGEVERSION (0x01)
718
719/* defines for IO Unit Page 3 GPIOVal field */
720#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC)
721#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2)
722#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000)
723#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001)
724
725
726/****************************************************************************
727* IOC Config Pages
728****************************************************************************/
729
730/* IOC Page 0 */
731
732typedef struct _MPI2_CONFIG_PAGE_IOC_0
733{
734 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
735 U32 Reserved1; /* 0x04 */
736 U32 Reserved2; /* 0x08 */
737 U16 VendorID; /* 0x0C */
738 U16 DeviceID; /* 0x0E */
739 U8 RevisionID; /* 0x10 */
740 U8 Reserved3; /* 0x11 */
741 U16 Reserved4; /* 0x12 */
742 U32 ClassCode; /* 0x14 */
743 U16 SubsystemVendorID; /* 0x18 */
744 U16 SubsystemID; /* 0x1A */
745} MPI2_CONFIG_PAGE_IOC_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_0,
746 Mpi2IOCPage0_t, MPI2_POINTER pMpi2IOCPage0_t;
747
748#define MPI2_IOCPAGE0_PAGEVERSION (0x02)
749
750
751/* IOC Page 1 */
752
753typedef struct _MPI2_CONFIG_PAGE_IOC_1
754{
755 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
756 U32 Flags; /* 0x04 */
757 U32 CoalescingTimeout; /* 0x08 */
758 U8 CoalescingDepth; /* 0x0C */
759 U8 PCISlotNum; /* 0x0D */
760 U8 PCIBusNum; /* 0x0E */
761 U8 PCIDomainSegment; /* 0x0F */
762 U32 Reserved1; /* 0x10 */
763 U32 Reserved2; /* 0x14 */
764} MPI2_CONFIG_PAGE_IOC_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_1,
765 Mpi2IOCPage1_t, MPI2_POINTER pMpi2IOCPage1_t;
766
767#define MPI2_IOCPAGE1_PAGEVERSION (0x05)
768
769/* defines for IOC Page 1 Flags field */
770#define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001)
771
772#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF)
773#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF)
774#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF)
775
776/* IOC Page 6 */
777
778typedef struct _MPI2_CONFIG_PAGE_IOC_6
779{
780 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
781 U32 CapabilitiesFlags; /* 0x04 */
782 U8 MaxDrivesRAID0; /* 0x08 */
783 U8 MaxDrivesRAID1; /* 0x09 */
784 U8 MaxDrivesRAID1E; /* 0x0A */
785 U8 MaxDrivesRAID10; /* 0x0B */
786 U8 MinDrivesRAID0; /* 0x0C */
787 U8 MinDrivesRAID1; /* 0x0D */
788 U8 MinDrivesRAID1E; /* 0x0E */
789 U8 MinDrivesRAID10; /* 0x0F */
790 U32 Reserved1; /* 0x10 */
791 U8 MaxGlobalHotSpares; /* 0x14 */
792 U8 MaxPhysDisks; /* 0x15 */
793 U8 MaxVolumes; /* 0x16 */
794 U8 MaxConfigs; /* 0x17 */
795 U8 MaxOCEDisks; /* 0x18 */
796 U8 Reserved2; /* 0x19 */
797 U16 Reserved3; /* 0x1A */
798 U32 SupportedStripeSizeMapRAID0; /* 0x1C */
799 U32 SupportedStripeSizeMapRAID1E; /* 0x20 */
800 U32 SupportedStripeSizeMapRAID10; /* 0x24 */
801 U32 Reserved4; /* 0x28 */
802 U32 Reserved5; /* 0x2C */
803 U16 DefaultMetadataSize; /* 0x30 */
804 U16 Reserved6; /* 0x32 */
805 U16 MaxBadBlockTableEntries; /* 0x34 */
806 U16 Reserved7; /* 0x36 */
807 U32 IRNvsramVersion; /* 0x38 */
808} MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6,
809 Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t;
810
811#define MPI2_IOCPAGE6_PAGEVERSION (0x04)
812
813/* defines for IOC Page 6 CapabilitiesFlags */
814#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010)
815#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008)
816#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004)
817#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002)
818#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001)
819
820
821/* IOC Page 7 */
822
823#define MPI2_IOCPAGE7_EVENTMASK_WORDS (4)
824
825typedef struct _MPI2_CONFIG_PAGE_IOC_7
826{
827 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
828 U32 Reserved1; /* 0x04 */
829 U32 EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */
830 U16 SASBroadcastPrimitiveMasks; /* 0x18 */
831 U16 Reserved2; /* 0x1A */
832 U32 Reserved3; /* 0x1C */
833} MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7,
834 Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t;
835
836#define MPI2_IOCPAGE7_PAGEVERSION (0x01)
837
838
839/* IOC Page 8 */
840
841typedef struct _MPI2_CONFIG_PAGE_IOC_8
842{
843 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
844 U8 NumDevsPerEnclosure; /* 0x04 */
845 U8 Reserved1; /* 0x05 */
846 U16 Reserved2; /* 0x06 */
847 U16 MaxPersistentEntries; /* 0x08 */
848 U16 MaxNumPhysicalMappedIDs; /* 0x0A */
849 U16 Flags; /* 0x0C */
850 U16 Reserved3; /* 0x0E */
851 U16 IRVolumeMappingFlags; /* 0x10 */
852 U16 Reserved4; /* 0x12 */
853 U32 Reserved5; /* 0x14 */
854} MPI2_CONFIG_PAGE_IOC_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_8,
855 Mpi2IOCPage8_t, MPI2_POINTER pMpi2IOCPage8_t;
856
857#define MPI2_IOCPAGE8_PAGEVERSION (0x00)
858
859/* defines for IOC Page 8 Flags field */
860#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020)
861#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010)
862
863#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E)
864#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000)
865#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002)
866
867#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001)
868#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000)
869
870/* defines for IOC Page 8 IRVolumeMappingFlags */
871#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003)
872#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000)
873#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001)
874
875
876/****************************************************************************
877* BIOS Config Pages
878****************************************************************************/
879
880/* BIOS Page 1 */
881
882typedef struct _MPI2_CONFIG_PAGE_BIOS_1
883{
884 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
885 U32 BiosOptions; /* 0x04 */
886 U32 IOCSettings; /* 0x08 */
887 U32 Reserved1; /* 0x0C */
888 U32 DeviceSettings; /* 0x10 */
889 U16 NumberOfDevices; /* 0x14 */
890 U16 Reserved2; /* 0x16 */
891 U16 IOTimeoutBlockDevicesNonRM; /* 0x18 */
892 U16 IOTimeoutSequential; /* 0x1A */
893 U16 IOTimeoutOther; /* 0x1C */
894 U16 IOTimeoutBlockDevicesRM; /* 0x1E */
895} MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1,
896 Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t;
897
898#define MPI2_BIOSPAGE1_PAGEVERSION (0x04)
899
900/* values for BIOS Page 1 BiosOptions field */
901#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
902
903/* values for BIOS Page 1 IOCSettings field */
904#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
905#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
906#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
907
908#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0)
909#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000)
910#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040)
911#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080)
912
913#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030)
914#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000)
915#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010)
916#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020)
917#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030)
918
919#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008)
920
921/* values for BIOS Page 1 DeviceSettings field */
922#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010)
923#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008)
924#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004)
925#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
926#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
927
928
929/* BIOS Page 2 */
930
931typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER
932{
933 U32 Reserved1; /* 0x00 */
934 U32 Reserved2; /* 0x04 */
935 U32 Reserved3; /* 0x08 */
936 U32 Reserved4; /* 0x0C */
937 U32 Reserved5; /* 0x10 */
938 U32 Reserved6; /* 0x14 */
939} MPI2_BOOT_DEVICE_ADAPTER_ORDER,
940 MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER,
941 Mpi2BootDeviceAdapterOrder_t, MPI2_POINTER pMpi2BootDeviceAdapterOrder_t;
942
943typedef struct _MPI2_BOOT_DEVICE_SAS_WWID
944{
945 U64 SASAddress; /* 0x00 */
946 U8 LUN[8]; /* 0x08 */
947 U32 Reserved1; /* 0x10 */
948 U32 Reserved2; /* 0x14 */
949} MPI2_BOOT_DEVICE_SAS_WWID, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_SAS_WWID,
950 Mpi2BootDeviceSasWwid_t, MPI2_POINTER pMpi2BootDeviceSasWwid_t;
951
952typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT
953{
954 U64 EnclosureLogicalID; /* 0x00 */
955 U32 Reserved1; /* 0x08 */
956 U32 Reserved2; /* 0x0C */
957 U16 SlotNumber; /* 0x10 */
958 U16 Reserved3; /* 0x12 */
959 U32 Reserved4; /* 0x14 */
960} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
961 MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
962 Mpi2BootDeviceEnclosureSlot_t, MPI2_POINTER pMpi2BootDeviceEnclosureSlot_t;
963
964typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME
965{
966 U64 DeviceName; /* 0x00 */
967 U8 LUN[8]; /* 0x08 */
968 U32 Reserved1; /* 0x10 */
969 U32 Reserved2; /* 0x14 */
970} MPI2_BOOT_DEVICE_DEVICE_NAME, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_DEVICE_NAME,
971 Mpi2BootDeviceDeviceName_t, MPI2_POINTER pMpi2BootDeviceDeviceName_t;
972
973typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE
974{
975 MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder;
976 MPI2_BOOT_DEVICE_SAS_WWID SasWwid;
977 MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot;
978 MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName;
979} MPI2_BIOSPAGE2_BOOT_DEVICE, MPI2_POINTER PTR_MPI2_BIOSPAGE2_BOOT_DEVICE,
980 Mpi2BiosPage2BootDevice_t, MPI2_POINTER pMpi2BiosPage2BootDevice_t;
981
982typedef struct _MPI2_CONFIG_PAGE_BIOS_2
983{
984 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
985 U32 Reserved1; /* 0x04 */
986 U32 Reserved2; /* 0x08 */
987 U32 Reserved3; /* 0x0C */
988 U32 Reserved4; /* 0x10 */
989 U32 Reserved5; /* 0x14 */
990 U32 Reserved6; /* 0x18 */
991 U8 ReqBootDeviceForm; /* 0x1C */
992 U8 Reserved7; /* 0x1D */
993 U16 Reserved8; /* 0x1E */
994 MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /* 0x20 */
995 U8 ReqAltBootDeviceForm; /* 0x38 */
996 U8 Reserved9; /* 0x39 */
997 U16 Reserved10; /* 0x3A */
998 MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /* 0x3C */
999 U8 CurrentBootDeviceForm; /* 0x58 */
1000 U8 Reserved11; /* 0x59 */
1001 U16 Reserved12; /* 0x5A */
1002 MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /* 0x58 */
1003} MPI2_CONFIG_PAGE_BIOS_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_2,
1004 Mpi2BiosPage2_t, MPI2_POINTER pMpi2BiosPage2_t;
1005
1006#define MPI2_BIOSPAGE2_PAGEVERSION (0x04)
1007
1008/* values for BIOS Page 2 BootDeviceForm fields */
1009#define MPI2_BIOSPAGE2_FORM_MASK (0x0F)
1010#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00)
1011#define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05)
1012#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06)
1013#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07)
1014
1015
1016/* BIOS Page 3 */
1017
1018typedef struct _MPI2_ADAPTER_INFO
1019{
1020 U8 PciBusNumber; /* 0x00 */
1021 U8 PciDeviceAndFunctionNumber; /* 0x01 */
1022 U16 AdapterFlags; /* 0x02 */
1023} MPI2_ADAPTER_INFO, MPI2_POINTER PTR_MPI2_ADAPTER_INFO,
1024 Mpi2AdapterInfo_t, MPI2_POINTER pMpi2AdapterInfo_t;
1025
1026#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001)
1027#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002)
1028
1029typedef struct _MPI2_CONFIG_PAGE_BIOS_3
1030{
1031 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
1032 U32 GlobalFlags; /* 0x04 */
1033 U32 BiosVersion; /* 0x08 */
1034 MPI2_ADAPTER_INFO AdapterOrder[4]; /* 0x0C */
1035 U32 Reserved1; /* 0x1C */
1036} MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3,
1037 Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t;
1038
1039#define MPI2_BIOSPAGE3_PAGEVERSION (0x00)
1040
1041/* values for BIOS Page 3 GlobalFlags */
1042#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002)
1043#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004)
1044#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010)
1045
1046#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0)
1047#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000)
1048#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020)
1049#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040)
1050
1051
1052/* BIOS Page 4 */
1053
1054/*
1055 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1056 * one and check Header.PageLength or NumPhys at runtime.
1057 */
1058#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
1059#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1)
1060#endif
1061
1062typedef struct _MPI2_BIOS4_ENTRY
1063{
1064 U64 ReassignmentWWID; /* 0x00 */
1065 U64 ReassignmentDeviceName; /* 0x08 */
1066} MPI2_BIOS4_ENTRY, MPI2_POINTER PTR_MPI2_BIOS4_ENTRY,
1067 Mpi2MBios4Entry_t, MPI2_POINTER pMpi2Bios4Entry_t;
1068
1069typedef struct _MPI2_CONFIG_PAGE_BIOS_4
1070{
1071 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
1072 U8 NumPhys; /* 0x04 */
1073 U8 Reserved1; /* 0x05 */
1074 U16 Reserved2; /* 0x06 */
1075 MPI2_BIOS4_ENTRY Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /* 0x08 */
1076} MPI2_CONFIG_PAGE_BIOS_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_4,
1077 Mpi2BiosPage4_t, MPI2_POINTER pMpi2BiosPage4_t;
1078
1079#define MPI2_BIOSPAGE4_PAGEVERSION (0x01)
1080
1081
1082/****************************************************************************
1083* RAID Volume Config Pages
1084****************************************************************************/
1085
1086/* RAID Volume Page 0 */
1087
1088typedef struct _MPI2_RAIDVOL0_PHYS_DISK
1089{
1090 U8 RAIDSetNum; /* 0x00 */
1091 U8 PhysDiskMap; /* 0x01 */
1092 U8 PhysDiskNum; /* 0x02 */
1093 U8 Reserved; /* 0x03 */
1094} MPI2_RAIDVOL0_PHYS_DISK, MPI2_POINTER PTR_MPI2_RAIDVOL0_PHYS_DISK,
1095 Mpi2RaidVol0PhysDisk_t, MPI2_POINTER pMpi2RaidVol0PhysDisk_t;
1096
1097/* defines for the PhysDiskMap field */
1098#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01)
1099#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02)
1100
1101typedef struct _MPI2_RAIDVOL0_SETTINGS
1102{
1103 U16 Settings; /* 0x00 */
1104 U8 HotSparePool; /* 0x01 */
1105 U8 Reserved; /* 0x02 */
1106} MPI2_RAIDVOL0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDVOL0_SETTINGS,
1107 Mpi2RaidVol0Settings_t, MPI2_POINTER pMpi2RaidVol0Settings_t;
1108
1109/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */
1110#define MPI2_RAID_HOT_SPARE_POOL_0 (0x01)
1111#define MPI2_RAID_HOT_SPARE_POOL_1 (0x02)
1112#define MPI2_RAID_HOT_SPARE_POOL_2 (0x04)
1113#define MPI2_RAID_HOT_SPARE_POOL_3 (0x08)
1114#define MPI2_RAID_HOT_SPARE_POOL_4 (0x10)
1115#define MPI2_RAID_HOT_SPARE_POOL_5 (0x20)
1116#define MPI2_RAID_HOT_SPARE_POOL_6 (0x40)
1117#define MPI2_RAID_HOT_SPARE_POOL_7 (0x80)
1118
1119/* RAID Volume Page 0 VolumeSettings defines */
1120#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008)
1121#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004)
1122
1123#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003)
1124#define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000)
1125#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001)
1126#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002)
1127
1128/*
1129 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1130 * one and check Header.PageLength at runtime.
1131 */
1132#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
1133#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1)
1134#endif
1135
1136typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0
1137{
1138 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
1139 U16 DevHandle; /* 0x04 */
1140 U8 VolumeState; /* 0x06 */
1141 U8 VolumeType; /* 0x07 */
1142 U32 VolumeStatusFlags; /* 0x08 */
1143 MPI2_RAIDVOL0_SETTINGS VolumeSettings; /* 0x0C */
1144 U64 MaxLBA; /* 0x10 */
1145 U32 StripeSize; /* 0x18 */
1146 U16 BlockSize; /* 0x1C */
1147 U16 Reserved1; /* 0x1E */
1148 U8 SupportedPhysDisks; /* 0x20 */
1149 U8 ResyncRate; /* 0x21 */
1150 U16 DataScrubDuration; /* 0x22 */
1151 U8 NumPhysDisks; /* 0x24 */
1152 U8 Reserved2; /* 0x25 */
1153 U8 Reserved3; /* 0x26 */
1154 U8 InactiveStatus; /* 0x27 */
1155 MPI2_RAIDVOL0_PHYS_DISK PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /* 0x28 */
1156} MPI2_CONFIG_PAGE_RAID_VOL_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
1157 Mpi2RaidVolPage0_t, MPI2_POINTER pMpi2RaidVolPage0_t;
1158
1159#define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A)
1160
1161/* values for RAID VolumeState */
1162#define MPI2_RAID_VOL_STATE_MISSING (0x00)
1163#define MPI2_RAID_VOL_STATE_FAILED (0x01)
1164#define MPI2_RAID_VOL_STATE_INITIALIZING (0x02)
1165#define MPI2_RAID_VOL_STATE_ONLINE (0x03)
1166#define MPI2_RAID_VOL_STATE_DEGRADED (0x04)
1167#define MPI2_RAID_VOL_STATE_OPTIMAL (0x05)
1168
1169/* values for RAID VolumeType */
1170#define MPI2_RAID_VOL_TYPE_RAID0 (0x00)
1171#define MPI2_RAID_VOL_TYPE_RAID1E (0x01)
1172#define MPI2_RAID_VOL_TYPE_RAID1 (0x02)
1173#define MPI2_RAID_VOL_TYPE_RAID10 (0x05)
1174#define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF)
1175
1176/* values for RAID Volume Page 0 VolumeStatusFlags field */
1177#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000)
1178#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000)
1179#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000)
1180#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000)
1181#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000)
1182#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000)
1183#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000)
1184#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000)
1185#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000)
1186#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000)
1187#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040)
1188#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020)
1189#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000)
1190#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010)
1191#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008)
1192#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004)
1193#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002)
1194#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001)
1195
1196/* values for RAID Volume Page 0 SupportedPhysDisks field */
1197#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08)
1198#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04)
1199#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02)
1200#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01)
1201
1202/* values for RAID Volume Page 0 InactiveStatus field */
1203#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
1204#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01)
1205#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02)
1206#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03)
1207#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04)
1208#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05)
1209#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06)
1210
1211
1212/* RAID Volume Page 1 */
1213
1214typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1
1215{
1216 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
1217 U16 DevHandle; /* 0x04 */
1218 U16 Reserved0; /* 0x06 */
1219 U8 GUID[24]; /* 0x08 */
1220 U8 Name[16]; /* 0x20 */
1221 U64 WWID; /* 0x30 */
1222 U32 Reserved1; /* 0x38 */
1223 U32 Reserved2; /* 0x3C */
1224} MPI2_CONFIG_PAGE_RAID_VOL_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_1,
1225 Mpi2RaidVolPage1_t, MPI2_POINTER pMpi2RaidVolPage1_t;
1226
1227#define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03)
1228
1229
1230/****************************************************************************
1231* RAID Physical Disk Config Pages
1232****************************************************************************/
1233
1234/* RAID Physical Disk Page 0 */
1235
1236typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS
1237{
1238 U16 Reserved1; /* 0x00 */
1239 U8 HotSparePool; /* 0x02 */
1240 U8 Reserved2; /* 0x03 */
1241} MPI2_RAIDPHYSDISK0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_SETTINGS,
1242 Mpi2RaidPhysDisk0Settings_t, MPI2_POINTER pMpi2RaidPhysDisk0Settings_t;
1243
1244/* use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */
1245
1246typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA
1247{
1248 U8 VendorID[8]; /* 0x00 */
1249 U8 ProductID[16]; /* 0x08 */
1250 U8 ProductRevLevel[4]; /* 0x18 */
1251 U8 SerialNum[32]; /* 0x1C */
1252} MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
1253 MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
1254 Mpi2RaidPhysDisk0InquiryData_t, MPI2_POINTER pMpi2RaidPhysDisk0InquiryData_t;
1255
1256typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0
1257{
1258 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
1259 U16 DevHandle; /* 0x04 */
1260 U8 Reserved1; /* 0x06 */
1261 U8 PhysDiskNum; /* 0x07 */
1262 MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /* 0x08 */
1263 U32 Reserved2; /* 0x0C */
1264 MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /* 0x10 */
1265 U32 Reserved3; /* 0x4C */
1266 U8 PhysDiskState; /* 0x50 */
1267 U8 OfflineReason; /* 0x51 */
1268 U8 IncompatibleReason; /* 0x52 */
1269 U8 PhysDiskAttributes; /* 0x53 */
1270 U32 PhysDiskStatusFlags; /* 0x54 */
1271 U64 DeviceMaxLBA; /* 0x58 */
1272 U64 HostMaxLBA; /* 0x60 */
1273 U64 CoercedMaxLBA; /* 0x68 */
1274 U16 BlockSize; /* 0x70 */
1275 U16 Reserved5; /* 0x72 */
1276 U32 Reserved6; /* 0x74 */
1277} MPI2_CONFIG_PAGE_RD_PDISK_0,
1278 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_0,
1279 Mpi2RaidPhysDiskPage0_t, MPI2_POINTER pMpi2RaidPhysDiskPage0_t;
1280
1281#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05)
1282
1283/* PhysDiskState defines */
1284#define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00)
1285#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01)
1286#define MPI2_RAID_PD_STATE_OFFLINE (0x02)
1287#define MPI2_RAID_PD_STATE_ONLINE (0x03)
1288#define MPI2_RAID_PD_STATE_HOT_SPARE (0x04)
1289#define MPI2_RAID_PD_STATE_DEGRADED (0x05)
1290#define MPI2_RAID_PD_STATE_REBUILDING (0x06)
1291#define MPI2_RAID_PD_STATE_OPTIMAL (0x07)
1292
1293/* OfflineReason defines */
1294#define MPI2_PHYSDISK0_ONLINE (0x00)
1295#define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01)
1296#define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03)
1297#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04)
1298#define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05)
1299#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06)
1300#define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF)
1301
1302/* IncompatibleReason defines */
1303#define MPI2_PHYSDISK0_COMPATIBLE (0x00)
1304#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01)
1305#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02)
1306#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03)
1307#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04)
1308#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05)
1309#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF)
1310
1311/* PhysDiskAttributes defines */
1312#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08)
1313#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04)
1314#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02)
1315#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01)
1316
1317/* PhysDiskStatusFlags defines */
1318#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040)
1319#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020)
1320#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010)
1321#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000)
1322#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008)
1323#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004)
1324#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002)
1325#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001)
1326
1327
1328/* RAID Physical Disk Page 1 */
1329
1330/*
1331 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1332 * one and check Header.PageLength or NumPhysDiskPaths at runtime.
1333 */
1334#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
1335#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1)
1336#endif
1337
1338typedef struct _MPI2_RAIDPHYSDISK1_PATH
1339{
1340 U16 DevHandle; /* 0x00 */
1341 U16 Reserved1; /* 0x02 */
1342 U64 WWID; /* 0x04 */
1343 U64 OwnerWWID; /* 0x0C */
1344 U8 OwnerIdentifier; /* 0x14 */
1345 U8 Reserved2; /* 0x15 */
1346 U16 Flags; /* 0x16 */
1347} MPI2_RAIDPHYSDISK1_PATH, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK1_PATH,
1348 Mpi2RaidPhysDisk1Path_t, MPI2_POINTER pMpi2RaidPhysDisk1Path_t;
1349
1350/* RAID Physical Disk Page 1 Physical Disk Path Flags field defines */
1351#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004)
1352#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002)
1353#define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001)
1354
1355typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
1356{
1357 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
1358 U8 NumPhysDiskPaths; /* 0x04 */
1359 U8 PhysDiskNum; /* 0x05 */
1360 U16 Reserved1; /* 0x06 */
1361 U32 Reserved2; /* 0x08 */
1362 MPI2_RAIDPHYSDISK1_PATH PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/* 0x0C */
1363} MPI2_CONFIG_PAGE_RD_PDISK_1,
1364 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
1365 Mpi2RaidPhysDiskPage1_t, MPI2_POINTER pMpi2RaidPhysDiskPage1_t;
1366
1367#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02)
1368
1369
1370/****************************************************************************
1371* values for fields used by several types of SAS Config Pages
1372****************************************************************************/
1373
1374/* values for NegotiatedLinkRates fields */
1375#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0)
1376#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4)
1377#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F)
1378/* link rates used for Negotiated Physical and Logical Link Rate */
1379#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00)
1380#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01)
1381#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02)
1382#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03)
1383#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04)
1384#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05)
1385#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08)
1386#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09)
1387#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A)
1388
1389
1390/* values for AttachedPhyInfo fields */
1391#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040)
1392#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020)
1393#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010)
1394
1395#define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F)
1396#define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000)
1397#define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001)
1398#define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002)
1399#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003)
1400#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004)
1401#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005)
1402#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006)
1403#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007)
1404#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008)
1405
1406
1407/* values for PhyInfo fields */
1408#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000)
1409#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000)
1410#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000)
1411#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000)
1412#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000)
1413#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000)
1414#define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000)
1415
1416#define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000)
1417#define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000)
1418#define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000)
1419#define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000)
1420#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000)
1421#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000)
1422#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000)
1423#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000)
1424#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000)
1425#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000)
1426
1427#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000)
1428#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000)
1429#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000)
1430#define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000)
1431
1432#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00)
1433#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8)
1434
1435#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0)
1436#define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000)
1437#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010)
1438#define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020)
1439
1440
1441/* values for SAS ProgrammedLinkRate fields */
1442#define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0)
1443#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00)
1444#define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80)
1445#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90)
1446#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0)
1447#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F)
1448#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00)
1449#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08)
1450#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09)
1451#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A)
1452
1453
1454/* values for SAS HwLinkRate fields */
1455#define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0)
1456#define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80)
1457#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90)
1458#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0)
1459#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F)
1460#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08)
1461#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09)
1462#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A)
1463
1464
1465
1466/****************************************************************************
1467* SAS IO Unit Config Pages
1468****************************************************************************/
1469
1470/* SAS IO Unit Page 0 */
1471
1472typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA
1473{
1474 U8 Port; /* 0x00 */
1475 U8 PortFlags; /* 0x01 */
1476 U8 PhyFlags; /* 0x02 */
1477 U8 NegotiatedLinkRate; /* 0x03 */
1478 U32 ControllerPhyDeviceInfo;/* 0x04 */
1479 U16 AttachedDevHandle; /* 0x08 */
1480 U16 ControllerDevHandle; /* 0x0A */
1481 U32 DiscoveryStatus; /* 0x0C */
1482 U32 Reserved; /* 0x10 */
1483} MPI2_SAS_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT0_PHY_DATA,
1484 Mpi2SasIOUnit0PhyData_t, MPI2_POINTER pMpi2SasIOUnit0PhyData_t;
1485
1486/*
1487 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1488 * one and check Header.ExtPageLength or NumPhys at runtime.
1489 */
1490#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
1491#define MPI2_SAS_IOUNIT0_PHY_MAX (1)
1492#endif
1493
1494typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0
1495{
1496 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1497 U32 Reserved1; /* 0x08 */
1498 U8 NumPhys; /* 0x0C */
1499 U8 Reserved2; /* 0x0D */
1500 U16 Reserved3; /* 0x0E */
1501 MPI2_SAS_IO_UNIT0_PHY_DATA PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /* 0x10 */
1502} MPI2_CONFIG_PAGE_SASIOUNIT_0,
1503 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
1504 Mpi2SasIOUnitPage0_t, MPI2_POINTER pMpi2SasIOUnitPage0_t;
1505
1506#define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05)
1507
1508/* values for SAS IO Unit Page 0 PortFlags */
1509#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08)
1510#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01)
1511
1512/* values for SAS IO Unit Page 0 PhyFlags */
1513#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10)
1514#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08)
1515
1516/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
1517
1518/* see mpi2_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
1519
1520/* values for SAS IO Unit Page 0 DiscoveryStatus */
1521#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
1522#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000)
1523#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000)
1524#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
1525#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000)
1526#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
1527#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
1528#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000)
1529#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
1530#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800)
1531#define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400)
1532#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200)
1533#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100)
1534#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080)
1535#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040)
1536#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020)
1537#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010)
1538#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004)
1539#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002)
1540#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001)
1541
1542
1543/* SAS IO Unit Page 1 */
1544
1545typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA
1546{
1547 U8 Port; /* 0x00 */
1548 U8 PortFlags; /* 0x01 */
1549 U8 PhyFlags; /* 0x02 */
1550 U8 MaxMinLinkRate; /* 0x03 */
1551 U32 ControllerPhyDeviceInfo; /* 0x04 */
1552 U16 MaxTargetPortConnectTime; /* 0x08 */
1553 U16 Reserved1; /* 0x0A */
1554} MPI2_SAS_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT1_PHY_DATA,
1555 Mpi2SasIOUnit1PhyData_t, MPI2_POINTER pMpi2SasIOUnit1PhyData_t;
1556
1557/*
1558 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1559 * one and check Header.ExtPageLength or NumPhys at runtime.
1560 */
1561#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
1562#define MPI2_SAS_IOUNIT1_PHY_MAX (1)
1563#endif
1564
1565typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1
1566{
1567 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1568 U16 ControlFlags; /* 0x08 */
1569 U16 SASNarrowMaxQueueDepth; /* 0x0A */
1570 U16 AdditionalControlFlags; /* 0x0C */
1571 U16 SASWideMaxQueueDepth; /* 0x0E */
1572 U8 NumPhys; /* 0x10 */
1573 U8 SATAMaxQDepth; /* 0x11 */
1574 U8 ReportDeviceMissingDelay; /* 0x12 */
1575 U8 IODeviceMissingDelay; /* 0x13 */
1576 MPI2_SAS_IO_UNIT1_PHY_DATA PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /* 0x14 */
1577} MPI2_CONFIG_PAGE_SASIOUNIT_1,
1578 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
1579 Mpi2SasIOUnitPage1_t, MPI2_POINTER pMpi2SasIOUnitPage1_t;
1580
1581#define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09)
1582
1583/* values for SAS IO Unit Page 1 ControlFlags */
1584#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
1585#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
1586#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
1587#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
1588
1589#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
1590#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
1591#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0)
1592#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1)
1593#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2)
1594
1595#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
1596#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
1597#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
1598#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
1599#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008)
1600#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
1601#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
1602#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
1603
1604/* values for SAS IO Unit Page 1 AdditionalControlFlags */
1605#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080)
1606#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040)
1607#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020)
1608#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010)
1609#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008)
1610#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004)
1611#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002)
1612#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001)
1613
1614/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
1615#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F)
1616#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80)
1617
1618/* values for SAS IO Unit Page 1 PortFlags */
1619#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
1620
1621/* values for SAS IO Unit Page 2 PhyFlags */
1622#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10)
1623#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08)
1624
1625/* values for SAS IO Unit Page 0 MaxMinLinkRate */
1626#define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0)
1627#define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80)
1628#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90)
1629#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0)
1630#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F)
1631#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08)
1632#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09)
1633#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A)
1634
1635/* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
1636
1637
1638/* SAS IO Unit Page 4 */
1639
1640typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP
1641{
1642 U8 MaxTargetSpinup; /* 0x00 */
1643 U8 SpinupDelay; /* 0x01 */
1644 U16 Reserved1; /* 0x02 */
1645} MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP,
1646 Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t;
1647
1648/*
1649 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1650 * four and check Header.ExtPageLength or NumPhys at runtime.
1651 */
1652#ifndef MPI2_SAS_IOUNIT4_PHY_MAX
1653#define MPI2_SAS_IOUNIT4_PHY_MAX (4)
1654#endif
1655
1656typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4
1657{
1658 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1659 MPI2_SAS_IOUNIT4_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */
1660 U32 Reserved1; /* 0x18 */
1661 U32 Reserved2; /* 0x1C */
1662 U32 Reserved3; /* 0x20 */
1663 U8 BootDeviceWaitTime; /* 0x24 */
1664 U8 Reserved4; /* 0x25 */
1665 U16 Reserved5; /* 0x26 */
1666 U8 NumPhys; /* 0x28 */
1667 U8 PEInitialSpinupDelay; /* 0x29 */
1668 U8 PEReplyDelay; /* 0x2A */
1669 U8 Flags; /* 0x2B */
1670 U8 PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /* 0x2C */
1671} MPI2_CONFIG_PAGE_SASIOUNIT_4,
1672 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4,
1673 Mpi2SasIOUnitPage4_t, MPI2_POINTER pMpi2SasIOUnitPage4_t;
1674
1675#define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02)
1676
1677/* defines for Flags field */
1678#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01)
1679
1680/* defines for PHY field */
1681#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03)
1682
1683
1684/****************************************************************************
1685* SAS Expander Config Pages
1686****************************************************************************/
1687
1688/* SAS Expander Page 0 */
1689
1690typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0
1691{
1692 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1693 U8 PhysicalPort; /* 0x08 */
1694 U8 ReportGenLength; /* 0x09 */
1695 U16 EnclosureHandle; /* 0x0A */
1696 U64 SASAddress; /* 0x0C */
1697 U32 DiscoveryStatus; /* 0x14 */
1698 U16 DevHandle; /* 0x18 */
1699 U16 ParentDevHandle; /* 0x1A */
1700 U16 ExpanderChangeCount; /* 0x1C */
1701 U16 ExpanderRouteIndexes; /* 0x1E */
1702 U8 NumPhys; /* 0x20 */
1703 U8 SASLevel; /* 0x21 */
1704 U16 Flags; /* 0x22 */
1705 U16 STPBusInactivityTimeLimit; /* 0x24 */
1706 U16 STPMaxConnectTimeLimit; /* 0x26 */
1707 U16 STP_SMP_NexusLossTime; /* 0x28 */
1708 U16 MaxNumRoutedSasAddresses; /* 0x2A */
1709 U64 ActiveZoneManagerSASAddress;/* 0x2C */
1710 U16 ZoneLockInactivityLimit; /* 0x34 */
1711 U16 Reserved1; /* 0x36 */
1712} MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0,
1713 Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t;
1714
1715#define MPI2_SASEXPANDER0_PAGEVERSION (0x05)
1716
1717/* values for SAS Expander Page 0 DiscoveryStatus field */
1718#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
1719#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000)
1720#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000)
1721#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
1722#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000)
1723#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
1724#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
1725#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000)
1726#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
1727#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800)
1728#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400)
1729#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200)
1730#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100)
1731#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080)
1732#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040)
1733#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020)
1734#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010)
1735#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004)
1736#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002)
1737#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
1738
1739/* values for SAS Expander Page 0 Flags field */
1740#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000)
1741#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800)
1742#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400)
1743#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200)
1744#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100)
1745#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080)
1746#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010)
1747#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004)
1748#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002)
1749#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001)
1750
1751
1752/* SAS Expander Page 1 */
1753
1754typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1
1755{
1756 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1757 U8 PhysicalPort; /* 0x08 */
1758 U8 Reserved1; /* 0x09 */
1759 U16 Reserved2; /* 0x0A */
1760 U8 NumPhys; /* 0x0C */
1761 U8 Phy; /* 0x0D */
1762 U16 NumTableEntriesProgrammed; /* 0x0E */
1763 U8 ProgrammedLinkRate; /* 0x10 */
1764 U8 HwLinkRate; /* 0x11 */
1765 U16 AttachedDevHandle; /* 0x12 */
1766 U32 PhyInfo; /* 0x14 */
1767 U32 AttachedDeviceInfo; /* 0x18 */
1768 U16 ExpanderDevHandle; /* 0x1C */
1769 U8 ChangeCount; /* 0x1E */
1770 U8 NegotiatedLinkRate; /* 0x1F */
1771 U8 PhyIdentifier; /* 0x20 */
1772 U8 AttachedPhyIdentifier; /* 0x21 */
1773 U8 Reserved3; /* 0x22 */
1774 U8 DiscoveryInfo; /* 0x23 */
1775 U32 AttachedPhyInfo; /* 0x24 */
1776 U8 ZoneGroup; /* 0x28 */
1777 U8 SelfConfigStatus; /* 0x29 */
1778 U16 Reserved4; /* 0x2A */
1779} MPI2_CONFIG_PAGE_EXPANDER_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_1,
1780 Mpi2ExpanderPage1_t, MPI2_POINTER pMpi2ExpanderPage1_t;
1781
1782#define MPI2_SASEXPANDER1_PAGEVERSION (0x02)
1783
1784/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
1785
1786/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
1787
1788/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
1789
1790/* see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines used for the AttachedDeviceInfo field */
1791
1792/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
1793
1794/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
1795
1796/* values for SAS Expander Page 1 DiscoveryInfo field */
1797#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04)
1798#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02)
1799#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01)
1800
1801
1802/****************************************************************************
1803* SAS Device Config Pages
1804****************************************************************************/
1805
1806/* SAS Device Page 0 */
1807
1808typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0
1809{
1810 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1811 U16 Slot; /* 0x08 */
1812 U16 EnclosureHandle; /* 0x0A */
1813 U64 SASAddress; /* 0x0C */
1814 U16 ParentDevHandle; /* 0x14 */
1815 U8 PhyNum; /* 0x16 */
1816 U8 AccessStatus; /* 0x17 */
1817 U16 DevHandle; /* 0x18 */
1818 U8 AttachedPhyIdentifier; /* 0x1A */
1819 U8 ZoneGroup; /* 0x1B */
1820 U32 DeviceInfo; /* 0x1C */
1821 U16 Flags; /* 0x20 */
1822 U8 PhysicalPort; /* 0x22 */
1823 U8 MaxPortConnections; /* 0x23 */
1824 U64 DeviceName; /* 0x24 */
1825 U8 PortGroups; /* 0x2C */
1826 U8 DmaGroup; /* 0x2D */
1827 U8 ControlGroup; /* 0x2E */
1828 U8 Reserved1; /* 0x2F */
1829 U32 Reserved2; /* 0x30 */
1830 U32 Reserved3; /* 0x34 */
1831} MPI2_CONFIG_PAGE_SAS_DEV_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_0,
1832 Mpi2SasDevicePage0_t, MPI2_POINTER pMpi2SasDevicePage0_t;
1833
1834#define MPI2_SASDEVICE0_PAGEVERSION (0x08)
1835
1836/* values for SAS Device Page 0 AccessStatus field */
1837#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00)
1838#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01)
1839#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02)
1840#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03)
1841#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04)
1842#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05)
1843#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06)
1844#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07)
1845/* specific values for SATA Init failures */
1846#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10)
1847#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11)
1848#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12)
1849#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13)
1850#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14)
1851#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15)
1852#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16)
1853#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17)
1854#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18)
1855#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19)
1856#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F)
1857
1858/* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
1859
1860/* values for SAS Device Page 0 Flags field */
1861#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400)
1862#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200)
1863#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
1864#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080)
1865#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040)
1866#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020)
1867#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010)
1868#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008)
1869#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
1870
1871
1872/* SAS Device Page 1 */
1873
1874typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1
1875{
1876 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1877 U32 Reserved1; /* 0x08 */
1878 U64 SASAddress; /* 0x0C */
1879 U32 Reserved2; /* 0x14 */
1880 U16 DevHandle; /* 0x18 */
1881 U16 Reserved3; /* 0x1A */
1882 U8 InitialRegDeviceFIS[20];/* 0x1C */
1883} MPI2_CONFIG_PAGE_SAS_DEV_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_1,
1884 Mpi2SasDevicePage1_t, MPI2_POINTER pMpi2SasDevicePage1_t;
1885
1886#define MPI2_SASDEVICE1_PAGEVERSION (0x01)
1887
1888
1889/****************************************************************************
1890* SAS PHY Config Pages
1891****************************************************************************/
1892
1893/* SAS PHY Page 0 */
1894
1895typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0
1896{
1897 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1898 U16 OwnerDevHandle; /* 0x08 */
1899 U16 Reserved1; /* 0x0A */
1900 U16 AttachedDevHandle; /* 0x0C */
1901 U8 AttachedPhyIdentifier; /* 0x0E */
1902 U8 Reserved2; /* 0x0F */
1903 U32 AttachedPhyInfo; /* 0x10 */
1904 U8 ProgrammedLinkRate; /* 0x14 */
1905 U8 HwLinkRate; /* 0x15 */
1906 U8 ChangeCount; /* 0x16 */
1907 U8 Flags; /* 0x17 */
1908 U32 PhyInfo; /* 0x18 */
1909 U8 NegotiatedLinkRate; /* 0x1C */
1910 U8 Reserved3; /* 0x1D */
1911 U16 Reserved4; /* 0x1E */
1912} MPI2_CONFIG_PAGE_SAS_PHY_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_0,
1913 Mpi2SasPhyPage0_t, MPI2_POINTER pMpi2SasPhyPage0_t;
1914
1915#define MPI2_SASPHY0_PAGEVERSION (0x03)
1916
1917/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
1918
1919/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
1920
1921/* values for SAS PHY Page 0 Flags field */
1922#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01)
1923
1924/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
1925
1926/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
1927
1928/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
1929
1930
1931/* SAS PHY Page 1 */
1932
1933typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1
1934{
1935 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1936 U32 Reserved1; /* 0x08 */
1937 U32 InvalidDwordCount; /* 0x0C */
1938 U32 RunningDisparityErrorCount; /* 0x10 */
1939 U32 LossDwordSynchCount; /* 0x14 */
1940 U32 PhyResetProblemCount; /* 0x18 */
1941} MPI2_CONFIG_PAGE_SAS_PHY_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_1,
1942 Mpi2SasPhyPage1_t, MPI2_POINTER pMpi2SasPhyPage1_t;
1943
1944#define MPI2_SASPHY1_PAGEVERSION (0x01)
1945
1946
1947/****************************************************************************
1948* SAS Port Config Pages
1949****************************************************************************/
1950
1951/* SAS Port Page 0 */
1952
1953typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0
1954{
1955 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1956 U8 PortNumber; /* 0x08 */
1957 U8 PhysicalPort; /* 0x09 */
1958 U8 PortWidth; /* 0x0A */
1959 U8 PhysicalPortWidth; /* 0x0B */
1960 U8 ZoneGroup; /* 0x0C */
1961 U8 Reserved1; /* 0x0D */
1962 U16 Reserved2; /* 0x0E */
1963 U64 SASAddress; /* 0x10 */
1964 U32 DeviceInfo; /* 0x18 */
1965 U32 Reserved3; /* 0x1C */
1966 U32 Reserved4; /* 0x20 */
1967} MPI2_CONFIG_PAGE_SAS_PORT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PORT_0,
1968 Mpi2SasPortPage0_t, MPI2_POINTER pMpi2SasPortPage0_t;
1969
1970#define MPI2_SASPORT0_PAGEVERSION (0x00)
1971
1972/* see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */
1973
1974
1975/****************************************************************************
1976* SAS Enclosure Config Pages
1977****************************************************************************/
1978
1979/* SAS Enclosure Page 0 */
1980
1981typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0
1982{
1983 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
1984 U32 Reserved1; /* 0x08 */
1985 U64 EnclosureLogicalID; /* 0x0C */
1986 U16 Flags; /* 0x14 */
1987 U16 EnclosureHandle; /* 0x16 */
1988 U16 NumSlots; /* 0x18 */
1989 U16 StartSlot; /* 0x1A */
1990 U16 Reserved2; /* 0x1C */
1991 U16 SEPDevHandle; /* 0x1E */
1992 U32 Reserved3; /* 0x20 */
1993 U32 Reserved4; /* 0x24 */
1994} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
1995 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
1996 Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t;
1997
1998#define MPI2_SASENCLOSURE0_PAGEVERSION (0x03)
1999
2000/* values for SAS Enclosure Page 0 Flags field */
2001#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F)
2002#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000)
2003#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001)
2004#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
2005#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
2006#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
2007#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
2008
2009
2010/****************************************************************************
2011* Log Config Page
2012****************************************************************************/
2013
2014/* Log Page 0 */
2015
2016/*
2017 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2018 * one and check Header.ExtPageLength or NumPhys at runtime.
2019 */
2020#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
2021#define MPI2_LOG_0_NUM_LOG_ENTRIES (1)
2022#endif
2023
2024#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C)
2025
2026typedef struct _MPI2_LOG_0_ENTRY
2027{
2028 U64 TimeStamp; /* 0x00 */
2029 U32 Reserved1; /* 0x08 */
2030 U16 LogSequence; /* 0x0C */
2031 U16 LogEntryQualifier; /* 0x0E */
2032 U8 VP_ID; /* 0x10 */
2033 U8 VF_ID; /* 0x11 */
2034 U16 Reserved2; /* 0x12 */
2035 U8 LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/* 0x14 */
2036} MPI2_LOG_0_ENTRY, MPI2_POINTER PTR_MPI2_LOG_0_ENTRY,
2037 Mpi2Log0Entry_t, MPI2_POINTER pMpi2Log0Entry_t;
2038
2039/* values for Log Page 0 LogEntry LogEntryQualifier field */
2040#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000)
2041#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001)
2042#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002)
2043#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000)
2044#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF)
2045
2046typedef struct _MPI2_CONFIG_PAGE_LOG_0
2047{
2048 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
2049 U32 Reserved1; /* 0x08 */
2050 U32 Reserved2; /* 0x0C */
2051 U16 NumLogEntries; /* 0x10 */
2052 U16 Reserved3; /* 0x12 */
2053 MPI2_LOG_0_ENTRY LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /* 0x14 */
2054} MPI2_CONFIG_PAGE_LOG_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_LOG_0,
2055 Mpi2LogPage0_t, MPI2_POINTER pMpi2LogPage0_t;
2056
2057#define MPI2_LOG_0_PAGEVERSION (0x02)
2058
2059
2060/****************************************************************************
2061* RAID Config Page
2062****************************************************************************/
2063
2064/* RAID Page 0 */
2065
2066/*
2067 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2068 * one and check Header.ExtPageLength or NumPhys at runtime.
2069 */
2070#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
2071#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1)
2072#endif
2073
2074typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT
2075{
2076 U16 ElementFlags; /* 0x00 */
2077 U16 VolDevHandle; /* 0x02 */
2078 U8 HotSparePool; /* 0x04 */
2079 U8 PhysDiskNum; /* 0x05 */
2080 U16 PhysDiskDevHandle; /* 0x06 */
2081} MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
2082 MPI2_POINTER PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
2083 Mpi2RaidConfig0ConfigElement_t, MPI2_POINTER pMpi2RaidConfig0ConfigElement_t;
2084
2085/* values for the ElementFlags field */
2086#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F)
2087#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000)
2088#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001)
2089#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002)
2090#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003)
2091
2092
2093typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0
2094{
2095 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
2096 U8 NumHotSpares; /* 0x08 */
2097 U8 NumPhysDisks; /* 0x09 */
2098 U8 NumVolumes; /* 0x0A */
2099 U8 ConfigNum; /* 0x0B */
2100 U32 Flags; /* 0x0C */
2101 U8 ConfigGUID[24]; /* 0x10 */
2102 U32 Reserved1; /* 0x28 */
2103 U8 NumElements; /* 0x2C */
2104 U8 Reserved2; /* 0x2D */
2105 U16 Reserved3; /* 0x2E */
2106 MPI2_RAIDCONFIG0_CONFIG_ELEMENT ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /* 0x30 */
2107} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
2108 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
2109 Mpi2RaidConfigurationPage0_t, MPI2_POINTER pMpi2RaidConfigurationPage0_t;
2110
2111#define MPI2_RAIDCONFIG0_PAGEVERSION (0x00)
2112
2113/* values for RAID Configuration Page 0 Flags field */
2114#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001)
2115
2116
2117/****************************************************************************
2118* Driver Persistent Mapping Config Pages
2119****************************************************************************/
2120
2121/* Driver Persistent Mapping Page 0 */
2122
2123typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY
2124{
2125 U64 PhysicalIdentifier; /* 0x00 */
2126 U16 MappingInformation; /* 0x08 */
2127 U16 DeviceIndex; /* 0x0A */
2128 U32 PhysicalBitsMapping; /* 0x0C */
2129 U32 Reserved1; /* 0x10 */
2130} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
2131 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
2132 Mpi2DriverMap0Entry_t, MPI2_POINTER pMpi2DriverMap0Entry_t;
2133
2134typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0
2135{
2136 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
2137 MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /* 0x08 */
2138} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
2139 MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
2140 Mpi2DriverMappingPage0_t, MPI2_POINTER pMpi2DriverMappingPage0_t;
2141
2142#define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00)
2143
2144/* values for Driver Persistent Mapping Page 0 MappingInformation field */
2145#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0)
2146#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4)
2147#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F)
2148
2149
2150#endif
2151
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
new file mode 100644
index 000000000000..f1115f0f0eb2
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
@@ -0,0 +1,420 @@
1/*
2 * Copyright (c) 2000-2008 LSI Corporation.
3 *
4 *
5 * Name: mpi2_init.h
6 * Title: MPI SCSI initiator mode messages and structures
7 * Creation Date: June 23, 2006
8 *
9 * mpi2_init.h Version: 02.00.06
10 *
11 * Version History
12 * ---------------
13 *
14 * Date Version Description
15 * -------- -------- ------------------------------------------------------
16 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
17 * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t.
18 * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines.
19 * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention.
20 * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
21 * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t.
22 * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO
23 * Control field Task Attribute flags.
24 * Moved LUN field defines to mpi2.h becasue they are
25 * common to many structures.
26 * --------------------------------------------------------------------------
27 */
28
29#ifndef MPI2_INIT_H
30#define MPI2_INIT_H
31
32/*****************************************************************************
33*
34* SCSI Initiator Messages
35*
36*****************************************************************************/
37
38/****************************************************************************
39* SCSI IO messages and associated structures
40****************************************************************************/
41
42typedef struct
43{
44 U8 CDB[20]; /* 0x00 */
45 U32 PrimaryReferenceTag; /* 0x14 */
46 U16 PrimaryApplicationTag; /* 0x18 */
47 U16 PrimaryApplicationTagMask; /* 0x1A */
48 U32 TransferLength; /* 0x1C */
49} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32,
50 Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t;
51
52/* TBD: I don't think this is needed for MPI2/Gen2 */
53#if 0
54typedef struct
55{
56 U8 CDB[16]; /* 0x00 */
57 U32 DataLength; /* 0x10 */
58 U32 PrimaryReferenceTag; /* 0x14 */
59 U16 PrimaryApplicationTag; /* 0x18 */
60 U16 PrimaryApplicationTagMask; /* 0x1A */
61 U32 TransferLength; /* 0x1C */
62} MPI2_SCSI_IO32_CDB_EEDP16, MPI2_POINTER PTR_MPI2_SCSI_IO32_CDB_EEDP16,
63 Mpi2ScsiIo32CdbEedp16_t, MPI2_POINTER pMpi2ScsiIo32CdbEedp16_t;
64#endif
65
66typedef union
67{
68 U8 CDB32[32];
69 MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
70 MPI2_SGE_SIMPLE_UNION SGE;
71} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION,
72 Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t;
73
74/* SCSI IO Request Message */
75typedef struct _MPI2_SCSI_IO_REQUEST
76{
77 U16 DevHandle; /* 0x00 */
78 U8 ChainOffset; /* 0x02 */
79 U8 Function; /* 0x03 */
80 U16 Reserved1; /* 0x04 */
81 U8 Reserved2; /* 0x06 */
82 U8 MsgFlags; /* 0x07 */
83 U8 VP_ID; /* 0x08 */
84 U8 VF_ID; /* 0x09 */
85 U16 Reserved3; /* 0x0A */
86 U32 SenseBufferLowAddress; /* 0x0C */
87 U16 SGLFlags; /* 0x10 */
88 U8 SenseBufferLength; /* 0x12 */
89 U8 Reserved4; /* 0x13 */
90 U8 SGLOffset0; /* 0x14 */
91 U8 SGLOffset1; /* 0x15 */
92 U8 SGLOffset2; /* 0x16 */
93 U8 SGLOffset3; /* 0x17 */
94 U32 SkipCount; /* 0x18 */
95 U32 DataLength; /* 0x1C */
96 U32 BidirectionalDataLength; /* 0x20 */
97 U16 IoFlags; /* 0x24 */
98 U16 EEDPFlags; /* 0x26 */
99 U32 EEDPBlockSize; /* 0x28 */
100 U32 SecondaryReferenceTag; /* 0x2C */
101 U16 SecondaryApplicationTag; /* 0x30 */
102 U16 ApplicationTagTranslationMask; /* 0x32 */
103 U8 LUN[8]; /* 0x34 */
104 U32 Control; /* 0x3C */
105 MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
106 MPI2_SGE_IO_UNION SGL; /* 0x60 */
107} MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST,
108 Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t;
109
110/* SCSI IO MsgFlags bits */
111
112/* MsgFlags for SenseBufferAddressSpace */
113#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C)
114#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00)
115#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04)
116#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08)
117#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C)
118
119/* SCSI IO SGLFlags bits */
120
121/* base values for Data Location Address Space */
122#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C)
123#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00)
124#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04)
125#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08)
126#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C)
127
128/* base values for Type */
129#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03)
130#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00)
131#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01)
132#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02)
133
134/* shift values for each sub-field */
135#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12)
136#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8)
137#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4)
138#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0)
139
140/* SCSI IO IoFlags bits */
141
142/* Large CDB Address Space */
143#define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000)
144#define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000)
145#define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000)
146#define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000)
147#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000)
148
149#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000)
150#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800)
151#define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400)
152#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200)
153#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF)
154
155/* SCSI IO EEDPFlags bits */
156
157#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
158#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000)
159#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000)
160#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000)
161
162#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400)
163#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200)
164#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
165
166#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008)
167
168#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007)
169#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000)
170#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001)
171#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002)
172#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003)
173#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
174#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006)
175#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007)
176
177/* SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */
178
179/* SCSI IO Control bits */
180#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000)
181#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26)
182
183#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000)
184#define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000)
185#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000)
186#define MPI2_SCSIIO_CONTROL_READ (0x02000000)
187#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000)
188
189#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800)
190#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11)
191
192#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700)
193#define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000)
194#define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100)
195#define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200)
196#define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400)
197
198#define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0)
199#define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000)
200#define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040)
201#define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080)
202
203
204/* SCSI IO Error Reply Message */
205typedef struct _MPI2_SCSI_IO_REPLY
206{
207 U16 DevHandle; /* 0x00 */
208 U8 MsgLength; /* 0x02 */
209 U8 Function; /* 0x03 */
210 U16 Reserved1; /* 0x04 */
211 U8 Reserved2; /* 0x06 */
212 U8 MsgFlags; /* 0x07 */
213 U8 VP_ID; /* 0x08 */
214 U8 VF_ID; /* 0x09 */
215 U16 Reserved3; /* 0x0A */
216 U8 SCSIStatus; /* 0x0C */
217 U8 SCSIState; /* 0x0D */
218 U16 IOCStatus; /* 0x0E */
219 U32 IOCLogInfo; /* 0x10 */
220 U32 TransferCount; /* 0x14 */
221 U32 SenseCount; /* 0x18 */
222 U32 ResponseInfo; /* 0x1C */
223 U16 TaskTag; /* 0x20 */
224 U16 Reserved4; /* 0x22 */
225 U32 BidirectionalTransferCount; /* 0x24 */
226 U32 Reserved5; /* 0x28 */
227 U32 Reserved6; /* 0x2C */
228} MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY,
229 Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t;
230
231/* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */
232
233#define MPI2_SCSI_STATUS_GOOD (0x00)
234#define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02)
235#define MPI2_SCSI_STATUS_CONDITION_MET (0x04)
236#define MPI2_SCSI_STATUS_BUSY (0x08)
237#define MPI2_SCSI_STATUS_INTERMEDIATE (0x10)
238#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14)
239#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18)
240#define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /* obsolete */
241#define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28)
242#define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30)
243#define MPI2_SCSI_STATUS_TASK_ABORTED (0x40)
244
245/* SCSI IO Reply SCSIState flags */
246
247#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10)
248#define MPI2_SCSI_STATE_TERMINATED (0x08)
249#define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04)
250#define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02)
251#define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01)
252
253#define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF)
254
255
256/****************************************************************************
257* SCSI Task Management messages
258****************************************************************************/
259
260/* SCSI Task Management Request Message */
261typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST
262{
263 U16 DevHandle; /* 0x00 */
264 U8 ChainOffset; /* 0x02 */
265 U8 Function; /* 0x03 */
266 U8 Reserved1; /* 0x04 */
267 U8 TaskType; /* 0x05 */
268 U8 Reserved2; /* 0x06 */
269 U8 MsgFlags; /* 0x07 */
270 U8 VP_ID; /* 0x08 */
271 U8 VF_ID; /* 0x09 */
272 U16 Reserved3; /* 0x0A */
273 U8 LUN[8]; /* 0x0C */
274 U32 Reserved4[7]; /* 0x14 */
275 U16 TaskMID; /* 0x30 */
276 U16 Reserved5; /* 0x32 */
277} MPI2_SCSI_TASK_MANAGE_REQUEST,
278 MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REQUEST,
279 Mpi2SCSITaskManagementRequest_t,
280 MPI2_POINTER pMpi2SCSITaskManagementRequest_t;
281
282/* TaskType values */
283
284#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01)
285#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02)
286#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03)
287#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
288#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
289#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
290#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08)
291#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09)
292#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION (0x0A)
293
294/* MsgFlags bits */
295
296#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18)
297#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00)
298#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08)
299#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10)
300
301#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01)
302
303
304
305/* SCSI Task Management Reply Message */
306typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY
307{
308 U16 DevHandle; /* 0x00 */
309 U8 MsgLength; /* 0x02 */
310 U8 Function; /* 0x03 */
311 U8 ResponseCode; /* 0x04 */
312 U8 TaskType; /* 0x05 */
313 U8 Reserved1; /* 0x06 */
314 U8 MsgFlags; /* 0x07 */
315 U8 VP_ID; /* 0x08 */
316 U8 VF_ID; /* 0x09 */
317 U16 Reserved2; /* 0x0A */
318 U16 Reserved3; /* 0x0C */
319 U16 IOCStatus; /* 0x0E */
320 U32 IOCLogInfo; /* 0x10 */
321 U32 TerminationCount; /* 0x14 */
322} MPI2_SCSI_TASK_MANAGE_REPLY,
323 MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REPLY,
324 Mpi2SCSITaskManagementReply_t, MPI2_POINTER pMpi2SCSIManagementReply_t;
325
326/* ResponseCode values */
327
328#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00)
329#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02)
330#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04)
331#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05)
332#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08)
333#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09)
334#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80)
335
336
337/****************************************************************************
338* SCSI Enclosure Processor messages
339****************************************************************************/
340
341/* SCSI Enclosure Processor Request Message */
342typedef struct _MPI2_SEP_REQUEST
343{
344 U16 DevHandle; /* 0x00 */
345 U8 ChainOffset; /* 0x02 */
346 U8 Function; /* 0x03 */
347 U8 Action; /* 0x04 */
348 U8 Flags; /* 0x05 */
349 U8 Reserved1; /* 0x06 */
350 U8 MsgFlags; /* 0x07 */
351 U8 VP_ID; /* 0x08 */
352 U8 VF_ID; /* 0x09 */
353 U16 Reserved2; /* 0x0A */
354 U32 SlotStatus; /* 0x0C */
355 U32 Reserved3; /* 0x10 */
356 U32 Reserved4; /* 0x14 */
357 U32 Reserved5; /* 0x18 */
358 U16 Slot; /* 0x1C */
359 U16 EnclosureHandle; /* 0x1E */
360} MPI2_SEP_REQUEST, MPI2_POINTER PTR_MPI2_SEP_REQUEST,
361 Mpi2SepRequest_t, MPI2_POINTER pMpi2SepRequest_t;
362
363/* Action defines */
364#define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00)
365#define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01)
366
367/* Flags defines */
368#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00)
369#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01)
370
371/* SlotStatus defines */
372#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000)
373#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
374#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
375#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100)
376#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080)
377#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040)
378#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004)
379#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002)
380#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001)
381
382
383/* SCSI Enclosure Processor Reply Message */
384typedef struct _MPI2_SEP_REPLY
385{
386 U16 DevHandle; /* 0x00 */
387 U8 MsgLength; /* 0x02 */
388 U8 Function; /* 0x03 */
389 U8 Action; /* 0x04 */
390 U8 Flags; /* 0x05 */
391 U8 Reserved1; /* 0x06 */
392 U8 MsgFlags; /* 0x07 */
393 U8 VP_ID; /* 0x08 */
394 U8 VF_ID; /* 0x09 */
395 U16 Reserved2; /* 0x0A */
396 U16 Reserved3; /* 0x0C */
397 U16 IOCStatus; /* 0x0E */
398 U32 IOCLogInfo; /* 0x10 */
399 U32 SlotStatus; /* 0x14 */
400 U32 Reserved4; /* 0x18 */
401 U16 Slot; /* 0x1C */
402 U16 EnclosureHandle; /* 0x1E */
403} MPI2_SEP_REPLY, MPI2_POINTER PTR_MPI2_SEP_REPLY,
404 Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t;
405
406/* SlotStatus defines */
407#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000)
408#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
409#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
410#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100)
411#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080)
412#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040)
413#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004)
414#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002)
415#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001)
416
417
418#endif
419
420
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
new file mode 100644
index 000000000000..8c5d81870c03
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
@@ -0,0 +1,1295 @@
1/*
2 * Copyright (c) 2000-2009 LSI Corporation.
3 *
4 *
5 * Name: mpi2_ioc.h
6 * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
7 * Creation Date: October 11, 2006
8 *
9 * mpi2_ioc.h Version: 02.00.10
10 *
11 * Version History
12 * ---------------
13 *
14 * Date Version Description
15 * -------- -------- ------------------------------------------------------
16 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
17 * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to
18 * MaxTargets.
19 * Added TotalImageSize field to FWDownload Request.
20 * Added reserved words to FWUpload Request.
21 * 06-26-07 02.00.02 Added IR Configuration Change List Event.
22 * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit
23 * request and replaced it with
24 * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
25 * Replaced the MinReplyQueueDepth field of the IOCFacts
26 * reply with MaxReplyDescriptorPostQueueDepth.
27 * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
28 * depth for the Reply Descriptor Post Queue.
29 * Added SASAddress field to Initiator Device Table
30 * Overflow Event data.
31 * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
32 * for SAS Initiator Device Status Change Event data.
33 * Modified Reason Code defines for SAS Topology Change
34 * List Event data, including adding a bit for PHY Vacant
35 * status, and adding a mask for the Reason Code.
36 * Added define for
37 * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
38 * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
39 * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of
40 * the IOCFacts Reply.
41 * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
42 * Moved MPI2_VERSION_UNION to mpi2.h.
43 * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
44 * instead of enables, and added SASBroadcastPrimitiveMasks
45 * field.
46 * Added Log Entry Added Event and related structure.
47 * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
48 * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
49 * Added MaxVolumes and MaxPersistentEntries fields to
50 * IOCFacts reply.
51 * Added ProtocalFlags and IOCCapabilities fields to
52 * MPI2_FW_IMAGE_HEADER.
53 * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
54 * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
55 * a U16 (from a U32).
56 * Removed extra 's' from EventMasks name.
57 * 06-27-08 02.00.08 Fixed an offset in a comment.
58 * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
59 * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
60 * renamed MinReplyFrameSize to ReplyFrameSize.
61 * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
62 * Added two new RAIDOperation values for Integrated RAID
63 * Operations Status Event data.
64 * Added four new IR Configuration Change List Event data
65 * ReasonCode values.
66 * Added two new ReasonCode defines for SAS Device Status
67 * Change Event data.
68 * Added three new DiscoveryStatus bits for the SAS
69 * Discovery event data.
70 * Added Multiplexing Status Change bit to the PhyStatus
71 * field of the SAS Topology Change List event data.
72 * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
73 * BootFlags are now product-specific.
74 * Added defines for the indivdual signature bytes
75 * for MPI2_INIT_IMAGE_FOOTER.
76 * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
77 * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
78 * define.
79 * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
80 * define.
81 * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
82 * --------------------------------------------------------------------------
83 */
84
85#ifndef MPI2_IOC_H
86#define MPI2_IOC_H
87
88/*****************************************************************************
89*
90* IOC Messages
91*
92*****************************************************************************/
93
94/****************************************************************************
95* IOCInit message
96****************************************************************************/
97
98/* IOCInit Request message */
99typedef struct _MPI2_IOC_INIT_REQUEST
100{
101 U8 WhoInit; /* 0x00 */
102 U8 Reserved1; /* 0x01 */
103 U8 ChainOffset; /* 0x02 */
104 U8 Function; /* 0x03 */
105 U16 Reserved2; /* 0x04 */
106 U8 Reserved3; /* 0x06 */
107 U8 MsgFlags; /* 0x07 */
108 U8 VP_ID; /* 0x08 */
109 U8 VF_ID; /* 0x09 */
110 U16 Reserved4; /* 0x0A */
111 U16 MsgVersion; /* 0x0C */
112 U16 HeaderVersion; /* 0x0E */
113 U32 Reserved5; /* 0x10 */
114 U32 Reserved6; /* 0x14 */
115 U16 Reserved7; /* 0x18 */
116 U16 SystemRequestFrameSize; /* 0x1A */
117 U16 ReplyDescriptorPostQueueDepth; /* 0x1C */
118 U16 ReplyFreeQueueDepth; /* 0x1E */
119 U32 SenseBufferAddressHigh; /* 0x20 */
120 U32 SystemReplyAddressHigh; /* 0x24 */
121 U64 SystemRequestFrameBaseAddress; /* 0x28 */
122 U64 ReplyDescriptorPostQueueAddress;/* 0x30 */
123 U64 ReplyFreeQueueAddress; /* 0x38 */
124 U64 TimeStamp; /* 0x40 */
125} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST,
126 Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t;
127
128/* WhoInit values */
129#define MPI2_WHOINIT_NOT_INITIALIZED (0x00)
130#define MPI2_WHOINIT_SYSTEM_BIOS (0x01)
131#define MPI2_WHOINIT_ROM_BIOS (0x02)
132#define MPI2_WHOINIT_PCI_PEER (0x03)
133#define MPI2_WHOINIT_HOST_DRIVER (0x04)
134#define MPI2_WHOINIT_MANUFACTURER (0x05)
135
136/* MsgVersion */
137#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00)
138#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8)
139#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF)
140#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0)
141
142/* HeaderVersion */
143#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00)
144#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8)
145#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF)
146#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0)
147
148/* minimum depth for the Reply Descriptor Post Queue */
149#define MPI2_RDPQ_DEPTH_MIN (16)
150
151
152/* IOCInit Reply message */
153typedef struct _MPI2_IOC_INIT_REPLY
154{
155 U8 WhoInit; /* 0x00 */
156 U8 Reserved1; /* 0x01 */
157 U8 MsgLength; /* 0x02 */
158 U8 Function; /* 0x03 */
159 U16 Reserved2; /* 0x04 */
160 U8 Reserved3; /* 0x06 */
161 U8 MsgFlags; /* 0x07 */
162 U8 VP_ID; /* 0x08 */
163 U8 VF_ID; /* 0x09 */
164 U16 Reserved4; /* 0x0A */
165 U16 Reserved5; /* 0x0C */
166 U16 IOCStatus; /* 0x0E */
167 U32 IOCLogInfo; /* 0x10 */
168} MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY,
169 Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t;
170
171
172/****************************************************************************
173* IOCFacts message
174****************************************************************************/
175
176/* IOCFacts Request message */
177typedef struct _MPI2_IOC_FACTS_REQUEST
178{
179 U16 Reserved1; /* 0x00 */
180 U8 ChainOffset; /* 0x02 */
181 U8 Function; /* 0x03 */
182 U16 Reserved2; /* 0x04 */
183 U8 Reserved3; /* 0x06 */
184 U8 MsgFlags; /* 0x07 */
185 U8 VP_ID; /* 0x08 */
186 U8 VF_ID; /* 0x09 */
187 U16 Reserved4; /* 0x0A */
188} MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST,
189 Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t;
190
191
192/* IOCFacts Reply message */
193typedef struct _MPI2_IOC_FACTS_REPLY
194{
195 U16 MsgVersion; /* 0x00 */
196 U8 MsgLength; /* 0x02 */
197 U8 Function; /* 0x03 */
198 U16 HeaderVersion; /* 0x04 */
199 U8 IOCNumber; /* 0x06 */
200 U8 MsgFlags; /* 0x07 */
201 U8 VP_ID; /* 0x08 */
202 U8 VF_ID; /* 0x09 */
203 U16 Reserved1; /* 0x0A */
204 U16 IOCExceptions; /* 0x0C */
205 U16 IOCStatus; /* 0x0E */
206 U32 IOCLogInfo; /* 0x10 */
207 U8 MaxChainDepth; /* 0x14 */
208 U8 WhoInit; /* 0x15 */
209 U8 NumberOfPorts; /* 0x16 */
210 U8 Reserved2; /* 0x17 */
211 U16 RequestCredit; /* 0x18 */
212 U16 ProductID; /* 0x1A */
213 U32 IOCCapabilities; /* 0x1C */
214 MPI2_VERSION_UNION FWVersion; /* 0x20 */
215 U16 IOCRequestFrameSize; /* 0x24 */
216 U16 Reserved3; /* 0x26 */
217 U16 MaxInitiators; /* 0x28 */
218 U16 MaxTargets; /* 0x2A */
219 U16 MaxSasExpanders; /* 0x2C */
220 U16 MaxEnclosures; /* 0x2E */
221 U16 ProtocolFlags; /* 0x30 */
222 U16 HighPriorityCredit; /* 0x32 */
223 U16 MaxReplyDescriptorPostQueueDepth; /* 0x34 */
224 U8 ReplyFrameSize; /* 0x36 */
225 U8 MaxVolumes; /* 0x37 */
226 U16 MaxDevHandle; /* 0x38 */
227 U16 MaxPersistentEntries; /* 0x3A */
228 U32 Reserved4; /* 0x3C */
229} MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY,
230 Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t;
231
232/* MsgVersion */
233#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00)
234#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8)
235#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF)
236#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0)
237
238/* HeaderVersion */
239#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00)
240#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8)
241#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF)
242#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0)
243
244/* IOCExceptions */
245#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100)
246
247#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0)
248#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000)
249#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020)
250#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040)
251#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060)
252
253#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010)
254#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008)
255#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
256#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
257#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001)
258
259/* defines for WhoInit field are after the IOCInit Request */
260
261/* ProductID field uses MPI2_FW_HEADER_PID_ */
262
263/* IOCCapabilities */
264#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000)
265#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000)
266#define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800)
267#define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100)
268#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080)
269#define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040)
270#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
271#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
272#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
273
274/* ProtocolFlags */
275#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001)
276#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002)
277
278
279/****************************************************************************
280* PortFacts message
281****************************************************************************/
282
283/* PortFacts Request message */
284typedef struct _MPI2_PORT_FACTS_REQUEST
285{
286 U16 Reserved1; /* 0x00 */
287 U8 ChainOffset; /* 0x02 */
288 U8 Function; /* 0x03 */
289 U16 Reserved2; /* 0x04 */
290 U8 PortNumber; /* 0x06 */
291 U8 MsgFlags; /* 0x07 */
292 U8 VP_ID; /* 0x08 */
293 U8 VF_ID; /* 0x09 */
294 U16 Reserved3; /* 0x0A */
295} MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST,
296 Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t;
297
298/* PortFacts Reply message */
299typedef struct _MPI2_PORT_FACTS_REPLY
300{
301 U16 Reserved1; /* 0x00 */
302 U8 MsgLength; /* 0x02 */
303 U8 Function; /* 0x03 */
304 U16 Reserved2; /* 0x04 */
305 U8 PortNumber; /* 0x06 */
306 U8 MsgFlags; /* 0x07 */
307 U8 VP_ID; /* 0x08 */
308 U8 VF_ID; /* 0x09 */
309 U16 Reserved3; /* 0x0A */
310 U16 Reserved4; /* 0x0C */
311 U16 IOCStatus; /* 0x0E */
312 U32 IOCLogInfo; /* 0x10 */
313 U8 Reserved5; /* 0x14 */
314 U8 PortType; /* 0x15 */
315 U16 Reserved6; /* 0x16 */
316 U16 MaxPostedCmdBuffers; /* 0x18 */
317 U16 Reserved7; /* 0x1A */
318} MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY,
319 Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t;
320
321/* PortType values */
322#define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00)
323#define MPI2_PORTFACTS_PORTTYPE_FC (0x10)
324#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20)
325#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30)
326#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31)
327
328
329/****************************************************************************
330* PortEnable message
331****************************************************************************/
332
333/* PortEnable Request message */
334typedef struct _MPI2_PORT_ENABLE_REQUEST
335{
336 U16 Reserved1; /* 0x00 */
337 U8 ChainOffset; /* 0x02 */
338 U8 Function; /* 0x03 */
339 U8 Reserved2; /* 0x04 */
340 U8 PortFlags; /* 0x05 */
341 U8 Reserved3; /* 0x06 */
342 U8 MsgFlags; /* 0x07 */
343 U8 VP_ID; /* 0x08 */
344 U8 VF_ID; /* 0x09 */
345 U16 Reserved4; /* 0x0A */
346} MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST,
347 Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t;
348
349
350/* PortEnable Reply message */
351typedef struct _MPI2_PORT_ENABLE_REPLY
352{
353 U16 Reserved1; /* 0x00 */
354 U8 MsgLength; /* 0x02 */
355 U8 Function; /* 0x03 */
356 U8 Reserved2; /* 0x04 */
357 U8 PortFlags; /* 0x05 */
358 U8 Reserved3; /* 0x06 */
359 U8 MsgFlags; /* 0x07 */
360 U8 VP_ID; /* 0x08 */
361 U8 VF_ID; /* 0x09 */
362 U16 Reserved4; /* 0x0A */
363 U16 Reserved5; /* 0x0C */
364 U16 IOCStatus; /* 0x0E */
365 U32 IOCLogInfo; /* 0x10 */
366} MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY,
367 Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t;
368
369
370/****************************************************************************
371* EventNotification message
372****************************************************************************/
373
374/* EventNotification Request message */
375#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4)
376
377typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST
378{
379 U16 Reserved1; /* 0x00 */
380 U8 ChainOffset; /* 0x02 */
381 U8 Function; /* 0x03 */
382 U16 Reserved2; /* 0x04 */
383 U8 Reserved3; /* 0x06 */
384 U8 MsgFlags; /* 0x07 */
385 U8 VP_ID; /* 0x08 */
386 U8 VF_ID; /* 0x09 */
387 U16 Reserved4; /* 0x0A */
388 U32 Reserved5; /* 0x0C */
389 U32 Reserved6; /* 0x10 */
390 U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */
391 U16 SASBroadcastPrimitiveMasks; /* 0x24 */
392 U16 Reserved7; /* 0x26 */
393 U32 Reserved8; /* 0x28 */
394} MPI2_EVENT_NOTIFICATION_REQUEST,
395 MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
396 Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t;
397
398
399/* EventNotification Reply message */
400typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
401{
402 U16 EventDataLength; /* 0x00 */
403 U8 MsgLength; /* 0x02 */
404 U8 Function; /* 0x03 */
405 U16 Reserved1; /* 0x04 */
406 U8 AckRequired; /* 0x06 */
407 U8 MsgFlags; /* 0x07 */
408 U8 VP_ID; /* 0x08 */
409 U8 VF_ID; /* 0x09 */
410 U16 Reserved2; /* 0x0A */
411 U16 Reserved3; /* 0x0C */
412 U16 IOCStatus; /* 0x0E */
413 U32 IOCLogInfo; /* 0x10 */
414 U16 Event; /* 0x14 */
415 U16 Reserved4; /* 0x16 */
416 U32 EventContext; /* 0x18 */
417 U32 EventData[1]; /* 0x1C */
418} MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY,
419 Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t;
420
421/* AckRequired */
422#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00)
423#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01)
424
425/* Event */
426#define MPI2_EVENT_LOG_DATA (0x0001)
427#define MPI2_EVENT_STATE_CHANGE (0x0002)
428#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005)
429#define MPI2_EVENT_EVENT_CHANGE (0x000A)
430#define MPI2_EVENT_TASK_SET_FULL (0x000E)
431#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F)
432#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014)
433#define MPI2_EVENT_SAS_DISCOVERY (0x0016)
434#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017)
435#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018)
436#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019)
437#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C)
438#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D)
439#define MPI2_EVENT_IR_VOLUME (0x001E)
440#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F)
441#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020)
442#define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021)
443
444
445/* Log Entry Added Event data */
446
447/* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */
448#define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C)
449
450typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED
451{
452 U64 TimeStamp; /* 0x00 */
453 U32 Reserved1; /* 0x08 */
454 U16 LogSequence; /* 0x0C */
455 U16 LogEntryQualifier; /* 0x0E */
456 U8 VP_ID; /* 0x10 */
457 U8 VF_ID; /* 0x11 */
458 U16 Reserved2; /* 0x12 */
459 U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */
460} MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
461 MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
462 Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t;
463
464/* Hard Reset Received Event data */
465
466typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED
467{
468 U8 Reserved1; /* 0x00 */
469 U8 Port; /* 0x01 */
470 U16 Reserved2; /* 0x02 */
471} MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
472 MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
473 Mpi2EventDataHardResetReceived_t,
474 MPI2_POINTER pMpi2EventDataHardResetReceived_t;
475
476/* Task Set Full Event data */
477
478typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL
479{
480 U16 DevHandle; /* 0x00 */
481 U16 CurrentDepth; /* 0x02 */
482} MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL,
483 Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t;
484
485
486/* SAS Device Status Change Event data */
487
488typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
489{
490 U16 TaskTag; /* 0x00 */
491 U8 ReasonCode; /* 0x02 */
492 U8 Reserved1; /* 0x03 */
493 U8 ASC; /* 0x04 */
494 U8 ASCQ; /* 0x05 */
495 U16 DevHandle; /* 0x06 */
496 U32 Reserved2; /* 0x08 */
497 U64 SASAddress; /* 0x0C */
498 U8 LUN[8]; /* 0x14 */
499} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
500 MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
501 Mpi2EventDataSasDeviceStatusChange_t,
502 MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t;
503
504/* SAS Device Status Change Event data ReasonCode values */
505#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
506#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
507#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
508#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09)
509#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A)
510#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
511#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
512#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
513#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E)
514#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F)
515#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10)
516
517
518/* Integrated RAID Operation Status Event data */
519
520typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS
521{
522 U16 VolDevHandle; /* 0x00 */
523 U16 Reserved1; /* 0x02 */
524 U8 RAIDOperation; /* 0x04 */
525 U8 PercentComplete; /* 0x05 */
526 U16 Reserved2; /* 0x06 */
527 U32 Resereved3; /* 0x08 */
528} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
529 MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
530 Mpi2EventDataIrOperationStatus_t,
531 MPI2_POINTER pMpi2EventDataIrOperationStatus_t;
532
533/* Integrated RAID Operation Status Event data RAIDOperation values */
534#define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00)
535#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01)
536#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02)
537#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03)
538#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04)
539
540
541/* Integrated RAID Volume Event data */
542
543typedef struct _MPI2_EVENT_DATA_IR_VOLUME
544{
545 U16 VolDevHandle; /* 0x00 */
546 U8 ReasonCode; /* 0x02 */
547 U8 Reserved1; /* 0x03 */
548 U32 NewValue; /* 0x04 */
549 U32 PreviousValue; /* 0x08 */
550} MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME,
551 Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t;
552
553/* Integrated RAID Volume Event data ReasonCode values */
554#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01)
555#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02)
556#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03)
557
558
559/* Integrated RAID Physical Disk Event data */
560
561typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK
562{
563 U16 Reserved1; /* 0x00 */
564 U8 ReasonCode; /* 0x02 */
565 U8 PhysDiskNum; /* 0x03 */
566 U16 PhysDiskDevHandle; /* 0x04 */
567 U16 Reserved2; /* 0x06 */
568 U16 Slot; /* 0x08 */
569 U16 EnclosureHandle; /* 0x0A */
570 U32 NewValue; /* 0x0C */
571 U32 PreviousValue; /* 0x10 */
572} MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
573 MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
574 Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t;
575
576/* Integrated RAID Physical Disk Event data ReasonCode values */
577#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01)
578#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02)
579#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03)
580
581
582/* Integrated RAID Configuration Change List Event data */
583
584/*
585 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
586 * one and check NumElements at runtime.
587 */
588#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
589#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1)
590#endif
591
592typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT
593{
594 U16 ElementFlags; /* 0x00 */
595 U16 VolDevHandle; /* 0x02 */
596 U8 ReasonCode; /* 0x04 */
597 U8 PhysDiskNum; /* 0x05 */
598 U16 PhysDiskDevHandle; /* 0x06 */
599} MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT,
600 Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t;
601
602/* IR Configuration Change List Event data ElementFlags values */
603#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F)
604#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000)
605#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001)
606#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002)
607
608/* IR Configuration Change List Event data ReasonCode values */
609#define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01)
610#define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02)
611#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03)
612#define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04)
613#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05)
614#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06)
615#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07)
616#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08)
617#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09)
618
619typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST
620{
621 U8 NumElements; /* 0x00 */
622 U8 Reserved1; /* 0x01 */
623 U8 Reserved2; /* 0x02 */
624 U8 ConfigNum; /* 0x03 */
625 U32 Flags; /* 0x04 */
626 MPI2_EVENT_IR_CONFIG_ELEMENT ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT]; /* 0x08 */
627} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
628 MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
629 Mpi2EventDataIrConfigChangeList_t,
630 MPI2_POINTER pMpi2EventDataIrConfigChangeList_t;
631
632/* IR Configuration Change List Event data Flags values */
633#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001)
634
635
636/* SAS Discovery Event data */
637
638typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY
639{
640 U8 Flags; /* 0x00 */
641 U8 ReasonCode; /* 0x01 */
642 U8 PhysicalPort; /* 0x02 */
643 U8 Reserved1; /* 0x03 */
644 U32 DiscoveryStatus; /* 0x04 */
645} MPI2_EVENT_DATA_SAS_DISCOVERY,
646 MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY,
647 Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t;
648
649/* SAS Discovery Event data Flags values */
650#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02)
651#define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01)
652
653/* SAS Discovery Event data ReasonCode values */
654#define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01)
655#define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02)
656
657/* SAS Discovery Event data DiscoveryStatus values */
658#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
659#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000)
660#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000)
661#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
662#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000)
663#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
664#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
665#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000)
666#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
667#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800)
668#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400)
669#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200)
670#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100)
671#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080)
672#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040)
673#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020)
674#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010)
675#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004)
676#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002)
677#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001)
678
679
680/* SAS Broadcast Primitive Event data */
681
682typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE
683{
684 U8 PhyNum; /* 0x00 */
685 U8 Port; /* 0x01 */
686 U8 PortWidth; /* 0x02 */
687 U8 Primitive; /* 0x03 */
688} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
689 MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
690 Mpi2EventDataSasBroadcastPrimitive_t,
691 MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t;
692
693/* defines for the Primitive field */
694#define MPI2_EVENT_PRIMITIVE_CHANGE (0x01)
695#define MPI2_EVENT_PRIMITIVE_SES (0x02)
696#define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03)
697#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04)
698#define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05)
699#define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06)
700#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07)
701#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08)
702
703
704/* SAS Initiator Device Status Change Event data */
705
706typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
707{
708 U8 ReasonCode; /* 0x00 */
709 U8 PhysicalPort; /* 0x01 */
710 U16 DevHandle; /* 0x02 */
711 U64 SASAddress; /* 0x04 */
712} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
713 MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
714 Mpi2EventDataSasInitDevStatusChange_t,
715 MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t;
716
717/* SAS Initiator Device Status Change event ReasonCode values */
718#define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01)
719#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02)
720
721
722/* SAS Initiator Device Table Overflow Event data */
723
724typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
725{
726 U16 MaxInit; /* 0x00 */
727 U16 CurrentInit; /* 0x02 */
728 U64 SASAddress; /* 0x04 */
729} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
730 MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
731 Mpi2EventDataSasInitTableOverflow_t,
732 MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t;
733
734
735/* SAS Topology Change List Event data */
736
737/*
738 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
739 * one and check NumEntries at runtime.
740 */
741#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
742#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1)
743#endif
744
745typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY
746{
747 U16 AttachedDevHandle; /* 0x00 */
748 U8 LinkRate; /* 0x02 */
749 U8 PhyStatus; /* 0x03 */
750} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY,
751 Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t;
752
753typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST
754{
755 U16 EnclosureHandle; /* 0x00 */
756 U16 ExpanderDevHandle; /* 0x02 */
757 U8 NumPhys; /* 0x04 */
758 U8 Reserved1; /* 0x05 */
759 U16 Reserved2; /* 0x06 */
760 U8 NumEntries; /* 0x08 */
761 U8 StartPhyNum; /* 0x09 */
762 U8 ExpStatus; /* 0x0A */
763 U8 PhysicalPort; /* 0x0B */
764 MPI2_EVENT_SAS_TOPO_PHY_ENTRY PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/
765} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
766 MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
767 Mpi2EventDataSasTopologyChangeList_t,
768 MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t;
769
770/* values for the ExpStatus field */
771#define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01)
772#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02)
773#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03)
774#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04)
775
776/* defines for the LinkRate field */
777#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0)
778#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4)
779#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F)
780#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0)
781
782#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00)
783#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01)
784#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02)
785#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03)
786#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04)
787#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05)
788#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08)
789#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09)
790#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A)
791
792/* values for the PhyStatus field */
793#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80)
794#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10)
795/* values for the PhyStatus ReasonCode sub-field */
796#define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F)
797#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01)
798#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02)
799#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03)
800#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04)
801#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05)
802
803
804/* SAS Enclosure Device Status Change Event data */
805
806typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE
807{
808 U16 EnclosureHandle; /* 0x00 */
809 U8 ReasonCode; /* 0x02 */
810 U8 PhysicalPort; /* 0x03 */
811 U64 EnclosureLogicalID; /* 0x04 */
812 U16 NumSlots; /* 0x0C */
813 U16 StartSlot; /* 0x0E */
814 U32 PhyBits; /* 0x10 */
815} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
816 MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
817 Mpi2EventDataSasEnclDevStatusChange_t,
818 MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t;
819
820/* SAS Enclosure Device Status Change event ReasonCode values */
821#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01)
822#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02)
823
824
825/****************************************************************************
826* EventAck message
827****************************************************************************/
828
829/* EventAck Request message */
830typedef struct _MPI2_EVENT_ACK_REQUEST
831{
832 U16 Reserved1; /* 0x00 */
833 U8 ChainOffset; /* 0x02 */
834 U8 Function; /* 0x03 */
835 U16 Reserved2; /* 0x04 */
836 U8 Reserved3; /* 0x06 */
837 U8 MsgFlags; /* 0x07 */
838 U8 VP_ID; /* 0x08 */
839 U8 VF_ID; /* 0x09 */
840 U16 Reserved4; /* 0x0A */
841 U16 Event; /* 0x0C */
842 U16 Reserved5; /* 0x0E */
843 U32 EventContext; /* 0x10 */
844} MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST,
845 Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t;
846
847
848/* EventAck Reply message */
849typedef struct _MPI2_EVENT_ACK_REPLY
850{
851 U16 Reserved1; /* 0x00 */
852 U8 MsgLength; /* 0x02 */
853 U8 Function; /* 0x03 */
854 U16 Reserved2; /* 0x04 */
855 U8 Reserved3; /* 0x06 */
856 U8 MsgFlags; /* 0x07 */
857 U8 VP_ID; /* 0x08 */
858 U8 VF_ID; /* 0x09 */
859 U16 Reserved4; /* 0x0A */
860 U16 Reserved5; /* 0x0C */
861 U16 IOCStatus; /* 0x0E */
862 U32 IOCLogInfo; /* 0x10 */
863} MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY,
864 Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t;
865
866
867/****************************************************************************
868* FWDownload message
869****************************************************************************/
870
871/* FWDownload Request message */
872typedef struct _MPI2_FW_DOWNLOAD_REQUEST
873{
874 U8 ImageType; /* 0x00 */
875 U8 Reserved1; /* 0x01 */
876 U8 ChainOffset; /* 0x02 */
877 U8 Function; /* 0x03 */
878 U16 Reserved2; /* 0x04 */
879 U8 Reserved3; /* 0x06 */
880 U8 MsgFlags; /* 0x07 */
881 U8 VP_ID; /* 0x08 */
882 U8 VF_ID; /* 0x09 */
883 U16 Reserved4; /* 0x0A */
884 U32 TotalImageSize; /* 0x0C */
885 U32 Reserved5; /* 0x10 */
886 MPI2_MPI_SGE_UNION SGL; /* 0x14 */
887} MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST,
888 Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest;
889
890#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01)
891
892#define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01)
893#define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02)
894#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06)
895#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07)
896#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08)
897#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09)
898#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
899
900/* FWDownload TransactionContext Element */
901typedef struct _MPI2_FW_DOWNLOAD_TCSGE
902{
903 U8 Reserved1; /* 0x00 */
904 U8 ContextSize; /* 0x01 */
905 U8 DetailsLength; /* 0x02 */
906 U8 Flags; /* 0x03 */
907 U32 Reserved2; /* 0x04 */
908 U32 ImageOffset; /* 0x08 */
909 U32 ImageSize; /* 0x0C */
910} MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE,
911 Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t;
912
913/* FWDownload Reply message */
914typedef struct _MPI2_FW_DOWNLOAD_REPLY
915{
916 U8 ImageType; /* 0x00 */
917 U8 Reserved1; /* 0x01 */
918 U8 MsgLength; /* 0x02 */
919 U8 Function; /* 0x03 */
920 U16 Reserved2; /* 0x04 */
921 U8 Reserved3; /* 0x06 */
922 U8 MsgFlags; /* 0x07 */
923 U8 VP_ID; /* 0x08 */
924 U8 VF_ID; /* 0x09 */
925 U16 Reserved4; /* 0x0A */
926 U16 Reserved5; /* 0x0C */
927 U16 IOCStatus; /* 0x0E */
928 U32 IOCLogInfo; /* 0x10 */
929} MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY,
930 Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t;
931
932
933/****************************************************************************
934* FWUpload message
935****************************************************************************/
936
937/* FWUpload Request message */
938typedef struct _MPI2_FW_UPLOAD_REQUEST
939{
940 U8 ImageType; /* 0x00 */
941 U8 Reserved1; /* 0x01 */
942 U8 ChainOffset; /* 0x02 */
943 U8 Function; /* 0x03 */
944 U16 Reserved2; /* 0x04 */
945 U8 Reserved3; /* 0x06 */
946 U8 MsgFlags; /* 0x07 */
947 U8 VP_ID; /* 0x08 */
948 U8 VF_ID; /* 0x09 */
949 U16 Reserved4; /* 0x0A */
950 U32 Reserved5; /* 0x0C */
951 U32 Reserved6; /* 0x10 */
952 MPI2_MPI_SGE_UNION SGL; /* 0x14 */
953} MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST,
954 Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t;
955
956#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00)
957#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01)
958#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02)
959#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05)
960#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06)
961#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07)
962#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08)
963#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09)
964#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A)
965#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
966
967typedef struct _MPI2_FW_UPLOAD_TCSGE
968{
969 U8 Reserved1; /* 0x00 */
970 U8 ContextSize; /* 0x01 */
971 U8 DetailsLength; /* 0x02 */
972 U8 Flags; /* 0x03 */
973 U32 Reserved2; /* 0x04 */
974 U32 ImageOffset; /* 0x08 */
975 U32 ImageSize; /* 0x0C */
976} MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE,
977 Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t;
978
979/* FWUpload Reply message */
980typedef struct _MPI2_FW_UPLOAD_REPLY
981{
982 U8 ImageType; /* 0x00 */
983 U8 Reserved1; /* 0x01 */
984 U8 MsgLength; /* 0x02 */
985 U8 Function; /* 0x03 */
986 U16 Reserved2; /* 0x04 */
987 U8 Reserved3; /* 0x06 */
988 U8 MsgFlags; /* 0x07 */
989 U8 VP_ID; /* 0x08 */
990 U8 VF_ID; /* 0x09 */
991 U16 Reserved4; /* 0x0A */
992 U16 Reserved5; /* 0x0C */
993 U16 IOCStatus; /* 0x0E */
994 U32 IOCLogInfo; /* 0x10 */
995 U32 ActualImageSize; /* 0x14 */
996} MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY,
997 Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t;
998
999
1000/* FW Image Header */
1001typedef struct _MPI2_FW_IMAGE_HEADER
1002{
1003 U32 Signature; /* 0x00 */
1004 U32 Signature0; /* 0x04 */
1005 U32 Signature1; /* 0x08 */
1006 U32 Signature2; /* 0x0C */
1007 MPI2_VERSION_UNION MPIVersion; /* 0x10 */
1008 MPI2_VERSION_UNION FWVersion; /* 0x14 */
1009 MPI2_VERSION_UNION NVDATAVersion; /* 0x18 */
1010 MPI2_VERSION_UNION PackageVersion; /* 0x1C */
1011 U16 VendorID; /* 0x20 */
1012 U16 ProductID; /* 0x22 */
1013 U16 ProtocolFlags; /* 0x24 */
1014 U16 Reserved26; /* 0x26 */
1015 U32 IOCCapabilities; /* 0x28 */
1016 U32 ImageSize; /* 0x2C */
1017 U32 NextImageHeaderOffset; /* 0x30 */
1018 U32 Checksum; /* 0x34 */
1019 U32 Reserved38; /* 0x38 */
1020 U32 Reserved3C; /* 0x3C */
1021 U32 Reserved40; /* 0x40 */
1022 U32 Reserved44; /* 0x44 */
1023 U32 Reserved48; /* 0x48 */
1024 U32 Reserved4C; /* 0x4C */
1025 U32 Reserved50; /* 0x50 */
1026 U32 Reserved54; /* 0x54 */
1027 U32 Reserved58; /* 0x58 */
1028 U32 Reserved5C; /* 0x5C */
1029 U32 Reserved60; /* 0x60 */
1030 U32 FirmwareVersionNameWhat; /* 0x64 */
1031 U8 FirmwareVersionName[32]; /* 0x68 */
1032 U32 VendorNameWhat; /* 0x88 */
1033 U8 VendorName[32]; /* 0x8C */
1034 U32 PackageNameWhat; /* 0x88 */
1035 U8 PackageName[32]; /* 0x8C */
1036 U32 ReservedD0; /* 0xD0 */
1037 U32 ReservedD4; /* 0xD4 */
1038 U32 ReservedD8; /* 0xD8 */
1039 U32 ReservedDC; /* 0xDC */
1040 U32 ReservedE0; /* 0xE0 */
1041 U32 ReservedE4; /* 0xE4 */
1042 U32 ReservedE8; /* 0xE8 */
1043 U32 ReservedEC; /* 0xEC */
1044 U32 ReservedF0; /* 0xF0 */
1045 U32 ReservedF4; /* 0xF4 */
1046 U32 ReservedF8; /* 0xF8 */
1047 U32 ReservedFC; /* 0xFC */
1048} MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER,
1049 Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t;
1050
1051/* Signature field */
1052#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00)
1053#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000)
1054#define MPI2_FW_HEADER_SIGNATURE (0xEA000000)
1055
1056/* Signature0 field */
1057#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04)
1058#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A)
1059
1060/* Signature1 field */
1061#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08)
1062#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5)
1063
1064/* Signature2 field */
1065#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C)
1066#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA)
1067
1068
1069/* defines for using the ProductID field */
1070#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000)
1071#define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000)
1072
1073#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00)
1074#define MPI2_FW_HEADER_PID_PROD_A (0x0000)
1075
1076#define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF)
1077/* SAS */
1078#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0010)
1079
1080/* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
1081
1082/* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */
1083
1084
1085#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C)
1086#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30)
1087#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64)
1088
1089#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840)
1090
1091#define MPI2_FW_HEADER_SIZE (0x100)
1092
1093
1094/* Extended Image Header */
1095typedef struct _MPI2_EXT_IMAGE_HEADER
1096
1097{
1098 U8 ImageType; /* 0x00 */
1099 U8 Reserved1; /* 0x01 */
1100 U16 Reserved2; /* 0x02 */
1101 U32 Checksum; /* 0x04 */
1102 U32 ImageSize; /* 0x08 */
1103 U32 NextImageHeaderOffset; /* 0x0C */
1104 U32 PackageVersion; /* 0x10 */
1105 U32 Reserved3; /* 0x14 */
1106 U32 Reserved4; /* 0x18 */
1107 U32 Reserved5; /* 0x1C */
1108 U8 IdentifyString[32]; /* 0x20 */
1109} MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER,
1110 Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t;
1111
1112/* useful offsets */
1113#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00)
1114#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08)
1115#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C)
1116
1117#define MPI2_EXT_IMAGE_HEADER_SIZE (0x40)
1118
1119/* defines for the ImageType field */
1120#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00)
1121#define MPI2_EXT_IMAGE_TYPE_FW (0x01)
1122#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03)
1123#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04)
1124#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05)
1125#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06)
1126#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07)
1127#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08)
1128
1129#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MEGARAID)
1130
1131
1132
1133/* FLASH Layout Extended Image Data */
1134
1135/*
1136 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1137 * one and check RegionsPerLayout at runtime.
1138 */
1139#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
1140#define MPI2_FLASH_NUMBER_OF_REGIONS (1)
1141#endif
1142
1143/*
1144 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1145 * one and check NumberOfLayouts at runtime.
1146 */
1147#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
1148#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1)
1149#endif
1150
1151typedef struct _MPI2_FLASH_REGION
1152{
1153 U8 RegionType; /* 0x00 */
1154 U8 Reserved1; /* 0x01 */
1155 U16 Reserved2; /* 0x02 */
1156 U32 RegionOffset; /* 0x04 */
1157 U32 RegionSize; /* 0x08 */
1158 U32 Reserved3; /* 0x0C */
1159} MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION,
1160 Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t;
1161
1162typedef struct _MPI2_FLASH_LAYOUT
1163{
1164 U32 FlashSize; /* 0x00 */
1165 U32 Reserved1; /* 0x04 */
1166 U32 Reserved2; /* 0x08 */
1167 U32 Reserved3; /* 0x0C */
1168 MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */
1169} MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT,
1170 Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t;
1171
1172typedef struct _MPI2_FLASH_LAYOUT_DATA
1173{
1174 U8 ImageRevision; /* 0x00 */
1175 U8 Reserved1; /* 0x01 */
1176 U8 SizeOfRegion; /* 0x02 */
1177 U8 Reserved2; /* 0x03 */
1178 U16 NumberOfLayouts; /* 0x04 */
1179 U16 RegionsPerLayout; /* 0x06 */
1180 U16 MinimumSectorAlignment; /* 0x08 */
1181 U16 Reserved3; /* 0x0A */
1182 U32 Reserved4; /* 0x0C */
1183 MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */
1184} MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA,
1185 Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t;
1186
1187/* defines for the RegionType field */
1188#define MPI2_FLASH_REGION_UNUSED (0x00)
1189#define MPI2_FLASH_REGION_FIRMWARE (0x01)
1190#define MPI2_FLASH_REGION_BIOS (0x02)
1191#define MPI2_FLASH_REGION_NVDATA (0x03)
1192#define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05)
1193#define MPI2_FLASH_REGION_MFG_INFORMATION (0x06)
1194#define MPI2_FLASH_REGION_CONFIG_1 (0x07)
1195#define MPI2_FLASH_REGION_CONFIG_2 (0x08)
1196#define MPI2_FLASH_REGION_MEGARAID (0x09)
1197#define MPI2_FLASH_REGION_INIT (0x0A)
1198
1199/* ImageRevision */
1200#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00)
1201
1202
1203
1204/* Supported Devices Extended Image Data */
1205
1206/*
1207 * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1208 * one and check NumberOfDevices at runtime.
1209 */
1210#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
1211#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1)
1212#endif
1213
1214typedef struct _MPI2_SUPPORTED_DEVICE
1215{
1216 U16 DeviceID; /* 0x00 */
1217 U16 VendorID; /* 0x02 */
1218 U16 DeviceIDMask; /* 0x04 */
1219 U16 Reserved1; /* 0x06 */
1220 U8 LowPCIRev; /* 0x08 */
1221 U8 HighPCIRev; /* 0x09 */
1222 U16 Reserved2; /* 0x0A */
1223 U32 Reserved3; /* 0x0C */
1224} MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE,
1225 Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t;
1226
1227typedef struct _MPI2_SUPPORTED_DEVICES_DATA
1228{
1229 U8 ImageRevision; /* 0x00 */
1230 U8 Reserved1; /* 0x01 */
1231 U8 NumberOfDevices; /* 0x02 */
1232 U8 Reserved2; /* 0x03 */
1233 U32 Reserved3; /* 0x04 */
1234 MPI2_SUPPORTED_DEVICE SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */
1235} MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA,
1236 Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t;
1237
1238/* ImageRevision */
1239#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00)
1240
1241
1242/* Init Extended Image Data */
1243
1244typedef struct _MPI2_INIT_IMAGE_FOOTER
1245
1246{
1247 U32 BootFlags; /* 0x00 */
1248 U32 ImageSize; /* 0x04 */
1249 U32 Signature0; /* 0x08 */
1250 U32 Signature1; /* 0x0C */
1251 U32 Signature2; /* 0x10 */
1252 U32 ResetVector; /* 0x14 */
1253} MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER,
1254 Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t;
1255
1256/* defines for the BootFlags field */
1257#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00)
1258
1259/* defines for the ImageSize field */
1260#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04)
1261
1262/* defines for the Signature0 field */
1263#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08)
1264#define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA)
1265
1266/* defines for the Signature1 field */
1267#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C)
1268#define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5)
1269
1270/* defines for the Signature2 field */
1271#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10)
1272#define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A)
1273
1274/* Signature fields as individual bytes */
1275#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA)
1276#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A)
1277#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5)
1278#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A)
1279
1280#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5)
1281#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA)
1282#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A)
1283#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5)
1284
1285#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A)
1286#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5)
1287#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA)
1288#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A)
1289
1290/* defines for the ResetVector field */
1291#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14)
1292
1293
1294#endif
1295
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
new file mode 100644
index 000000000000..7134816d9046
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
@@ -0,0 +1,295 @@
1/*
2 * Copyright (c) 2000-2008 LSI Corporation.
3 *
4 *
5 * Name: mpi2_raid.h
6 * Title: MPI Integrated RAID messages and structures
7 * Creation Date: April 26, 2007
8 *
9 * mpi2_raid.h Version: 02.00.03
10 *
11 * Version History
12 * ---------------
13 *
14 * Date Version Description
15 * -------- -------- ------------------------------------------------------
16 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
17 * 08-31-07 02.00.01 Modifications to RAID Action request and reply,
18 * including the Actions and ActionData.
19 * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
20 * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
21 * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
22 * can be sized by the build environment.
23 * --------------------------------------------------------------------------
24 */
25
26#ifndef MPI2_RAID_H
27#define MPI2_RAID_H
28
29/*****************************************************************************
30*
31* Integrated RAID Messages
32*
33*****************************************************************************/
34
35/****************************************************************************
36* RAID Action messages
37****************************************************************************/
38
39/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
40#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000)
41#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001)
42
43/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
44
45/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
46#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001)
47
48/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
49typedef struct _MPI2_RAID_ACTION_RATE_DATA
50{
51 U8 RateToChange; /* 0x00 */
52 U8 RateOrMode; /* 0x01 */
53 U16 DataScrubDuration; /* 0x02 */
54} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA,
55 Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t;
56
57#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00)
58#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01)
59#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02)
60
61/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
62typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION
63{
64 U8 RAIDFunction; /* 0x00 */
65 U8 Flags; /* 0x01 */
66 U16 Reserved1; /* 0x02 */
67} MPI2_RAID_ACTION_START_RAID_FUNCTION,
68 MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
69 Mpi2RaidActionStartRaidFunction_t,
70 MPI2_POINTER pMpi2RaidActionStartRaidFunction_t;
71
72/* defines for the RAIDFunction field */
73#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00)
74#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
75#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02)
76
77/* defines for the Flags field */
78#define MPI2_RAID_ACTION_START_NEW (0x00)
79#define MPI2_RAID_ACTION_START_RESUME (0x01)
80
81/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
82typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION
83{
84 U8 RAIDFunction; /* 0x00 */
85 U8 Flags; /* 0x01 */
86 U16 Reserved1; /* 0x02 */
87} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
88 MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
89 Mpi2RaidActionStopRaidFunction_t,
90 MPI2_POINTER pMpi2RaidActionStopRaidFunction_t;
91
92/* defines for the RAIDFunction field */
93#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00)
94#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01)
95#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02)
96
97/* defines for the Flags field */
98#define MPI2_RAID_ACTION_STOP_ABORT (0x00)
99#define MPI2_RAID_ACTION_STOP_PAUSE (0x01)
100
101/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
102typedef struct _MPI2_RAID_ACTION_HOT_SPARE
103{
104 U8 HotSparePool; /* 0x00 */
105 U8 Reserved1; /* 0x01 */
106 U16 DevHandle; /* 0x02 */
107} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE,
108 Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t;
109
110/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
111typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE
112{
113 U8 Flags; /* 0x00 */
114 U8 DeviceFirmwareUpdateModeTimeout; /* 0x01 */
115 U16 Reserved1; /* 0x02 */
116} MPI2_RAID_ACTION_FW_UPDATE_MODE,
117 MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
118 Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t;
119
120/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
121#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00)
122#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01)
123
124typedef union _MPI2_RAID_ACTION_DATA
125{
126 U32 Word;
127 MPI2_RAID_ACTION_RATE_DATA Rates;
128 MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction;
129 MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction;
130 MPI2_RAID_ACTION_HOT_SPARE HotSpare;
131 MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode;
132} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA,
133 Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t;
134
135
136/* RAID Action Request Message */
137typedef struct _MPI2_RAID_ACTION_REQUEST
138{
139 U8 Action; /* 0x00 */
140 U8 Reserved1; /* 0x01 */
141 U8 ChainOffset; /* 0x02 */
142 U8 Function; /* 0x03 */
143 U16 VolDevHandle; /* 0x04 */
144 U8 PhysDiskNum; /* 0x06 */
145 U8 MsgFlags; /* 0x07 */
146 U8 VP_ID; /* 0x08 */
147 U8 VF_ID; /* 0x09 */
148 U16 Reserved2; /* 0x0A */
149 U32 Reserved3; /* 0x0C */
150 MPI2_RAID_ACTION_DATA ActionDataWord; /* 0x10 */
151 MPI2_SGE_SIMPLE_UNION ActionDataSGE; /* 0x14 */
152} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST,
153 Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t;
154
155/* RAID Action request Action values */
156
157#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01)
158#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02)
159#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03)
160#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04)
161#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05)
162#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A)
163#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B)
164#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F)
165#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11)
166#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15)
167#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17)
168#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18)
169#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19)
170#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C)
171#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D)
172#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E)
173#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20)
174#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21)
175#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22)
176
177
178/* RAID Volume Creation Structure */
179
180/*
181 * The following define can be customized for the targeted product.
182 */
183#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
184#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1)
185#endif
186
187typedef struct _MPI2_RAID_VOLUME_PHYSDISK
188{
189 U8 RAIDSetNum; /* 0x00 */
190 U8 PhysDiskMap; /* 0x01 */
191 U16 PhysDiskDevHandle; /* 0x02 */
192} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK,
193 Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t;
194
195/* defines for the PhysDiskMap field */
196#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01)
197#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02)
198
199typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT
200{
201 U8 NumPhysDisks; /* 0x00 */
202 U8 VolumeType; /* 0x01 */
203 U16 Reserved1; /* 0x02 */
204 U32 VolumeCreationFlags; /* 0x04 */
205 U32 VolumeSettings; /* 0x08 */
206 U8 Reserved2; /* 0x0C */
207 U8 ResyncRate; /* 0x0D */
208 U16 DataScrubDuration; /* 0x0E */
209 U64 VolumeMaxLBA; /* 0x10 */
210 U32 StripeSize; /* 0x18 */
211 U8 Name[16]; /* 0x1C */
212 MPI2_RAID_VOLUME_PHYSDISK PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */
213} MPI2_RAID_VOLUME_CREATION_STRUCT,
214 MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
215 Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t;
216
217/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
218
219/* defines for the VolumeCreationFlags field */
220#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
221#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x04)
222#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x02)
223#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x01)
224
225
226/* RAID Online Capacity Expansion Structure */
227
228typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION
229{
230 U32 Flags; /* 0x00 */
231 U16 DevHandle0; /* 0x04 */
232 U16 Reserved1; /* 0x06 */
233 U16 DevHandle1; /* 0x08 */
234 U16 Reserved2; /* 0x0A */
235} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
236 MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
237 Mpi2RaidOnlineCapacityExpansion_t,
238 MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t;
239
240
241/* RAID Volume Indicator Structure */
242
243typedef struct _MPI2_RAID_VOL_INDICATOR
244{
245 U64 TotalBlocks; /* 0x00 */
246 U64 BlocksRemaining; /* 0x08 */
247 U32 Flags; /* 0x10 */
248} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR,
249 Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t;
250
251/* defines for RAID Volume Indicator Flags field */
252#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F)
253#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000)
254#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
255#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002)
256#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003)
257
258
259/* RAID Action Reply ActionData union */
260typedef union _MPI2_RAID_ACTION_REPLY_DATA
261{
262 U32 Word[5];
263 MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
264 U16 VolDevHandle;
265 U8 VolumeState;
266 U8 PhysDiskNum;
267} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA,
268 Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t;
269
270/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
271
272
273/* RAID Action Reply Message */
274typedef struct _MPI2_RAID_ACTION_REPLY
275{
276 U8 Action; /* 0x00 */
277 U8 Reserved1; /* 0x01 */
278 U8 MsgLength; /* 0x02 */
279 U8 Function; /* 0x03 */
280 U16 VolDevHandle; /* 0x04 */
281 U8 PhysDiskNum; /* 0x06 */
282 U8 MsgFlags; /* 0x07 */
283 U8 VP_ID; /* 0x08 */
284 U8 VF_ID; /* 0x09 */
285 U16 Reserved2; /* 0x0A */
286 U16 Reserved3; /* 0x0C */
287 U16 IOCStatus; /* 0x0E */
288 U32 IOCLogInfo; /* 0x10 */
289 MPI2_RAID_ACTION_REPLY_DATA ActionData; /* 0x14 */
290} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY,
291 Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t;
292
293
294#endif
295
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
new file mode 100644
index 000000000000..8a42b136cf53
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
@@ -0,0 +1,282 @@
1/*
2 * Copyright (c) 2000-2007 LSI Corporation.
3 *
4 *
5 * Name: mpi2_sas.h
6 * Title: MPI Serial Attached SCSI structures and definitions
7 * Creation Date: February 9, 2007
8 *
9 * mpi2.h Version: 02.00.02
10 *
11 * Version History
12 * ---------------
13 *
14 * Date Version Description
15 * -------- -------- ------------------------------------------------------
16 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
17 * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit
18 * Control Request.
19 * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control
20 * Request.
21 * --------------------------------------------------------------------------
22 */
23
24#ifndef MPI2_SAS_H
25#define MPI2_SAS_H
26
27/*
28 * Values for SASStatus.
29 */
30#define MPI2_SASSTATUS_SUCCESS (0x00)
31#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01)
32#define MPI2_SASSTATUS_INVALID_FRAME (0x02)
33#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03)
34#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04)
35#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05)
36#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06)
37#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07)
38#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08)
39#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09)
40#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A)
41#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B)
42#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C)
43#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D)
44#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E)
45#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F)
46#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10)
47#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11)
48#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12)
49#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13)
50#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14)
51
52
53/*
54 * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
55 * data and SAS Configuration pages.
56 */
57#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000)
58#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
59#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
60#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
61#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400)
62#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200)
63#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100)
64#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080)
65#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040)
66#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020)
67#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010)
68#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008)
69
70#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
71#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000)
72#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001)
73#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
74#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
75
76
77/*****************************************************************************
78*
79* SAS Messages
80*
81*****************************************************************************/
82
83/****************************************************************************
84* SMP Passthrough messages
85****************************************************************************/
86
87/* SMP Passthrough Request Message */
88typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST
89{
90 U8 PassthroughFlags; /* 0x00 */
91 U8 PhysicalPort; /* 0x01 */
92 U8 ChainOffset; /* 0x02 */
93 U8 Function; /* 0x03 */
94 U16 RequestDataLength; /* 0x04 */
95 U8 SGLFlags; /* 0x06 */
96 U8 MsgFlags; /* 0x07 */
97 U8 VP_ID; /* 0x08 */
98 U8 VF_ID; /* 0x09 */
99 U16 Reserved1; /* 0x0A */
100 U32 Reserved2; /* 0x0C */
101 U64 SASAddress; /* 0x10 */
102 U32 Reserved3; /* 0x18 */
103 U32 Reserved4; /* 0x1C */
104 MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */
105} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
106 Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t;
107
108/* values for PassthroughFlags field */
109#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
110
111/* values for SGLFlags field are in the SGL section of mpi2.h */
112
113
114/* SMP Passthrough Reply Message */
115typedef struct _MPI2_SMP_PASSTHROUGH_REPLY
116{
117 U8 PassthroughFlags; /* 0x00 */
118 U8 PhysicalPort; /* 0x01 */
119 U8 MsgLength; /* 0x02 */
120 U8 Function; /* 0x03 */
121 U16 ResponseDataLength; /* 0x04 */
122 U8 SGLFlags; /* 0x06 */
123 U8 MsgFlags; /* 0x07 */
124 U8 VP_ID; /* 0x08 */
125 U8 VF_ID; /* 0x09 */
126 U16 Reserved1; /* 0x0A */
127 U8 Reserved2; /* 0x0C */
128 U8 SASStatus; /* 0x0D */
129 U16 IOCStatus; /* 0x0E */
130 U32 IOCLogInfo; /* 0x10 */
131 U32 Reserved3; /* 0x14 */
132 U8 ResponseData[4]; /* 0x18 */
133} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY,
134 Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t;
135
136/* values for PassthroughFlags field */
137#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
138
139/* values for SASStatus field are at the top of this file */
140
141
142/****************************************************************************
143* SATA Passthrough messages
144****************************************************************************/
145
146/* SATA Passthrough Request Message */
147typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
148{
149 U16 DevHandle; /* 0x00 */
150 U8 ChainOffset; /* 0x02 */
151 U8 Function; /* 0x03 */
152 U16 PassthroughFlags; /* 0x04 */
153 U8 SGLFlags; /* 0x06 */
154 U8 MsgFlags; /* 0x07 */
155 U8 VP_ID; /* 0x08 */
156 U8 VF_ID; /* 0x09 */
157 U16 Reserved1; /* 0x0A */
158 U32 Reserved2; /* 0x0C */
159 U32 Reserved3; /* 0x10 */
160 U32 Reserved4; /* 0x14 */
161 U32 DataLength; /* 0x18 */
162 U8 CommandFIS[20]; /* 0x1C */
163 MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */
164} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
165 Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
166
167/* values for PassthroughFlags field */
168#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
169#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
170#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
171#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
172#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
173#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
174
175/* values for SGLFlags field are in the SGL section of mpi2.h */
176
177
178/* SATA Passthrough Reply Message */
179typedef struct _MPI2_SATA_PASSTHROUGH_REPLY
180{
181 U16 DevHandle; /* 0x00 */
182 U8 MsgLength; /* 0x02 */
183 U8 Function; /* 0x03 */
184 U16 PassthroughFlags; /* 0x04 */
185 U8 SGLFlags; /* 0x06 */
186 U8 MsgFlags; /* 0x07 */
187 U8 VP_ID; /* 0x08 */
188 U8 VF_ID; /* 0x09 */
189 U16 Reserved1; /* 0x0A */
190 U8 Reserved2; /* 0x0C */
191 U8 SASStatus; /* 0x0D */
192 U16 IOCStatus; /* 0x0E */
193 U32 IOCLogInfo; /* 0x10 */
194 U8 StatusFIS[20]; /* 0x14 */
195 U32 StatusControlRegisters; /* 0x28 */
196 U32 TransferCount; /* 0x2C */
197} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY,
198 Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t;
199
200/* values for SASStatus field are at the top of this file */
201
202
203/****************************************************************************
204* SAS IO Unit Control messages
205****************************************************************************/
206
207/* SAS IO Unit Control Request Message */
208typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST
209{
210 U8 Operation; /* 0x00 */
211 U8 Reserved1; /* 0x01 */
212 U8 ChainOffset; /* 0x02 */
213 U8 Function; /* 0x03 */
214 U16 DevHandle; /* 0x04 */
215 U8 IOCParameter; /* 0x06 */
216 U8 MsgFlags; /* 0x07 */
217 U8 VP_ID; /* 0x08 */
218 U8 VF_ID; /* 0x09 */
219 U16 Reserved3; /* 0x0A */
220 U16 Reserved4; /* 0x0C */
221 U8 PhyNum; /* 0x0E */
222 U8 PrimFlags; /* 0x0F */
223 U32 Primitive; /* 0x10 */
224 U8 LookupMethod; /* 0x14 */
225 U8 Reserved5; /* 0x15 */
226 U16 SlotNumber; /* 0x16 */
227 U64 LookupAddress; /* 0x18 */
228 U32 IOCParameterValue; /* 0x20 */
229 U32 Reserved7; /* 0x24 */
230 U32 Reserved8; /* 0x28 */
231} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
232 MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
233 Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t;
234
235/* values for the Operation field */
236#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
237#define MPI2_SAS_OP_PHY_LINK_RESET (0x06)
238#define MPI2_SAS_OP_PHY_HARD_RESET (0x07)
239#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
240#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A)
241#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B)
242#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
243#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D)
244#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E)
245#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F)
246#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80)
247
248/* values for the PrimFlags field */
249#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08)
250#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02)
251#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01)
252
253/* values for the LookupMethod field */
254#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01)
255#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02)
256#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03)
257
258
259/* SAS IO Unit Control Reply Message */
260typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY
261{
262 U8 Operation; /* 0x00 */
263 U8 Reserved1; /* 0x01 */
264 U8 MsgLength; /* 0x02 */
265 U8 Function; /* 0x03 */
266 U16 DevHandle; /* 0x04 */
267 U8 IOCParameter; /* 0x06 */
268 U8 MsgFlags; /* 0x07 */
269 U8 VP_ID; /* 0x08 */
270 U8 VF_ID; /* 0x09 */
271 U16 Reserved3; /* 0x0A */
272 U16 Reserved4; /* 0x0C */
273 U16 IOCStatus; /* 0x0E */
274 U32 IOCLogInfo; /* 0x10 */
275} MPI2_SAS_IOUNIT_CONTROL_REPLY,
276 MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
277 Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t;
278
279
280#endif
281
282
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
new file mode 100644
index 000000000000..2ff4e936bd39
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
@@ -0,0 +1,249 @@
1/*
2 * Copyright (c) 2000-2008 LSI Corporation.
3 *
4 *
5 * Name: mpi2_tool.h
6 * Title: MPI diagnostic tool structures and definitions
7 * Creation Date: March 26, 2007
8 *
9 * mpi2_tool.h Version: 02.00.02
10 *
11 * Version History
12 * ---------------
13 *
14 * Date Version Description
15 * -------- -------- ------------------------------------------------------
16 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
17 * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release
18 * structures and defines.
19 * 02-29-08 02.00.02 Modified various names to make them 32-character unique.
20 * --------------------------------------------------------------------------
21 */
22
23#ifndef MPI2_TOOL_H
24#define MPI2_TOOL_H
25
26/*****************************************************************************
27*
28* Toolbox Messages
29*
30*****************************************************************************/
31
32/* defines for the Tools */
33#define MPI2_TOOLBOX_CLEAN_TOOL (0x00)
34#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01)
35#define MPI2_TOOLBOX_BEACON_TOOL (0x05)
36
37/****************************************************************************
38* Toolbox reply
39****************************************************************************/
40
41typedef struct _MPI2_TOOLBOX_REPLY
42{
43 U8 Tool; /* 0x00 */
44 U8 Reserved1; /* 0x01 */
45 U8 MsgLength; /* 0x02 */
46 U8 Function; /* 0x03 */
47 U16 Reserved2; /* 0x04 */
48 U8 Reserved3; /* 0x06 */
49 U8 MsgFlags; /* 0x07 */
50 U8 VP_ID; /* 0x08 */
51 U8 VF_ID; /* 0x09 */
52 U16 Reserved4; /* 0x0A */
53 U16 Reserved5; /* 0x0C */
54 U16 IOCStatus; /* 0x0E */
55 U32 IOCLogInfo; /* 0x10 */
56} MPI2_TOOLBOX_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_REPLY,
57 Mpi2ToolboxReply_t, MPI2_POINTER pMpi2ToolboxReply_t;
58
59
60/****************************************************************************
61* Toolbox Clean Tool request
62****************************************************************************/
63
64typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST
65{
66 U8 Tool; /* 0x00 */
67 U8 Reserved1; /* 0x01 */
68 U8 ChainOffset; /* 0x02 */
69 U8 Function; /* 0x03 */
70 U16 Reserved2; /* 0x04 */
71 U8 Reserved3; /* 0x06 */
72 U8 MsgFlags; /* 0x07 */
73 U8 VP_ID; /* 0x08 */
74 U8 VF_ID; /* 0x09 */
75 U16 Reserved4; /* 0x0A */
76 U32 Flags; /* 0x0C */
77 } MPI2_TOOLBOX_CLEAN_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_CLEAN_REQUEST,
78 Mpi2ToolboxCleanRequest_t, MPI2_POINTER pMpi2ToolboxCleanRequest_t;
79
80/* values for the Flags field */
81#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000)
82#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000)
83#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000)
84#define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000)
85#define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000)
86#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000)
87#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000)
88#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004)
89#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002)
90#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001)
91
92
93/****************************************************************************
94* Toolbox Memory Move request
95****************************************************************************/
96
97typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST
98{
99 U8 Tool; /* 0x00 */
100 U8 Reserved1; /* 0x01 */
101 U8 ChainOffset; /* 0x02 */
102 U8 Function; /* 0x03 */
103 U16 Reserved2; /* 0x04 */
104 U8 Reserved3; /* 0x06 */
105 U8 MsgFlags; /* 0x07 */
106 U8 VP_ID; /* 0x08 */
107 U8 VF_ID; /* 0x09 */
108 U16 Reserved4; /* 0x0A */
109 MPI2_SGE_SIMPLE_UNION SGL; /* 0x0C */
110} MPI2_TOOLBOX_MEM_MOVE_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST,
111 Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t;
112
113
114/****************************************************************************
115* Toolbox Beacon Tool request
116****************************************************************************/
117
118typedef struct _MPI2_TOOLBOX_BEACON_REQUEST
119{
120 U8 Tool; /* 0x00 */
121 U8 Reserved1; /* 0x01 */
122 U8 ChainOffset; /* 0x02 */
123 U8 Function; /* 0x03 */
124 U16 Reserved2; /* 0x04 */
125 U8 Reserved3; /* 0x06 */
126 U8 MsgFlags; /* 0x07 */
127 U8 VP_ID; /* 0x08 */
128 U8 VF_ID; /* 0x09 */
129 U16 Reserved4; /* 0x0A */
130 U8 Reserved5; /* 0x0C */
131 U8 PhysicalPort; /* 0x0D */
132 U8 Reserved6; /* 0x0E */
133 U8 Flags; /* 0x0F */
134} MPI2_TOOLBOX_BEACON_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_BEACON_REQUEST,
135 Mpi2ToolboxBeaconRequest_t, MPI2_POINTER pMpi2ToolboxBeaconRequest_t;
136
137/* values for the Flags field */
138#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00)
139#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01)
140
141
142/*****************************************************************************
143*
144* Diagnostic Buffer Messages
145*
146*****************************************************************************/
147
148
149/****************************************************************************
150* Diagnostic Buffer Post request
151****************************************************************************/
152
153typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST
154{
155 U8 Reserved1; /* 0x00 */
156 U8 BufferType; /* 0x01 */
157 U8 ChainOffset; /* 0x02 */
158 U8 Function; /* 0x03 */
159 U16 Reserved2; /* 0x04 */
160 U8 Reserved3; /* 0x06 */
161 U8 MsgFlags; /* 0x07 */
162 U8 VP_ID; /* 0x08 */
163 U8 VF_ID; /* 0x09 */
164 U16 Reserved4; /* 0x0A */
165 U64 BufferAddress; /* 0x0C */
166 U32 BufferLength; /* 0x14 */
167 U32 Reserved5; /* 0x18 */
168 U32 Reserved6; /* 0x1C */
169 U32 Flags; /* 0x20 */
170 U32 ProductSpecific[23]; /* 0x24 */
171} MPI2_DIAG_BUFFER_POST_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REQUEST,
172 Mpi2DiagBufferPostRequest_t, MPI2_POINTER pMpi2DiagBufferPostRequest_t;
173
174/* values for the BufferType field */
175#define MPI2_DIAG_BUF_TYPE_TRACE (0x00)
176#define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01)
177/* count of the number of buffer types */
178#define MPI2_DIAG_BUF_TYPE_COUNT (0x02)
179
180
181/****************************************************************************
182* Diagnostic Buffer Post reply
183****************************************************************************/
184
185typedef struct _MPI2_DIAG_BUFFER_POST_REPLY
186{
187 U8 Reserved1; /* 0x00 */
188 U8 BufferType; /* 0x01 */
189 U8 MsgLength; /* 0x02 */
190 U8 Function; /* 0x03 */
191 U16 Reserved2; /* 0x04 */
192 U8 Reserved3; /* 0x06 */
193 U8 MsgFlags; /* 0x07 */
194 U8 VP_ID; /* 0x08 */
195 U8 VF_ID; /* 0x09 */
196 U16 Reserved4; /* 0x0A */
197 U16 Reserved5; /* 0x0C */
198 U16 IOCStatus; /* 0x0E */
199 U32 IOCLogInfo; /* 0x10 */
200 U32 TransferLength; /* 0x14 */
201} MPI2_DIAG_BUFFER_POST_REPLY, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REPLY,
202 Mpi2DiagBufferPostReply_t, MPI2_POINTER pMpi2DiagBufferPostReply_t;
203
204
205/****************************************************************************
206* Diagnostic Release request
207****************************************************************************/
208
209typedef struct _MPI2_DIAG_RELEASE_REQUEST
210{
211 U8 Reserved1; /* 0x00 */
212 U8 BufferType; /* 0x01 */
213 U8 ChainOffset; /* 0x02 */
214 U8 Function; /* 0x03 */
215 U16 Reserved2; /* 0x04 */
216 U8 Reserved3; /* 0x06 */
217 U8 MsgFlags; /* 0x07 */
218 U8 VP_ID; /* 0x08 */
219 U8 VF_ID; /* 0x09 */
220 U16 Reserved4; /* 0x0A */
221} MPI2_DIAG_RELEASE_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REQUEST,
222 Mpi2DiagReleaseRequest_t, MPI2_POINTER pMpi2DiagReleaseRequest_t;
223
224
225/****************************************************************************
226* Diagnostic Buffer Post reply
227****************************************************************************/
228
229typedef struct _MPI2_DIAG_RELEASE_REPLY
230{
231 U8 Reserved1; /* 0x00 */
232 U8 BufferType; /* 0x01 */
233 U8 MsgLength; /* 0x02 */
234 U8 Function; /* 0x03 */
235 U16 Reserved2; /* 0x04 */
236 U8 Reserved3; /* 0x06 */
237 U8 MsgFlags; /* 0x07 */
238 U8 VP_ID; /* 0x08 */
239 U8 VF_ID; /* 0x09 */
240 U16 Reserved4; /* 0x0A */
241 U16 Reserved5; /* 0x0C */
242 U16 IOCStatus; /* 0x0E */
243 U32 IOCLogInfo; /* 0x10 */
244} MPI2_DIAG_RELEASE_REPLY, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REPLY,
245 Mpi2DiagReleaseReply_t, MPI2_POINTER pMpi2DiagReleaseReply_t;
246
247
248#endif
249
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_type.h b/drivers/scsi/mpt2sas/mpi/mpi2_type.h
new file mode 100644
index 000000000000..cfde017bf16e
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_type.h
@@ -0,0 +1,61 @@
1/*
2 * Copyright (c) 2000-2007 LSI Corporation.
3 *
4 *
5 * Name: mpi2_type.h
6 * Title: MPI basic type definitions
7 * Creation Date: August 16, 2006
8 *
9 * mpi2_type.h Version: 02.00.00
10 *
11 * Version History
12 * ---------------
13 *
14 * Date Version Description
15 * -------- -------- ------------------------------------------------------
16 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
17 * --------------------------------------------------------------------------
18 */
19
20#ifndef MPI2_TYPE_H
21#define MPI2_TYPE_H
22
23
24/*******************************************************************************
25 * Define MPI2_POINTER if it hasn't already been defined. By default
26 * MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as
27 * a far pointer by defining MPI2_POINTER as "far *" before this header file is
28 * included.
29 */
30#ifndef MPI2_POINTER
31#define MPI2_POINTER *
32#endif
33
34/* the basic types may have already been included by mpi_type.h */
35#ifndef MPI_TYPE_H
36/*****************************************************************************
37*
38* Basic Types
39*
40*****************************************************************************/
41
42typedef u8 U8;
43typedef __le16 U16;
44typedef __le32 U32;
45typedef __le64 U64 __attribute__((aligned(4)));
46
47/*****************************************************************************
48*
49* Pointer Types
50*
51*****************************************************************************/
52
53typedef U8 *PU8;
54typedef U16 *PU16;
55typedef U32 *PU32;
56typedef U64 *PU64;
57
58#endif
59
60#endif
61
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
new file mode 100644
index 000000000000..52427a8324f5
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -0,0 +1,3435 @@
1/*
2 * This is the Fusion MPT base driver providing common API layer interface
3 * for access to MPT (Message Passing Technology) firmware.
4 *
5 * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
6 * Copyright (C) 2007-2008 LSI Corporation
7 * (mailto:DL-MPTFusionLinux@lsi.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * NO WARRANTY
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
29
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
42 * USA.
43 */
44
45#include <linux/version.h>
46#include <linux/kernel.h>
47#include <linux/module.h>
48#include <linux/errno.h>
49#include <linux/init.h>
50#include <linux/slab.h>
51#include <linux/types.h>
52#include <linux/pci.h>
53#include <linux/kdev_t.h>
54#include <linux/blkdev.h>
55#include <linux/delay.h>
56#include <linux/interrupt.h>
57#include <linux/dma-mapping.h>
58#include <linux/sort.h>
59#include <linux/io.h>
60
61#include "mpt2sas_base.h"
62
63static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
64
65#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
66#define MPT2SAS_MAX_REQUEST_QUEUE 500 /* maximum controller queue depth */
67
68static int max_queue_depth = -1;
69module_param(max_queue_depth, int, 0);
70MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
71
72static int max_sgl_entries = -1;
73module_param(max_sgl_entries, int, 0);
74MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
75
76static int msix_disable = -1;
77module_param(msix_disable, int, 0);
78MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
79
80/**
81 * _base_fault_reset_work - workq handling ioc fault conditions
82 * @work: input argument, used to derive ioc
83 * Context: sleep.
84 *
85 * Return nothing.
86 */
87static void
88_base_fault_reset_work(struct work_struct *work)
89{
90 struct MPT2SAS_ADAPTER *ioc =
91 container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work);
92 unsigned long flags;
93 u32 doorbell;
94 int rc;
95
96 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
97 if (ioc->ioc_reset_in_progress)
98 goto rearm_timer;
99 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
100
101 doorbell = mpt2sas_base_get_iocstate(ioc, 0);
102 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
103 rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
104 FORCE_BIG_HAMMER);
105 printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name,
106 __func__, (rc == 0) ? "success" : "failed");
107 doorbell = mpt2sas_base_get_iocstate(ioc, 0);
108 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
109 mpt2sas_base_fault_info(ioc, doorbell &
110 MPI2_DOORBELL_DATA_MASK);
111 }
112
113 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
114 rearm_timer:
115 if (ioc->fault_reset_work_q)
116 queue_delayed_work(ioc->fault_reset_work_q,
117 &ioc->fault_reset_work,
118 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
119 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
120}
121
122#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
123/**
124 * _base_sas_ioc_info - verbose translation of the ioc status
125 * @ioc: pointer to scsi command object
126 * @mpi_reply: reply mf payload returned from firmware
127 * @request_hdr: request mf
128 *
129 * Return nothing.
130 */
131static void
132_base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
133 MPI2RequestHeader_t *request_hdr)
134{
135 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
136 MPI2_IOCSTATUS_MASK;
137 char *desc = NULL;
138 u16 frame_sz;
139 char *func_str = NULL;
140
141 /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
142 if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
143 request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
144 request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
145 return;
146
147 switch (ioc_status) {
148
149/****************************************************************************
150* Common IOCStatus values for all replies
151****************************************************************************/
152
153 case MPI2_IOCSTATUS_INVALID_FUNCTION:
154 desc = "invalid function";
155 break;
156 case MPI2_IOCSTATUS_BUSY:
157 desc = "busy";
158 break;
159 case MPI2_IOCSTATUS_INVALID_SGL:
160 desc = "invalid sgl";
161 break;
162 case MPI2_IOCSTATUS_INTERNAL_ERROR:
163 desc = "internal error";
164 break;
165 case MPI2_IOCSTATUS_INVALID_VPID:
166 desc = "invalid vpid";
167 break;
168 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
169 desc = "insufficient resources";
170 break;
171 case MPI2_IOCSTATUS_INVALID_FIELD:
172 desc = "invalid field";
173 break;
174 case MPI2_IOCSTATUS_INVALID_STATE:
175 desc = "invalid state";
176 break;
177 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
178 desc = "op state not supported";
179 break;
180
181/****************************************************************************
182* Config IOCStatus values
183****************************************************************************/
184
185 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
186 desc = "config invalid action";
187 break;
188 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
189 desc = "config invalid type";
190 break;
191 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
192 desc = "config invalid page";
193 break;
194 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
195 desc = "config invalid data";
196 break;
197 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
198 desc = "config no defaults";
199 break;
200 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
201 desc = "config cant commit";
202 break;
203
204/****************************************************************************
205* SCSI IO Reply
206****************************************************************************/
207
208 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
209 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
210 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
211 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
212 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
213 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
214 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
215 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
216 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
217 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
218 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
219 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
220 break;
221
222/****************************************************************************
223* For use by SCSI Initiator and SCSI Target end-to-end data protection
224****************************************************************************/
225
226 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
227 desc = "eedp guard error";
228 break;
229 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
230 desc = "eedp ref tag error";
231 break;
232 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
233 desc = "eedp app tag error";
234 break;
235
236/****************************************************************************
237* SCSI Target values
238****************************************************************************/
239
240 case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
241 desc = "target invalid io index";
242 break;
243 case MPI2_IOCSTATUS_TARGET_ABORTED:
244 desc = "target aborted";
245 break;
246 case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
247 desc = "target no conn retryable";
248 break;
249 case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
250 desc = "target no connection";
251 break;
252 case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
253 desc = "target xfer count mismatch";
254 break;
255 case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
256 desc = "target data offset error";
257 break;
258 case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
259 desc = "target too much write data";
260 break;
261 case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
262 desc = "target iu too short";
263 break;
264 case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
265 desc = "target ack nak timeout";
266 break;
267 case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
268 desc = "target nak received";
269 break;
270
271/****************************************************************************
272* Serial Attached SCSI values
273****************************************************************************/
274
275 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
276 desc = "smp request failed";
277 break;
278 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
279 desc = "smp data overrun";
280 break;
281
282/****************************************************************************
283* Diagnostic Buffer Post / Diagnostic Release values
284****************************************************************************/
285
286 case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
287 desc = "diagnostic released";
288 break;
289 default:
290 break;
291 }
292
293 if (!desc)
294 return;
295
296 switch (request_hdr->Function) {
297 case MPI2_FUNCTION_CONFIG:
298 frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
299 func_str = "config_page";
300 break;
301 case MPI2_FUNCTION_SCSI_TASK_MGMT:
302 frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
303 func_str = "task_mgmt";
304 break;
305 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
306 frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
307 func_str = "sas_iounit_ctl";
308 break;
309 case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
310 frame_sz = sizeof(Mpi2SepRequest_t);
311 func_str = "enclosure";
312 break;
313 case MPI2_FUNCTION_IOC_INIT:
314 frame_sz = sizeof(Mpi2IOCInitRequest_t);
315 func_str = "ioc_init";
316 break;
317 case MPI2_FUNCTION_PORT_ENABLE:
318 frame_sz = sizeof(Mpi2PortEnableRequest_t);
319 func_str = "port_enable";
320 break;
321 case MPI2_FUNCTION_SMP_PASSTHROUGH:
322 frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
323 func_str = "smp_passthru";
324 break;
325 default:
326 frame_sz = 32;
327 func_str = "unknown";
328 break;
329 }
330
331 printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p),"
332 " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str);
333
334 _debug_dump_mf(request_hdr, frame_sz/4);
335}
336
337/**
338 * _base_display_event_data - verbose translation of firmware asyn events
339 * @ioc: pointer to scsi command object
340 * @mpi_reply: reply mf payload returned from firmware
341 *
342 * Return nothing.
343 */
344static void
345_base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
346 Mpi2EventNotificationReply_t *mpi_reply)
347{
348 char *desc = NULL;
349 u16 event;
350
351 if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
352 return;
353
354 event = le16_to_cpu(mpi_reply->Event);
355
356 switch (event) {
357 case MPI2_EVENT_LOG_DATA:
358 desc = "Log Data";
359 break;
360 case MPI2_EVENT_STATE_CHANGE:
361 desc = "Status Change";
362 break;
363 case MPI2_EVENT_HARD_RESET_RECEIVED:
364 desc = "Hard Reset Received";
365 break;
366 case MPI2_EVENT_EVENT_CHANGE:
367 desc = "Event Change";
368 break;
369 case MPI2_EVENT_TASK_SET_FULL:
370 desc = "Task Set Full";
371 break;
372 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
373 desc = "Device Status Change";
374 break;
375 case MPI2_EVENT_IR_OPERATION_STATUS:
376 desc = "IR Operation Status";
377 break;
378 case MPI2_EVENT_SAS_DISCOVERY:
379 desc = "Discovery";
380 break;
381 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
382 desc = "SAS Broadcast Primitive";
383 break;
384 case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
385 desc = "SAS Init Device Status Change";
386 break;
387 case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
388 desc = "SAS Init Table Overflow";
389 break;
390 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
391 desc = "SAS Topology Change List";
392 break;
393 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
394 desc = "SAS Enclosure Device Status Change";
395 break;
396 case MPI2_EVENT_IR_VOLUME:
397 desc = "IR Volume";
398 break;
399 case MPI2_EVENT_IR_PHYSICAL_DISK:
400 desc = "IR Physical Disk";
401 break;
402 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
403 desc = "IR Configuration Change List";
404 break;
405 case MPI2_EVENT_LOG_ENTRY_ADDED:
406 desc = "Log Entry Added";
407 break;
408 }
409
410 if (!desc)
411 return;
412
413 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc);
414}
415#endif
416
417/**
418 * _base_sas_log_info - verbose translation of firmware log info
419 * @ioc: pointer to scsi command object
420 * @log_info: log info
421 *
422 * Return nothing.
423 */
424static void
425_base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
426{
427 union loginfo_type {
428 u32 loginfo;
429 struct {
430 u32 subcode:16;
431 u32 code:8;
432 u32 originator:4;
433 u32 bus_type:4;
434 } dw;
435 };
436 union loginfo_type sas_loginfo;
437 char *originator_str = NULL;
438
439 sas_loginfo.loginfo = log_info;
440 if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
441 return;
442
443 /* eat the loginfos associated with task aborts */
444 if (ioc->ignore_loginfos && (log_info == 30050000 || log_info ==
445 0x31140000 || log_info == 0x31130000))
446 return;
447
448 switch (sas_loginfo.dw.originator) {
449 case 0:
450 originator_str = "IOP";
451 break;
452 case 1:
453 originator_str = "PL";
454 break;
455 case 2:
456 originator_str = "IR";
457 break;
458 }
459
460 printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), "
461 "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info,
462 originator_str, sas_loginfo.dw.code,
463 sas_loginfo.dw.subcode);
464}
465
466/**
467 * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
468 * @ioc: pointer to scsi command object
469 * @fault_code: fault code
470 *
471 * Return nothing.
472 */
473void
474mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
475{
476 printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
477 ioc->name, fault_code);
478}
479
480/**
481 * _base_display_reply_info -
482 * @ioc: pointer to scsi command object
483 * @smid: system request message index
484 * @VF_ID: virtual function id
485 * @reply: reply message frame(lower 32bit addr)
486 *
487 * Return nothing.
488 */
489static void
490_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
491 u32 reply)
492{
493 MPI2DefaultReply_t *mpi_reply;
494 u16 ioc_status;
495
496 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
497 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
498#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
499 if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
500 (ioc->logging_level & MPT_DEBUG_REPLY)) {
501 _base_sas_ioc_info(ioc , mpi_reply,
502 mpt2sas_base_get_msg_frame(ioc, smid));
503 }
504#endif
505 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
506 _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo));
507}
508
509/**
510 * mpt2sas_base_done - base internal command completion routine
511 * @ioc: pointer to scsi command object
512 * @smid: system request message index
513 * @VF_ID: virtual function id
514 * @reply: reply message frame(lower 32bit addr)
515 *
516 * Return nothing.
517 */
518void
519mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
520{
521 MPI2DefaultReply_t *mpi_reply;
522
523 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
524 if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
525 return;
526
527 if (ioc->base_cmds.status == MPT2_CMD_NOT_USED)
528 return;
529
530 ioc->base_cmds.status |= MPT2_CMD_COMPLETE;
531 if (mpi_reply) {
532 ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID;
533 memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
534 }
535 ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
536 complete(&ioc->base_cmds.done);
537}
538
539/**
540 * _base_async_event - main callback handler for firmware asyn events
541 * @ioc: pointer to scsi command object
542 * @VF_ID: virtual function id
543 * @reply: reply message frame(lower 32bit addr)
544 *
545 * Return nothing.
546 */
547static void
548_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
549{
550 Mpi2EventNotificationReply_t *mpi_reply;
551 Mpi2EventAckRequest_t *ack_request;
552 u16 smid;
553
554 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
555 if (!mpi_reply)
556 return;
557 if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
558 return;
559#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
560 _base_display_event_data(ioc, mpi_reply);
561#endif
562 if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
563 goto out;
564 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
565 if (!smid) {
566 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
567 ioc->name, __func__);
568 goto out;
569 }
570
571 ack_request = mpt2sas_base_get_msg_frame(ioc, smid);
572 memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
573 ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
574 ack_request->Event = mpi_reply->Event;
575 ack_request->EventContext = mpi_reply->EventContext;
576 ack_request->VF_ID = VF_ID;
577 mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
578
579 out:
580
581 /* scsih callback handler */
582 mpt2sas_scsih_event_callback(ioc, VF_ID, reply);
583
584 /* ctl callback handler */
585 mpt2sas_ctl_event_callback(ioc, VF_ID, reply);
586}
587
588/**
589 * _base_mask_interrupts - disable interrupts
590 * @ioc: pointer to scsi command object
591 *
592 * Disabling ResetIRQ, Reply and Doorbell Interrupts
593 *
594 * Return nothing.
595 */
596static void
597_base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
598{
599 u32 him_register;
600
601 ioc->mask_interrupts = 1;
602 him_register = readl(&ioc->chip->HostInterruptMask);
603 him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
604 writel(him_register, &ioc->chip->HostInterruptMask);
605 readl(&ioc->chip->HostInterruptMask);
606}
607
608/**
609 * _base_unmask_interrupts - enable interrupts
610 * @ioc: pointer to scsi command object
611 *
612 * Enabling only Reply Interrupts
613 *
614 * Return nothing.
615 */
616static void
617_base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
618{
619 u32 him_register;
620
621 writel(0, &ioc->chip->HostInterruptStatus);
622 him_register = readl(&ioc->chip->HostInterruptMask);
623 him_register &= ~MPI2_HIM_RIM;
624 writel(him_register, &ioc->chip->HostInterruptMask);
625 ioc->mask_interrupts = 0;
626}
627
628/**
629 * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
630 * @irq: irq number (not used)
631 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
632 * @r: pt_regs pointer (not used)
633 *
634 * Return IRQ_HANDLE if processed, else IRQ_NONE.
635 */
636static irqreturn_t
637_base_interrupt(int irq, void *bus_id)
638{
639 u32 post_index, post_index_next, completed_cmds;
640 u8 request_desript_type;
641 u16 smid;
642 u8 cb_idx;
643 u32 reply;
644 u8 VF_ID;
645 int i;
646 struct MPT2SAS_ADAPTER *ioc = bus_id;
647
648 if (ioc->mask_interrupts)
649 return IRQ_NONE;
650
651 post_index = ioc->reply_post_host_index;
652 request_desript_type = ioc->reply_post_free[post_index].
653 Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
654 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
655 return IRQ_NONE;
656
657 completed_cmds = 0;
658 do {
659 if (ioc->reply_post_free[post_index].Words == ~0ULL)
660 goto out;
661 reply = 0;
662 cb_idx = 0xFF;
663 smid = le16_to_cpu(ioc->reply_post_free[post_index].
664 Default.DescriptorTypeDependent1);
665 VF_ID = ioc->reply_post_free[post_index].
666 Default.VF_ID;
667 if (request_desript_type ==
668 MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
669 reply = le32_to_cpu(ioc->reply_post_free[post_index].
670 AddressReply.ReplyFrameAddress);
671 } else if (request_desript_type ==
672 MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
673 goto next;
674 else if (request_desript_type ==
675 MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
676 goto next;
677 if (smid)
678 cb_idx = ioc->scsi_lookup[smid - 1].cb_idx;
679 if (smid && cb_idx != 0xFF) {
680 mpt_callbacks[cb_idx](ioc, smid, VF_ID, reply);
681 if (reply)
682 _base_display_reply_info(ioc, smid, VF_ID,
683 reply);
684 mpt2sas_base_free_smid(ioc, smid);
685 }
686 if (!smid)
687 _base_async_event(ioc, VF_ID, reply);
688
689 /* reply free queue handling */
690 if (reply) {
691 ioc->reply_free_host_index =
692 (ioc->reply_free_host_index ==
693 (ioc->reply_free_queue_depth - 1)) ?
694 0 : ioc->reply_free_host_index + 1;
695 ioc->reply_free[ioc->reply_free_host_index] =
696 cpu_to_le32(reply);
697 writel(ioc->reply_free_host_index,
698 &ioc->chip->ReplyFreeHostIndex);
699 wmb();
700 }
701
702 next:
703 post_index_next = (post_index == (ioc->reply_post_queue_depth -
704 1)) ? 0 : post_index + 1;
705 request_desript_type =
706 ioc->reply_post_free[post_index_next].Default.ReplyFlags
707 & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
708 completed_cmds++;
709 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
710 goto out;
711 post_index = post_index_next;
712 } while (1);
713
714 out:
715
716 if (!completed_cmds)
717 return IRQ_NONE;
718
719 /* reply post descriptor handling */
720 post_index_next = ioc->reply_post_host_index;
721 for (i = 0 ; i < completed_cmds; i++) {
722 post_index = post_index_next;
723 /* poison the reply post descriptor */
724 ioc->reply_post_free[post_index_next].Words = ~0ULL;
725 post_index_next = (post_index ==
726 (ioc->reply_post_queue_depth - 1))
727 ? 0 : post_index + 1;
728 }
729 ioc->reply_post_host_index = post_index_next;
730 writel(post_index_next, &ioc->chip->ReplyPostHostIndex);
731 wmb();
732 return IRQ_HANDLED;
733}
734
735/**
736 * mpt2sas_base_release_callback_handler - clear interupt callback handler
737 * @cb_idx: callback index
738 *
739 * Return nothing.
740 */
741void
742mpt2sas_base_release_callback_handler(u8 cb_idx)
743{
744 mpt_callbacks[cb_idx] = NULL;
745}
746
747/**
748 * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler
749 * @cb_func: callback function
750 *
751 * Returns cb_func.
752 */
753u8
754mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func)
755{
756 u8 cb_idx;
757
758 for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
759 if (mpt_callbacks[cb_idx] == NULL)
760 break;
761
762 mpt_callbacks[cb_idx] = cb_func;
763 return cb_idx;
764}
765
766/**
767 * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler
768 *
769 * Return nothing.
770 */
771void
772mpt2sas_base_initialize_callback_handler(void)
773{
774 u8 cb_idx;
775
776 for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
777 mpt2sas_base_release_callback_handler(cb_idx);
778}
779
780/**
781 * mpt2sas_base_build_zero_len_sge - build zero length sg entry
782 * @ioc: per adapter object
783 * @paddr: virtual address for SGE
784 *
785 * Create a zero length scatter gather entry to insure the IOCs hardware has
786 * something to use if the target device goes brain dead and tries
787 * to send data even when none is asked for.
788 *
789 * Return nothing.
790 */
791void
792mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr)
793{
794 u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
795 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
796 MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
797 MPI2_SGE_FLAGS_SHIFT);
798 ioc->base_add_sg_single(paddr, flags_length, -1);
799}
800
801/**
802 * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
803 * @paddr: virtual address for SGE
804 * @flags_length: SGE flags and data transfer length
805 * @dma_addr: Physical address
806 *
807 * Return nothing.
808 */
809static void
810_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
811{
812 Mpi2SGESimple32_t *sgel = paddr;
813
814 flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
815 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
816 sgel->FlagsLength = cpu_to_le32(flags_length);
817 sgel->Address = cpu_to_le32(dma_addr);
818}
819
820
821/**
822 * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
823 * @paddr: virtual address for SGE
824 * @flags_length: SGE flags and data transfer length
825 * @dma_addr: Physical address
826 *
827 * Return nothing.
828 */
829static void
830_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
831{
832 Mpi2SGESimple64_t *sgel = paddr;
833
834 flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
835 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
836 sgel->FlagsLength = cpu_to_le32(flags_length);
837 sgel->Address = cpu_to_le64(dma_addr);
838}
839
840#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
841
842/**
843 * _base_config_dma_addressing - set dma addressing
844 * @ioc: per adapter object
845 * @pdev: PCI device struct
846 *
847 * Returns 0 for success, non-zero for failure.
848 */
849static int
850_base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
851{
852 struct sysinfo s;
853 char *desc = NULL;
854
855 if (sizeof(dma_addr_t) > 4) {
856 const uint64_t required_mask =
857 dma_get_required_mask(&pdev->dev);
858 if ((required_mask > DMA_32BIT_MASK) && !pci_set_dma_mask(pdev,
859 DMA_64BIT_MASK) && !pci_set_consistent_dma_mask(pdev,
860 DMA_64BIT_MASK)) {
861 ioc->base_add_sg_single = &_base_add_sg_single_64;
862 ioc->sge_size = sizeof(Mpi2SGESimple64_t);
863 desc = "64";
864 goto out;
865 }
866 }
867
868 if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
869 && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
870 ioc->base_add_sg_single = &_base_add_sg_single_32;
871 ioc->sge_size = sizeof(Mpi2SGESimple32_t);
872 desc = "32";
873 } else
874 return -ENODEV;
875
876 out:
877 si_meminfo(&s);
878 printk(MPT2SAS_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, "
879 "total mem (%ld kB)\n", ioc->name, desc, convert_to_kb(s.totalram));
880
881 return 0;
882}
883
884/**
885 * _base_save_msix_table - backup msix vector table
886 * @ioc: per adapter object
887 *
888 * This address an errata where diag reset clears out the table
889 */
890static void
891_base_save_msix_table(struct MPT2SAS_ADAPTER *ioc)
892{
893 int i;
894
895 if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
896 return;
897
898 for (i = 0; i < ioc->msix_vector_count; i++)
899 ioc->msix_table_backup[i] = ioc->msix_table[i];
900}
901
902/**
903 * _base_restore_msix_table - this restores the msix vector table
904 * @ioc: per adapter object
905 *
906 */
907static void
908_base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc)
909{
910 int i;
911
912 if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
913 return;
914
915 for (i = 0; i < ioc->msix_vector_count; i++)
916 ioc->msix_table[i] = ioc->msix_table_backup[i];
917}
918
919/**
920 * _base_check_enable_msix - checks MSIX capabable.
921 * @ioc: per adapter object
922 *
923 * Check to see if card is capable of MSIX, and set number
924 * of avaliable msix vectors
925 */
926static int
927_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
928{
929 int base;
930 u16 message_control;
931 u32 msix_table_offset;
932
933 base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
934 if (!base) {
935 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
936 "supported\n", ioc->name));
937 return -EINVAL;
938 }
939
940 /* get msix vector count */
941 pci_read_config_word(ioc->pdev, base + 2, &message_control);
942 ioc->msix_vector_count = (message_control & 0x3FF) + 1;
943
944 /* get msix table */
945 pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset);
946 msix_table_offset &= 0xFFFFFFF8;
947 ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset);
948
949 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
950 "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name,
951 ioc->msix_vector_count, msix_table_offset, ioc->msix_table));
952 return 0;
953}
954
955/**
956 * _base_disable_msix - disables msix
957 * @ioc: per adapter object
958 *
959 */
960static void
961_base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
962{
963 if (ioc->msix_enable) {
964 pci_disable_msix(ioc->pdev);
965 kfree(ioc->msix_table_backup);
966 ioc->msix_table_backup = NULL;
967 ioc->msix_enable = 0;
968 }
969}
970
971/**
972 * _base_enable_msix - enables msix, failback to io_apic
973 * @ioc: per adapter object
974 *
975 */
976static int
977_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
978{
979 struct msix_entry entries;
980 int r;
981 u8 try_msix = 0;
982
983 if (msix_disable == -1 || msix_disable == 0)
984 try_msix = 1;
985
986 if (!try_msix)
987 goto try_ioapic;
988
989 if (_base_check_enable_msix(ioc) != 0)
990 goto try_ioapic;
991
992 ioc->msix_table_backup = kcalloc(ioc->msix_vector_count,
993 sizeof(u32), GFP_KERNEL);
994 if (!ioc->msix_table_backup) {
995 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
996 "msix_table_backup failed!!!\n", ioc->name));
997 goto try_ioapic;
998 }
999
1000 memset(&entries, 0, sizeof(struct msix_entry));
1001 r = pci_enable_msix(ioc->pdev, &entries, 1);
1002 if (r) {
1003 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix "
1004 "failed (r=%d) !!!\n", ioc->name, r));
1005 goto try_ioapic;
1006 }
1007
1008 r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED,
1009 ioc->name, ioc);
1010 if (r) {
1011 dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate "
1012 "interrupt %d !!!\n", ioc->name, entries.vector));
1013 pci_disable_msix(ioc->pdev);
1014 goto try_ioapic;
1015 }
1016
1017 ioc->pci_irq = entries.vector;
1018 ioc->msix_enable = 1;
1019 return 0;
1020
1021/* failback to io_apic interrupt routing */
1022 try_ioapic:
1023
1024 r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED,
1025 ioc->name, ioc);
1026 if (r) {
1027 printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
1028 ioc->name, ioc->pdev->irq);
1029 r = -EBUSY;
1030 goto out_fail;
1031 }
1032
1033 ioc->pci_irq = ioc->pdev->irq;
1034 return 0;
1035
1036 out_fail:
1037 return r;
1038}
1039
1040/**
1041 * mpt2sas_base_map_resources - map in controller resources (io/irq/memap)
1042 * @ioc: per adapter object
1043 *
1044 * Returns 0 for success, non-zero for failure.
1045 */
1046int
1047mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
1048{
1049 struct pci_dev *pdev = ioc->pdev;
1050 u32 memap_sz;
1051 u32 pio_sz;
1052 int i, r = 0;
1053
1054 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n",
1055 ioc->name, __func__));
1056
1057 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1058 if (pci_enable_device_mem(pdev)) {
1059 printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: "
1060 "failed\n", ioc->name);
1061 return -ENODEV;
1062 }
1063
1064
1065 if (pci_request_selected_regions(pdev, ioc->bars,
1066 MPT2SAS_DRIVER_NAME)) {
1067 printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: "
1068 "failed\n", ioc->name);
1069 r = -ENODEV;
1070 goto out_fail;
1071 }
1072
1073 pci_set_master(pdev);
1074
1075 if (_base_config_dma_addressing(ioc, pdev) != 0) {
1076 printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n",
1077 ioc->name, pci_name(pdev));
1078 r = -ENODEV;
1079 goto out_fail;
1080 }
1081
1082 for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) {
1083 if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO) {
1084 if (pio_sz)
1085 continue;
1086 ioc->pio_chip = pci_resource_start(pdev, i);
1087 pio_sz = pci_resource_len(pdev, i);
1088 } else {
1089 if (memap_sz)
1090 continue;
1091 ioc->chip_phys = pci_resource_start(pdev, i);
1092 memap_sz = pci_resource_len(pdev, i);
1093 ioc->chip = ioremap(ioc->chip_phys, memap_sz);
1094 if (ioc->chip == NULL) {
1095 printk(MPT2SAS_ERR_FMT "unable to map adapter "
1096 "memory!\n", ioc->name);
1097 r = -EINVAL;
1098 goto out_fail;
1099 }
1100 }
1101 }
1102
1103 pci_set_drvdata(pdev, ioc->shost);
1104 _base_mask_interrupts(ioc);
1105 r = _base_enable_msix(ioc);
1106 if (r)
1107 goto out_fail;
1108
1109 printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
1110 ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
1111 "IO-APIC enabled"), ioc->pci_irq);
1112 printk(MPT2SAS_INFO_FMT "iomem(0x%lx), mapped(0x%p), size(%d)\n",
1113 ioc->name, ioc->chip_phys, ioc->chip, memap_sz);
1114 printk(MPT2SAS_INFO_FMT "ioport(0x%lx), size(%d)\n",
1115 ioc->name, ioc->pio_chip, pio_sz);
1116
1117 return 0;
1118
1119 out_fail:
1120 if (ioc->chip_phys)
1121 iounmap(ioc->chip);
1122 ioc->chip_phys = 0;
1123 ioc->pci_irq = -1;
1124 pci_release_selected_regions(ioc->pdev, ioc->bars);
1125 pci_disable_device(pdev);
1126 pci_set_drvdata(pdev, NULL);
1127 return r;
1128}
1129
1130/**
1131 * mpt2sas_base_get_msg_frame_dma - obtain request mf pointer phys addr
1132 * @ioc: per adapter object
1133 * @smid: system request message index(smid zero is invalid)
1134 *
1135 * Returns phys pointer to message frame.
1136 */
1137dma_addr_t
1138mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1139{
1140 return ioc->request_dma + (smid * ioc->request_sz);
1141}
1142
1143/**
1144 * mpt2sas_base_get_msg_frame - obtain request mf pointer
1145 * @ioc: per adapter object
1146 * @smid: system request message index(smid zero is invalid)
1147 *
1148 * Returns virt pointer to message frame.
1149 */
1150void *
1151mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1152{
1153 return (void *)(ioc->request + (smid * ioc->request_sz));
1154}
1155
1156/**
1157 * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request
1158 * @ioc: per adapter object
1159 * @smid: system request message index
1160 *
1161 * Returns virt pointer to sense buffer.
1162 */
1163void *
1164mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1165{
1166 return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
1167}
1168
1169/**
1170 * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request
1171 * @ioc: per adapter object
1172 * @smid: system request message index
1173 *
1174 * Returns phys pointer to sense buffer.
1175 */
1176dma_addr_t
1177mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1178{
1179 return ioc->sense_dma + ((smid - 1) * SCSI_SENSE_BUFFERSIZE);
1180}
1181
1182/**
1183 * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address
1184 * @ioc: per adapter object
1185 * @phys_addr: lower 32 physical addr of the reply
1186 *
1187 * Converts 32bit lower physical addr into a virt address.
1188 */
1189void *
1190mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr)
1191{
1192 if (!phys_addr)
1193 return NULL;
1194 return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
1195}
1196
1197/**
1198 * mpt2sas_base_get_smid - obtain a free smid
1199 * @ioc: per adapter object
1200 * @cb_idx: callback index
1201 *
1202 * Returns smid (zero is invalid)
1203 */
1204u16
1205mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
1206{
1207 unsigned long flags;
1208 struct request_tracker *request;
1209 u16 smid;
1210
1211 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1212 if (list_empty(&ioc->free_list)) {
1213 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1214 printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
1215 ioc->name, __func__);
1216 return 0;
1217 }
1218
1219 request = list_entry(ioc->free_list.next,
1220 struct request_tracker, tracker_list);
1221 request->cb_idx = cb_idx;
1222 smid = request->smid;
1223 list_del(&request->tracker_list);
1224 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1225 return smid;
1226}
1227
1228
1229/**
1230 * mpt2sas_base_free_smid - put smid back on free_list
1231 * @ioc: per adapter object
1232 * @smid: system request message index
1233 *
1234 * Return nothing.
1235 */
1236void
1237mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
1238{
1239 unsigned long flags;
1240
1241 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1242 ioc->scsi_lookup[smid - 1].cb_idx = 0xFF;
1243 list_add_tail(&ioc->scsi_lookup[smid - 1].tracker_list,
1244 &ioc->free_list);
1245 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1246
1247 /*
1248 * See _wait_for_commands_to_complete() call with regards to this code.
1249 */
1250 if (ioc->shost_recovery && ioc->pending_io_count) {
1251 if (ioc->pending_io_count == 1)
1252 wake_up(&ioc->reset_wq);
1253 ioc->pending_io_count--;
1254 }
1255}
1256
1257/**
1258 * _base_writeq - 64 bit write to MMIO
1259 * @ioc: per adapter object
1260 * @b: data payload
1261 * @addr: address in MMIO space
1262 * @writeq_lock: spin lock
1263 *
1264 * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
1265 * care of 32 bit environment where its not quarenteed to send the entire word
1266 * in one transfer.
1267 */
1268#ifndef writeq
1269static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
1270 spinlock_t *writeq_lock)
1271{
1272 unsigned long flags;
1273 __u64 data_out = cpu_to_le64(b);
1274
1275 spin_lock_irqsave(writeq_lock, flags);
1276 writel((u32)(data_out), addr);
1277 writel((u32)(data_out >> 32), (addr + 4));
1278 spin_unlock_irqrestore(writeq_lock, flags);
1279}
1280#else
1281static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
1282 spinlock_t *writeq_lock)
1283{
1284 writeq(cpu_to_le64(b), addr);
1285}
1286#endif
1287
1288/**
1289 * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
1290 * @ioc: per adapter object
1291 * @smid: system request message index
1292 * @vf_id: virtual function id
1293 * @handle: device handle
1294 *
1295 * Return nothing.
1296 */
1297void
1298mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id,
1299 u16 handle)
1300{
1301 Mpi2RequestDescriptorUnion_t descriptor;
1302 u64 *request = (u64 *)&descriptor;
1303
1304
1305 descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
1306 descriptor.SCSIIO.VF_ID = vf_id;
1307 descriptor.SCSIIO.SMID = cpu_to_le16(smid);
1308 descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
1309 descriptor.SCSIIO.LMID = 0;
1310 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1311 &ioc->scsi_lookup_lock);
1312}
1313
1314
1315/**
1316 * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware
1317 * @ioc: per adapter object
1318 * @smid: system request message index
1319 * @vf_id: virtual function id
1320 *
1321 * Return nothing.
1322 */
1323void
1324mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid,
1325 u8 vf_id)
1326{
1327 Mpi2RequestDescriptorUnion_t descriptor;
1328 u64 *request = (u64 *)&descriptor;
1329
1330 descriptor.HighPriority.RequestFlags =
1331 MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
1332 descriptor.HighPriority.VF_ID = vf_id;
1333 descriptor.HighPriority.SMID = cpu_to_le16(smid);
1334 descriptor.HighPriority.LMID = 0;
1335 descriptor.HighPriority.Reserved1 = 0;
1336 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1337 &ioc->scsi_lookup_lock);
1338}
1339
1340/**
1341 * mpt2sas_base_put_smid_default - Default, primarily used for config pages
1342 * @ioc: per adapter object
1343 * @smid: system request message index
1344 * @vf_id: virtual function id
1345 *
1346 * Return nothing.
1347 */
1348void
1349mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id)
1350{
1351 Mpi2RequestDescriptorUnion_t descriptor;
1352 u64 *request = (u64 *)&descriptor;
1353
1354 descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1355 descriptor.Default.VF_ID = vf_id;
1356 descriptor.Default.SMID = cpu_to_le16(smid);
1357 descriptor.Default.LMID = 0;
1358 descriptor.Default.DescriptorTypeDependent = 0;
1359 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1360 &ioc->scsi_lookup_lock);
1361}
1362
1363/**
1364 * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware
1365 * @ioc: per adapter object
1366 * @smid: system request message index
1367 * @vf_id: virtual function id
1368 * @io_index: value used to track the IO
1369 *
1370 * Return nothing.
1371 */
1372void
1373mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
1374 u8 vf_id, u16 io_index)
1375{
1376 Mpi2RequestDescriptorUnion_t descriptor;
1377 u64 *request = (u64 *)&descriptor;
1378
1379 descriptor.SCSITarget.RequestFlags =
1380 MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
1381 descriptor.SCSITarget.VF_ID = vf_id;
1382 descriptor.SCSITarget.SMID = cpu_to_le16(smid);
1383 descriptor.SCSITarget.LMID = 0;
1384 descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
1385 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
1386 &ioc->scsi_lookup_lock);
1387}
1388
1389/**
1390 * _base_display_ioc_capabilities - Disply IOC's capabilities.
1391 * @ioc: per adapter object
1392 *
1393 * Return nothing.
1394 */
1395static void
1396_base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
1397{
1398 int i = 0;
1399 char desc[16];
1400 u8 revision;
1401 u32 iounit_pg1_flags;
1402
1403 pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
1404 strncpy(desc, ioc->manu_pg0.ChipName, 16);
1405 printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
1406 "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
1407 ioc->name, desc,
1408 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
1409 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
1410 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
1411 ioc->facts.FWVersion.Word & 0x000000FF,
1412 revision,
1413 (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24,
1414 (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16,
1415 (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
1416 ioc->bios_pg3.BiosVersion & 0x000000FF);
1417
1418 printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
1419
1420 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
1421 printk("Initiator");
1422 i++;
1423 }
1424
1425 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
1426 printk("%sTarget", i ? "," : "");
1427 i++;
1428 }
1429
1430 i = 0;
1431 printk("), ");
1432 printk("Capabilities=(");
1433
1434 if (ioc->facts.IOCCapabilities &
1435 MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
1436 printk("Raid");
1437 i++;
1438 }
1439
1440 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
1441 printk("%sTLR", i ? "," : "");
1442 i++;
1443 }
1444
1445 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
1446 printk("%sMulticast", i ? "," : "");
1447 i++;
1448 }
1449
1450 if (ioc->facts.IOCCapabilities &
1451 MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
1452 printk("%sBIDI Target", i ? "," : "");
1453 i++;
1454 }
1455
1456 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
1457 printk("%sEEDP", i ? "," : "");
1458 i++;
1459 }
1460
1461 if (ioc->facts.IOCCapabilities &
1462 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
1463 printk("%sSnapshot Buffer", i ? "," : "");
1464 i++;
1465 }
1466
1467 if (ioc->facts.IOCCapabilities &
1468 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
1469 printk("%sDiag Trace Buffer", i ? "," : "");
1470 i++;
1471 }
1472
1473 if (ioc->facts.IOCCapabilities &
1474 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
1475 printk("%sTask Set Full", i ? "," : "");
1476 i++;
1477 }
1478
1479 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
1480 if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
1481 printk("%sNCQ", i ? "," : "");
1482 i++;
1483 }
1484
1485 printk(")\n");
1486}
1487
1488/**
1489 * _base_static_config_pages - static start of day config pages
1490 * @ioc: per adapter object
1491 *
1492 * Return nothing.
1493 */
1494static void
1495_base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
1496{
1497 Mpi2ConfigReply_t mpi_reply;
1498 u32 iounit_pg1_flags;
1499
1500 mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
1501 mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
1502 mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
1503 mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
1504 mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
1505 mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
1506 _base_display_ioc_capabilities(ioc);
1507
1508 /*
1509 * Enable task_set_full handling in iounit_pg1 when the
1510 * facts capabilities indicate that its supported.
1511 */
1512 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
1513 if ((ioc->facts.IOCCapabilities &
1514 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
1515 iounit_pg1_flags &=
1516 ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
1517 else
1518 iounit_pg1_flags |=
1519 MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
1520 ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
1521 mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, ioc->iounit_pg1);
1522}
1523
1524/**
1525 * _base_release_memory_pools - release memory
1526 * @ioc: per adapter object
1527 *
1528 * Free memory allocated from _base_allocate_memory_pools.
1529 *
1530 * Return nothing.
1531 */
1532static void
1533_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
1534{
1535 dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1536 __func__));
1537
1538 if (ioc->request) {
1539 pci_free_consistent(ioc->pdev, ioc->request_dma_sz,
1540 ioc->request, ioc->request_dma);
1541 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "request_pool(0x%p)"
1542 ": free\n", ioc->name, ioc->request));
1543 ioc->request = NULL;
1544 }
1545
1546 if (ioc->sense) {
1547 pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
1548 if (ioc->sense_dma_pool)
1549 pci_pool_destroy(ioc->sense_dma_pool);
1550 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_pool(0x%p)"
1551 ": free\n", ioc->name, ioc->sense));
1552 ioc->sense = NULL;
1553 }
1554
1555 if (ioc->reply) {
1556 pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma);
1557 if (ioc->reply_dma_pool)
1558 pci_pool_destroy(ioc->reply_dma_pool);
1559 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_pool(0x%p)"
1560 ": free\n", ioc->name, ioc->reply));
1561 ioc->reply = NULL;
1562 }
1563
1564 if (ioc->reply_free) {
1565 pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free,
1566 ioc->reply_free_dma);
1567 if (ioc->reply_free_dma_pool)
1568 pci_pool_destroy(ioc->reply_free_dma_pool);
1569 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_pool"
1570 "(0x%p): free\n", ioc->name, ioc->reply_free));
1571 ioc->reply_free = NULL;
1572 }
1573
1574 if (ioc->reply_post_free) {
1575 pci_pool_free(ioc->reply_post_free_dma_pool,
1576 ioc->reply_post_free, ioc->reply_post_free_dma);
1577 if (ioc->reply_post_free_dma_pool)
1578 pci_pool_destroy(ioc->reply_post_free_dma_pool);
1579 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
1580 "reply_post_free_pool(0x%p): free\n", ioc->name,
1581 ioc->reply_post_free));
1582 ioc->reply_post_free = NULL;
1583 }
1584
1585 if (ioc->config_page) {
1586 dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
1587 "config_page(0x%p): free\n", ioc->name,
1588 ioc->config_page));
1589 pci_free_consistent(ioc->pdev, ioc->config_page_sz,
1590 ioc->config_page, ioc->config_page_dma);
1591 }
1592
1593 kfree(ioc->scsi_lookup);
1594}
1595
1596
1597/**
1598 * _base_allocate_memory_pools - allocate start of day memory pools
1599 * @ioc: per adapter object
1600 * @sleep_flag: CAN_SLEEP or NO_SLEEP
1601 *
1602 * Returns 0 success, anything else error
1603 */
1604static int
1605_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
1606{
1607 Mpi2IOCFactsReply_t *facts;
1608 u32 queue_size, queue_diff;
1609 u16 max_sge_elements;
1610 u16 num_of_reply_frames;
1611 u16 chains_needed_per_io;
1612 u32 sz, total_sz;
1613 u16 i;
1614 u32 retry_sz;
1615 u16 max_request_credit;
1616
1617 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1618 __func__));
1619
1620 retry_sz = 0;
1621 facts = &ioc->facts;
1622
1623 /* command line tunables for max sgl entries */
1624 if (max_sgl_entries != -1) {
1625 ioc->shost->sg_tablesize = (max_sgl_entries <
1626 MPT2SAS_SG_DEPTH) ? max_sgl_entries :
1627 MPT2SAS_SG_DEPTH;
1628 } else {
1629 ioc->shost->sg_tablesize = MPT2SAS_SG_DEPTH;
1630 }
1631
1632 /* command line tunables for max controller queue depth */
1633 if (max_queue_depth != -1) {
1634 max_request_credit = (max_queue_depth < facts->RequestCredit)
1635 ? max_queue_depth : facts->RequestCredit;
1636 } else {
1637 max_request_credit = (facts->RequestCredit >
1638 MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE :
1639 facts->RequestCredit;
1640 }
1641 ioc->request_depth = max_request_credit;
1642
1643 /* request frame size */
1644 ioc->request_sz = facts->IOCRequestFrameSize * 4;
1645
1646 /* reply frame size */
1647 ioc->reply_sz = facts->ReplyFrameSize * 4;
1648
1649 retry_allocation:
1650 total_sz = 0;
1651 /* calculate number of sg elements left over in the 1st frame */
1652 max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) -
1653 sizeof(Mpi2SGEIOUnion_t)) + ioc->sge_size);
1654 ioc->max_sges_in_main_message = max_sge_elements/ioc->sge_size;
1655
1656 /* now do the same for a chain buffer */
1657 max_sge_elements = ioc->request_sz - ioc->sge_size;
1658 ioc->max_sges_in_chain_message = max_sge_elements/ioc->sge_size;
1659
1660 ioc->chain_offset_value_for_main_message =
1661 ((sizeof(Mpi2SCSIIORequest_t) - sizeof(Mpi2SGEIOUnion_t)) +
1662 (ioc->max_sges_in_chain_message * ioc->sge_size)) / 4;
1663
1664 /*
1665 * MPT2SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE
1666 */
1667 chains_needed_per_io = ((ioc->shost->sg_tablesize -
1668 ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message)
1669 + 1;
1670 if (chains_needed_per_io > facts->MaxChainDepth) {
1671 chains_needed_per_io = facts->MaxChainDepth;
1672 ioc->shost->sg_tablesize = min_t(u16,
1673 ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message
1674 * chains_needed_per_io), ioc->shost->sg_tablesize);
1675 }
1676 ioc->chains_needed_per_io = chains_needed_per_io;
1677
1678 /* reply free queue sizing - taking into account for events */
1679 num_of_reply_frames = ioc->request_depth + 32;
1680
1681 /* number of replies frames can't be a multiple of 16 */
1682 /* decrease number of reply frames by 1 */
1683 if (!(num_of_reply_frames % 16))
1684 num_of_reply_frames--;
1685
1686 /* calculate number of reply free queue entries
1687 * (must be multiple of 16)
1688 */
1689
1690 /* (we know reply_free_queue_depth is not a multiple of 16) */
1691 queue_size = num_of_reply_frames;
1692 queue_size += 16 - (queue_size % 16);
1693 ioc->reply_free_queue_depth = queue_size;
1694
1695 /* reply descriptor post queue sizing */
1696 /* this size should be the number of request frames + number of reply
1697 * frames
1698 */
1699
1700 queue_size = ioc->request_depth + num_of_reply_frames + 1;
1701 /* round up to 16 byte boundary */
1702 if (queue_size % 16)
1703 queue_size += 16 - (queue_size % 16);
1704
1705 /* check against IOC maximum reply post queue depth */
1706 if (queue_size > facts->MaxReplyDescriptorPostQueueDepth) {
1707 queue_diff = queue_size -
1708 facts->MaxReplyDescriptorPostQueueDepth;
1709
1710 /* round queue_diff up to multiple of 16 */
1711 if (queue_diff % 16)
1712 queue_diff += 16 - (queue_diff % 16);
1713
1714 /* adjust request_depth, reply_free_queue_depth,
1715 * and queue_size
1716 */
1717 ioc->request_depth -= queue_diff;
1718 ioc->reply_free_queue_depth -= queue_diff;
1719 queue_size -= queue_diff;
1720 }
1721 ioc->reply_post_queue_depth = queue_size;
1722
1723 /* max scsi host queue depth */
1724 ioc->shost->can_queue = ioc->request_depth - INTERNAL_CMDS_COUNT;
1725 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host queue: depth"
1726 "(%d)\n", ioc->name, ioc->shost->can_queue));
1727
1728 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: "
1729 "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
1730 "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message,
1731 ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
1732 ioc->chains_needed_per_io));
1733
1734 /* contiguous pool for request and chains, 16 byte align, one extra "
1735 * "frame for smid=0
1736 */
1737 ioc->chain_depth = ioc->chains_needed_per_io * ioc->request_depth;
1738 sz = ((ioc->request_depth + 1 + ioc->chain_depth) * ioc->request_sz);
1739
1740 ioc->request_dma_sz = sz;
1741 ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma);
1742 if (!ioc->request) {
1743 printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
1744 "failed: req_depth(%d), chains_per_io(%d), frame_sz(%d), "
1745 "total(%d kB)\n", ioc->name, ioc->request_depth,
1746 ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
1747 if (ioc->request_depth < MPT2SAS_SAS_QUEUE_DEPTH)
1748 goto out;
1749 retry_sz += 64;
1750 ioc->request_depth = max_request_credit - retry_sz;
1751 goto retry_allocation;
1752 }
1753
1754 if (retry_sz)
1755 printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
1756 "succeed: req_depth(%d), chains_per_io(%d), frame_sz(%d), "
1757 "total(%d kb)\n", ioc->name, ioc->request_depth,
1758 ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
1759
1760 ioc->chain = ioc->request + ((ioc->request_depth + 1) *
1761 ioc->request_sz);
1762 ioc->chain_dma = ioc->request_dma + ((ioc->request_depth + 1) *
1763 ioc->request_sz);
1764 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
1765 "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
1766 ioc->request, ioc->request_depth, ioc->request_sz,
1767 ((ioc->request_depth + 1) * ioc->request_sz)/1024));
1768 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth"
1769 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain,
1770 ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
1771 ioc->request_sz))/1024));
1772 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
1773 ioc->name, (unsigned long long) ioc->request_dma));
1774 total_sz += sz;
1775
1776 ioc->scsi_lookup = kcalloc(ioc->request_depth,
1777 sizeof(struct request_tracker), GFP_KERNEL);
1778 if (!ioc->scsi_lookup) {
1779 printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n",
1780 ioc->name);
1781 goto out;
1782 }
1783
1784 /* initialize some bits */
1785 for (i = 0; i < ioc->request_depth; i++)
1786 ioc->scsi_lookup[i].smid = i + 1;
1787
1788 /* sense buffers, 4 byte align */
1789 sz = ioc->request_depth * SCSI_SENSE_BUFFERSIZE;
1790 ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
1791 0);
1792 if (!ioc->sense_dma_pool) {
1793 printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_create failed\n",
1794 ioc->name);
1795 goto out;
1796 }
1797 ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL,
1798 &ioc->sense_dma);
1799 if (!ioc->sense) {
1800 printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_alloc failed\n",
1801 ioc->name);
1802 goto out;
1803 }
1804 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
1805 "sense pool(0x%p): depth(%d), element_size(%d), pool_size"
1806 "(%d kB)\n", ioc->name, ioc->sense, ioc->request_depth,
1807 SCSI_SENSE_BUFFERSIZE, sz/1024));
1808 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n",
1809 ioc->name, (unsigned long long)ioc->sense_dma));
1810 total_sz += sz;
1811
1812 /* reply pool, 4 byte align */
1813 sz = ioc->reply_free_queue_depth * ioc->reply_sz;
1814 ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4,
1815 0);
1816 if (!ioc->reply_dma_pool) {
1817 printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_create failed\n",
1818 ioc->name);
1819 goto out;
1820 }
1821 ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL,
1822 &ioc->reply_dma);
1823 if (!ioc->reply) {
1824 printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_alloc failed\n",
1825 ioc->name);
1826 goto out;
1827 }
1828 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
1829 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
1830 ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
1831 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_dma(0x%llx)\n",
1832 ioc->name, (unsigned long long)ioc->reply_dma));
1833 total_sz += sz;
1834
1835 /* reply free queue, 16 byte align */
1836 sz = ioc->reply_free_queue_depth * 4;
1837 ioc->reply_free_dma_pool = pci_pool_create("reply_free pool",
1838 ioc->pdev, sz, 16, 0);
1839 if (!ioc->reply_free_dma_pool) {
1840 printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_create "
1841 "failed\n", ioc->name);
1842 goto out;
1843 }
1844 ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL,
1845 &ioc->reply_free_dma);
1846 if (!ioc->reply_free) {
1847 printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_alloc "
1848 "failed\n", ioc->name);
1849 goto out;
1850 }
1851 memset(ioc->reply_free, 0, sz);
1852 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free pool(0x%p): "
1853 "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name,
1854 ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024));
1855 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_dma"
1856 "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma));
1857 total_sz += sz;
1858
1859 /* reply post queue, 16 byte align */
1860 sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t);
1861 ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
1862 ioc->pdev, sz, 16, 0);
1863 if (!ioc->reply_post_free_dma_pool) {
1864 printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_create "
1865 "failed\n", ioc->name);
1866 goto out;
1867 }
1868 ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool ,
1869 GFP_KERNEL, &ioc->reply_post_free_dma);
1870 if (!ioc->reply_post_free) {
1871 printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_alloc "
1872 "failed\n", ioc->name);
1873 goto out;
1874 }
1875 memset(ioc->reply_post_free, 0, sz);
1876 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply post free pool"
1877 "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
1878 ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8,
1879 sz/1024));
1880 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_post_free_dma = "
1881 "(0x%llx)\n", ioc->name, (unsigned long long)
1882 ioc->reply_post_free_dma));
1883 total_sz += sz;
1884
1885 ioc->config_page_sz = 512;
1886 ioc->config_page = pci_alloc_consistent(ioc->pdev,
1887 ioc->config_page_sz, &ioc->config_page_dma);
1888 if (!ioc->config_page) {
1889 printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc "
1890 "failed\n", ioc->name);
1891 goto out;
1892 }
1893 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size"
1894 "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz));
1895 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma"
1896 "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma));
1897 total_sz += ioc->config_page_sz;
1898
1899 printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n",
1900 ioc->name, total_sz/1024);
1901 printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), "
1902 "Max Controller Queue Depth(%d)\n",
1903 ioc->name, ioc->shost->can_queue, facts->RequestCredit);
1904 printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n",
1905 ioc->name, ioc->shost->sg_tablesize);
1906 return 0;
1907
1908 out:
1909 _base_release_memory_pools(ioc);
1910 return -ENOMEM;
1911}
1912
1913
1914/**
1915 * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter.
1916 * @ioc: Pointer to MPT_ADAPTER structure
1917 * @cooked: Request raw or cooked IOC state
1918 *
1919 * Returns all IOC Doorbell register bits if cooked==0, else just the
1920 * Doorbell bits in MPI_IOC_STATE_MASK.
1921 */
1922u32
1923mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked)
1924{
1925 u32 s, sc;
1926
1927 s = readl(&ioc->chip->Doorbell);
1928 sc = s & MPI2_IOC_STATE_MASK;
1929 return cooked ? sc : s;
1930}
1931
1932/**
1933 * _base_wait_on_iocstate - waiting on a particular ioc state
1934 * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
1935 * @timeout: timeout in second
1936 * @sleep_flag: CAN_SLEEP or NO_SLEEP
1937 *
1938 * Returns 0 for success, non-zero for failure.
1939 */
1940static int
1941_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
1942 int sleep_flag)
1943{
1944 u32 count, cntdn;
1945 u32 current_state;
1946
1947 count = 0;
1948 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
1949 do {
1950 current_state = mpt2sas_base_get_iocstate(ioc, 1);
1951 if (current_state == ioc_state)
1952 return 0;
1953 if (count && current_state == MPI2_IOC_STATE_FAULT)
1954 break;
1955 if (sleep_flag == CAN_SLEEP)
1956 msleep(1);
1957 else
1958 udelay(500);
1959 count++;
1960 } while (--cntdn);
1961
1962 return current_state;
1963}
1964
1965/**
1966 * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
1967 * a write to the doorbell)
1968 * @ioc: per adapter object
1969 * @timeout: timeout in second
1970 * @sleep_flag: CAN_SLEEP or NO_SLEEP
1971 *
1972 * Returns 0 for success, non-zero for failure.
1973 *
1974 * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
1975 */
1976static int
1977_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,
1978 int sleep_flag)
1979{
1980 u32 cntdn, count;
1981 u32 int_status;
1982
1983 count = 0;
1984 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
1985 do {
1986 int_status = readl(&ioc->chip->HostInterruptStatus);
1987 if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
1988 dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
1989 "successfull count(%d), timeout(%d)\n", ioc->name,
1990 __func__, count, timeout));
1991 return 0;
1992 }
1993 if (sleep_flag == CAN_SLEEP)
1994 msleep(1);
1995 else
1996 udelay(500);
1997 count++;
1998 } while (--cntdn);
1999
2000 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2001 "int_status(%x)!\n", ioc->name, __func__, count, int_status);
2002 return -EFAULT;
2003}
2004
2005/**
2006 * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
2007 * @ioc: per adapter object
2008 * @timeout: timeout in second
2009 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2010 *
2011 * Returns 0 for success, non-zero for failure.
2012 *
2013 * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
2014 * doorbell.
2015 */
2016static int
2017_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,
2018 int sleep_flag)
2019{
2020 u32 cntdn, count;
2021 u32 int_status;
2022 u32 doorbell;
2023
2024 count = 0;
2025 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2026 do {
2027 int_status = readl(&ioc->chip->HostInterruptStatus);
2028 if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
2029 dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2030 "successfull count(%d), timeout(%d)\n", ioc->name,
2031 __func__, count, timeout));
2032 return 0;
2033 } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
2034 doorbell = readl(&ioc->chip->Doorbell);
2035 if ((doorbell & MPI2_IOC_STATE_MASK) ==
2036 MPI2_IOC_STATE_FAULT) {
2037 mpt2sas_base_fault_info(ioc , doorbell);
2038 return -EFAULT;
2039 }
2040 } else if (int_status == 0xFFFFFFFF)
2041 goto out;
2042
2043 if (sleep_flag == CAN_SLEEP)
2044 msleep(1);
2045 else
2046 udelay(500);
2047 count++;
2048 } while (--cntdn);
2049
2050 out:
2051 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2052 "int_status(%x)!\n", ioc->name, __func__, count, int_status);
2053 return -EFAULT;
2054}
2055
2056/**
2057 * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
2058 * @ioc: per adapter object
2059 * @timeout: timeout in second
2060 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2061 *
2062 * Returns 0 for success, non-zero for failure.
2063 *
2064 */
2065static int
2066_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,
2067 int sleep_flag)
2068{
2069 u32 cntdn, count;
2070 u32 doorbell_reg;
2071
2072 count = 0;
2073 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2074 do {
2075 doorbell_reg = readl(&ioc->chip->Doorbell);
2076 if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
2077 dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2078 "successfull count(%d), timeout(%d)\n", ioc->name,
2079 __func__, count, timeout));
2080 return 0;
2081 }
2082 if (sleep_flag == CAN_SLEEP)
2083 msleep(1);
2084 else
2085 udelay(500);
2086 count++;
2087 } while (--cntdn);
2088
2089 printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
2090 "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg);
2091 return -EFAULT;
2092}
2093
2094/**
2095 * _base_send_ioc_reset - send doorbell reset
2096 * @ioc: per adapter object
2097 * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
2098 * @timeout: timeout in second
2099 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2100 *
2101 * Returns 0 for success, non-zero for failure.
2102 */
2103static int
2104_base_send_ioc_reset(struct MPT2SAS_ADAPTER *ioc, u8 reset_type, int timeout,
2105 int sleep_flag)
2106{
2107 u32 ioc_state;
2108 int r = 0;
2109
2110 if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
2111 printk(MPT2SAS_ERR_FMT "%s: unknown reset_type\n",
2112 ioc->name, __func__);
2113 return -EFAULT;
2114 }
2115
2116 if (!(ioc->facts.IOCCapabilities &
2117 MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY))
2118 return -EFAULT;
2119
2120 printk(MPT2SAS_INFO_FMT "sending message unit reset !!\n", ioc->name);
2121
2122 writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
2123 &ioc->chip->Doorbell);
2124 if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
2125 r = -EFAULT;
2126 goto out;
2127 }
2128 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
2129 timeout, sleep_flag);
2130 if (ioc_state) {
2131 printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
2132 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
2133 r = -EFAULT;
2134 goto out;
2135 }
2136 out:
2137 printk(MPT2SAS_INFO_FMT "message unit reset: %s\n",
2138 ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
2139 return r;
2140}
2141
2142/**
2143 * _base_handshake_req_reply_wait - send request thru doorbell interface
2144 * @ioc: per adapter object
2145 * @request_bytes: request length
2146 * @request: pointer having request payload
2147 * @reply_bytes: reply length
2148 * @reply: pointer to reply payload
2149 * @timeout: timeout in second
2150 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2151 *
2152 * Returns 0 for success, non-zero for failure.
2153 */
2154static int
2155_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
2156 u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
2157{
2158 MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
2159 int i;
2160 u8 failed;
2161 u16 dummy;
2162 u32 *mfp;
2163
2164 /* make sure doorbell is not in use */
2165 if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
2166 printk(MPT2SAS_ERR_FMT "doorbell is in use "
2167 " (line=%d)\n", ioc->name, __LINE__);
2168 return -EFAULT;
2169 }
2170
2171 /* clear pending doorbell interrupts from previous state changes */
2172 if (readl(&ioc->chip->HostInterruptStatus) &
2173 MPI2_HIS_IOC2SYS_DB_STATUS)
2174 writel(0, &ioc->chip->HostInterruptStatus);
2175
2176 /* send message to ioc */
2177 writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
2178 ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
2179 &ioc->chip->Doorbell);
2180
2181 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
2182 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2183 "int failed (line=%d)\n", ioc->name, __LINE__);
2184 return -EFAULT;
2185 }
2186 writel(0, &ioc->chip->HostInterruptStatus);
2187
2188 if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
2189 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2190 "ack failed (line=%d)\n", ioc->name, __LINE__);
2191 return -EFAULT;
2192 }
2193
2194 /* send message 32-bits at a time */
2195 for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
2196 writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
2197 if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
2198 failed = 1;
2199 }
2200
2201 if (failed) {
2202 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2203 "sending request failed (line=%d)\n", ioc->name, __LINE__);
2204 return -EFAULT;
2205 }
2206
2207 /* now wait for the reply */
2208 if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
2209 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2210 "int failed (line=%d)\n", ioc->name, __LINE__);
2211 return -EFAULT;
2212 }
2213
2214 /* read the first two 16-bits, it gives the total length of the reply */
2215 reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2216 & MPI2_DOORBELL_DATA_MASK);
2217 writel(0, &ioc->chip->HostInterruptStatus);
2218 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
2219 printk(MPT2SAS_ERR_FMT "doorbell handshake "
2220 "int failed (line=%d)\n", ioc->name, __LINE__);
2221 return -EFAULT;
2222 }
2223 reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2224 & MPI2_DOORBELL_DATA_MASK);
2225 writel(0, &ioc->chip->HostInterruptStatus);
2226
2227 for (i = 2; i < default_reply->MsgLength * 2; i++) {
2228 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
2229 printk(MPT2SAS_ERR_FMT "doorbell "
2230 "handshake int failed (line=%d)\n", ioc->name,
2231 __LINE__);
2232 return -EFAULT;
2233 }
2234 if (i >= reply_bytes/2) /* overflow case */
2235 dummy = readl(&ioc->chip->Doorbell);
2236 else
2237 reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
2238 & MPI2_DOORBELL_DATA_MASK);
2239 writel(0, &ioc->chip->HostInterruptStatus);
2240 }
2241
2242 _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
2243 if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
2244 dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use "
2245 " (line=%d)\n", ioc->name, __LINE__));
2246 }
2247 writel(0, &ioc->chip->HostInterruptStatus);
2248
2249 if (ioc->logging_level & MPT_DEBUG_INIT) {
2250 mfp = (u32 *)reply;
2251 printk(KERN_DEBUG "\toffset:data\n");
2252 for (i = 0; i < reply_bytes/4; i++)
2253 printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4,
2254 le32_to_cpu(mfp[i]));
2255 }
2256 return 0;
2257}
2258
2259/**
2260 * mpt2sas_base_sas_iounit_control - send sas iounit control to FW
2261 * @ioc: per adapter object
2262 * @mpi_reply: the reply payload from FW
2263 * @mpi_request: the request payload sent to FW
2264 *
2265 * The SAS IO Unit Control Request message allows the host to perform low-level
2266 * operations, such as resets on the PHYs of the IO Unit, also allows the host
2267 * to obtain the IOC assigned device handles for a device if it has other
2268 * identifying information about the device, in addition allows the host to
2269 * remove IOC resources associated with the device.
2270 *
2271 * Returns 0 for success, non-zero for failure.
2272 */
2273int
2274mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
2275 Mpi2SasIoUnitControlReply_t *mpi_reply,
2276 Mpi2SasIoUnitControlRequest_t *mpi_request)
2277{
2278 u16 smid;
2279 u32 ioc_state;
2280 unsigned long timeleft;
2281 u8 issue_reset;
2282 int rc;
2283 void *request;
2284 u16 wait_state_count;
2285
2286 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
2287 __func__));
2288
2289 mutex_lock(&ioc->base_cmds.mutex);
2290
2291 if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
2292 printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
2293 ioc->name, __func__);
2294 rc = -EAGAIN;
2295 goto out;
2296 }
2297
2298 wait_state_count = 0;
2299 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2300 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
2301 if (wait_state_count++ == 10) {
2302 printk(MPT2SAS_ERR_FMT
2303 "%s: failed due to ioc not operational\n",
2304 ioc->name, __func__);
2305 rc = -EFAULT;
2306 goto out;
2307 }
2308 ssleep(1);
2309 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2310 printk(MPT2SAS_INFO_FMT "%s: waiting for "
2311 "operational state(count=%d)\n", ioc->name,
2312 __func__, wait_state_count);
2313 }
2314
2315 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
2316 if (!smid) {
2317 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2318 ioc->name, __func__);
2319 rc = -EAGAIN;
2320 goto out;
2321 }
2322
2323 rc = 0;
2324 ioc->base_cmds.status = MPT2_CMD_PENDING;
2325 request = mpt2sas_base_get_msg_frame(ioc, smid);
2326 ioc->base_cmds.smid = smid;
2327 memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t));
2328 if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
2329 mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
2330 ioc->ioc_link_reset_in_progress = 1;
2331 mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
2332 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
2333 msecs_to_jiffies(10000));
2334 if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
2335 mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) &&
2336 ioc->ioc_link_reset_in_progress)
2337 ioc->ioc_link_reset_in_progress = 0;
2338 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
2339 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
2340 ioc->name, __func__);
2341 _debug_dump_mf(mpi_request,
2342 sizeof(Mpi2SasIoUnitControlRequest_t)/4);
2343 if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
2344 issue_reset = 1;
2345 goto issue_host_reset;
2346 }
2347 if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
2348 memcpy(mpi_reply, ioc->base_cmds.reply,
2349 sizeof(Mpi2SasIoUnitControlReply_t));
2350 else
2351 memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t));
2352 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2353 goto out;
2354
2355 issue_host_reset:
2356 if (issue_reset)
2357 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2358 FORCE_BIG_HAMMER);
2359 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2360 rc = -EFAULT;
2361 out:
2362 mutex_unlock(&ioc->base_cmds.mutex);
2363 return rc;
2364}
2365
2366
2367/**
2368 * mpt2sas_base_scsi_enclosure_processor - sending request to sep device
2369 * @ioc: per adapter object
2370 * @mpi_reply: the reply payload from FW
2371 * @mpi_request: the request payload sent to FW
2372 *
2373 * The SCSI Enclosure Processor request message causes the IOC to
2374 * communicate with SES devices to control LED status signals.
2375 *
2376 * Returns 0 for success, non-zero for failure.
2377 */
2378int
2379mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
2380 Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
2381{
2382 u16 smid;
2383 u32 ioc_state;
2384 unsigned long timeleft;
2385 u8 issue_reset;
2386 int rc;
2387 void *request;
2388 u16 wait_state_count;
2389
2390 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
2391 __func__));
2392
2393 mutex_lock(&ioc->base_cmds.mutex);
2394
2395 if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
2396 printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
2397 ioc->name, __func__);
2398 rc = -EAGAIN;
2399 goto out;
2400 }
2401
2402 wait_state_count = 0;
2403 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2404 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
2405 if (wait_state_count++ == 10) {
2406 printk(MPT2SAS_ERR_FMT
2407 "%s: failed due to ioc not operational\n",
2408 ioc->name, __func__);
2409 rc = -EFAULT;
2410 goto out;
2411 }
2412 ssleep(1);
2413 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
2414 printk(MPT2SAS_INFO_FMT "%s: waiting for "
2415 "operational state(count=%d)\n", ioc->name,
2416 __func__, wait_state_count);
2417 }
2418
2419 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
2420 if (!smid) {
2421 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2422 ioc->name, __func__);
2423 rc = -EAGAIN;
2424 goto out;
2425 }
2426
2427 rc = 0;
2428 ioc->base_cmds.status = MPT2_CMD_PENDING;
2429 request = mpt2sas_base_get_msg_frame(ioc, smid);
2430 ioc->base_cmds.smid = smid;
2431 memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
2432 mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
2433 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
2434 msecs_to_jiffies(10000));
2435 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
2436 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
2437 ioc->name, __func__);
2438 _debug_dump_mf(mpi_request,
2439 sizeof(Mpi2SepRequest_t)/4);
2440 if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
2441 issue_reset = 1;
2442 goto issue_host_reset;
2443 }
2444 if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
2445 memcpy(mpi_reply, ioc->base_cmds.reply,
2446 sizeof(Mpi2SepReply_t));
2447 else
2448 memset(mpi_reply, 0, sizeof(Mpi2SepReply_t));
2449 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2450 goto out;
2451
2452 issue_host_reset:
2453 if (issue_reset)
2454 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2455 FORCE_BIG_HAMMER);
2456 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2457 rc = -EFAULT;
2458 out:
2459 mutex_unlock(&ioc->base_cmds.mutex);
2460 return rc;
2461}
2462
2463/**
2464 * _base_get_port_facts - obtain port facts reply and save in ioc
2465 * @ioc: per adapter object
2466 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2467 *
2468 * Returns 0 for success, non-zero for failure.
2469 */
2470static int
2471_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
2472{
2473 Mpi2PortFactsRequest_t mpi_request;
2474 Mpi2PortFactsReply_t mpi_reply, *pfacts;
2475 int mpi_reply_sz, mpi_request_sz, r;
2476
2477 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
2478 __func__));
2479
2480 mpi_reply_sz = sizeof(Mpi2PortFactsReply_t);
2481 mpi_request_sz = sizeof(Mpi2PortFactsRequest_t);
2482 memset(&mpi_request, 0, mpi_request_sz);
2483 mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
2484 mpi_request.PortNumber = port;
2485 r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
2486 (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
2487
2488 if (r != 0) {
2489 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
2490 ioc->name, __func__, r);
2491 return r;
2492 }
2493
2494 pfacts = &ioc->pfacts[port];
2495 memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t));
2496 pfacts->PortNumber = mpi_reply.PortNumber;
2497 pfacts->VP_ID = mpi_reply.VP_ID;
2498 pfacts->VF_ID = mpi_reply.VF_ID;
2499 pfacts->MaxPostedCmdBuffers =
2500 le16_to_cpu(mpi_reply.MaxPostedCmdBuffers);
2501
2502 return 0;
2503}
2504
2505/**
2506 * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
2507 * @ioc: per adapter object
2508 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2509 *
2510 * Returns 0 for success, non-zero for failure.
2511 */
2512static int
2513_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2514{
2515 Mpi2IOCFactsRequest_t mpi_request;
2516 Mpi2IOCFactsReply_t mpi_reply, *facts;
2517 int mpi_reply_sz, mpi_request_sz, r;
2518
2519 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
2520 __func__));
2521
2522 mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
2523 mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
2524 memset(&mpi_request, 0, mpi_request_sz);
2525 mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
2526 r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
2527 (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
2528
2529 if (r != 0) {
2530 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
2531 ioc->name, __func__, r);
2532 return r;
2533 }
2534
2535 facts = &ioc->facts;
2536 memset(facts, 0, sizeof(Mpi2IOCFactsReply_t));
2537 facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
2538 facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
2539 facts->VP_ID = mpi_reply.VP_ID;
2540 facts->VF_ID = mpi_reply.VF_ID;
2541 facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
2542 facts->MaxChainDepth = mpi_reply.MaxChainDepth;
2543 facts->WhoInit = mpi_reply.WhoInit;
2544 facts->NumberOfPorts = mpi_reply.NumberOfPorts;
2545 facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
2546 facts->MaxReplyDescriptorPostQueueDepth =
2547 le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
2548 facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
2549 facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
2550 if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
2551 ioc->ir_firmware = 1;
2552 facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
2553 facts->IOCRequestFrameSize =
2554 le16_to_cpu(mpi_reply.IOCRequestFrameSize);
2555 facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
2556 facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
2557 ioc->shost->max_id = -1;
2558 facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
2559 facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
2560 facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
2561 facts->HighPriorityCredit =
2562 le16_to_cpu(mpi_reply.HighPriorityCredit);
2563 facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
2564 facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
2565
2566 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), "
2567 "max chains per io(%d)\n", ioc->name, facts->RequestCredit,
2568 facts->MaxChainDepth));
2569 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), "
2570 "reply frame size(%d)\n", ioc->name,
2571 facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
2572 return 0;
2573}
2574
2575/**
2576 * _base_send_ioc_init - send ioc_init to firmware
2577 * @ioc: per adapter object
2578 * @VF_ID: virtual function id
2579 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2580 *
2581 * Returns 0 for success, non-zero for failure.
2582 */
2583static int
2584_base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
2585{
2586 Mpi2IOCInitRequest_t mpi_request;
2587 Mpi2IOCInitReply_t mpi_reply;
2588 int r;
2589
2590 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
2591 __func__));
2592
2593 memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t));
2594 mpi_request.Function = MPI2_FUNCTION_IOC_INIT;
2595 mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
2596 mpi_request.VF_ID = VF_ID;
2597 mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
2598 mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
2599
2600 /* In MPI Revision I (0xA), the SystemReplyFrameSize(offset 0x18) was
2601 * removed and made reserved. For those with older firmware will need
2602 * this fix. It was decided that the Reply and Request frame sizes are
2603 * the same.
2604 */
2605 if ((ioc->facts.HeaderVersion >> 8) < 0xA) {
2606 mpi_request.Reserved7 = cpu_to_le16(ioc->reply_sz);
2607/* mpi_request.SystemReplyFrameSize =
2608 * cpu_to_le16(ioc->reply_sz);
2609 */
2610 }
2611
2612 mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
2613 mpi_request.ReplyDescriptorPostQueueDepth =
2614 cpu_to_le16(ioc->reply_post_queue_depth);
2615 mpi_request.ReplyFreeQueueDepth =
2616 cpu_to_le16(ioc->reply_free_queue_depth);
2617
2618#if BITS_PER_LONG > 32
2619 mpi_request.SenseBufferAddressHigh =
2620 cpu_to_le32(ioc->sense_dma >> 32);
2621 mpi_request.SystemReplyAddressHigh =
2622 cpu_to_le32(ioc->reply_dma >> 32);
2623 mpi_request.SystemRequestFrameBaseAddress =
2624 cpu_to_le64(ioc->request_dma);
2625 mpi_request.ReplyFreeQueueAddress =
2626 cpu_to_le64(ioc->reply_free_dma);
2627 mpi_request.ReplyDescriptorPostQueueAddress =
2628 cpu_to_le64(ioc->reply_post_free_dma);
2629#else
2630 mpi_request.SystemRequestFrameBaseAddress =
2631 cpu_to_le32(ioc->request_dma);
2632 mpi_request.ReplyFreeQueueAddress =
2633 cpu_to_le32(ioc->reply_free_dma);
2634 mpi_request.ReplyDescriptorPostQueueAddress =
2635 cpu_to_le32(ioc->reply_post_free_dma);
2636#endif
2637
2638 if (ioc->logging_level & MPT_DEBUG_INIT) {
2639 u32 *mfp;
2640 int i;
2641
2642 mfp = (u32 *)&mpi_request;
2643 printk(KERN_DEBUG "\toffset:data\n");
2644 for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
2645 printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4,
2646 le32_to_cpu(mfp[i]));
2647 }
2648
2649 r = _base_handshake_req_reply_wait(ioc,
2650 sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
2651 sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
2652 sleep_flag);
2653
2654 if (r != 0) {
2655 printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
2656 ioc->name, __func__, r);
2657 return r;
2658 }
2659
2660 if (mpi_reply.IOCStatus != MPI2_IOCSTATUS_SUCCESS ||
2661 mpi_reply.IOCLogInfo) {
2662 printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__);
2663 r = -EIO;
2664 }
2665
2666 return 0;
2667}
2668
2669/**
2670 * _base_send_port_enable - send port_enable(discovery stuff) to firmware
2671 * @ioc: per adapter object
2672 * @VF_ID: virtual function id
2673 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2674 *
2675 * Returns 0 for success, non-zero for failure.
2676 */
2677static int
2678_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
2679{
2680 Mpi2PortEnableRequest_t *mpi_request;
2681 u32 ioc_state;
2682 unsigned long timeleft;
2683 int r = 0;
2684 u16 smid;
2685
2686 printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
2687
2688 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
2689 printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
2690 ioc->name, __func__);
2691 return -EAGAIN;
2692 }
2693
2694 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
2695 if (!smid) {
2696 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2697 ioc->name, __func__);
2698 return -EAGAIN;
2699 }
2700
2701 ioc->base_cmds.status = MPT2_CMD_PENDING;
2702 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2703 ioc->base_cmds.smid = smid;
2704 memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
2705 mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
2706 mpi_request->VF_ID = VF_ID;
2707
2708 mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
2709 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
2710 300*HZ);
2711 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
2712 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
2713 ioc->name, __func__);
2714 _debug_dump_mf(mpi_request,
2715 sizeof(Mpi2PortEnableRequest_t)/4);
2716 if (ioc->base_cmds.status & MPT2_CMD_RESET)
2717 r = -EFAULT;
2718 else
2719 r = -ETIME;
2720 goto out;
2721 } else
2722 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n",
2723 ioc->name, __func__));
2724
2725 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL,
2726 60, sleep_flag);
2727 if (ioc_state) {
2728 printk(MPT2SAS_ERR_FMT "%s: failed going to operational state "
2729 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
2730 r = -EFAULT;
2731 }
2732 out:
2733 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2734 printk(MPT2SAS_INFO_FMT "port enable: %s\n",
2735 ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
2736 return r;
2737}
2738
2739/**
2740 * _base_unmask_events - turn on notification for this event
2741 * @ioc: per adapter object
2742 * @event: firmware event
2743 *
2744 * The mask is stored in ioc->event_masks.
2745 */
2746static void
2747_base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event)
2748{
2749 u32 desired_event;
2750
2751 if (event >= 128)
2752 return;
2753
2754 desired_event = (1 << (event % 32));
2755
2756 if (event < 32)
2757 ioc->event_masks[0] &= ~desired_event;
2758 else if (event < 64)
2759 ioc->event_masks[1] &= ~desired_event;
2760 else if (event < 96)
2761 ioc->event_masks[2] &= ~desired_event;
2762 else if (event < 128)
2763 ioc->event_masks[3] &= ~desired_event;
2764}
2765
2766/**
2767 * _base_event_notification - send event notification
2768 * @ioc: per adapter object
2769 * @VF_ID: virtual function id
2770 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2771 *
2772 * Returns 0 for success, non-zero for failure.
2773 */
2774static int
2775_base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
2776{
2777 Mpi2EventNotificationRequest_t *mpi_request;
2778 unsigned long timeleft;
2779 u16 smid;
2780 int r = 0;
2781 int i;
2782
2783 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
2784 __func__));
2785
2786 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
2787 printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
2788 ioc->name, __func__);
2789 return -EAGAIN;
2790 }
2791
2792 smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
2793 if (!smid) {
2794 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2795 ioc->name, __func__);
2796 return -EAGAIN;
2797 }
2798 ioc->base_cmds.status = MPT2_CMD_PENDING;
2799 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2800 ioc->base_cmds.smid = smid;
2801 memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
2802 mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
2803 mpi_request->VF_ID = VF_ID;
2804 for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
2805 mpi_request->EventMasks[i] =
2806 le32_to_cpu(ioc->event_masks[i]);
2807 mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
2808 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
2809 if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
2810 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
2811 ioc->name, __func__);
2812 _debug_dump_mf(mpi_request,
2813 sizeof(Mpi2EventNotificationRequest_t)/4);
2814 if (ioc->base_cmds.status & MPT2_CMD_RESET)
2815 r = -EFAULT;
2816 else
2817 r = -ETIME;
2818 } else
2819 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n",
2820 ioc->name, __func__));
2821 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
2822 return r;
2823}
2824
2825/**
2826 * mpt2sas_base_validate_event_type - validating event types
2827 * @ioc: per adapter object
2828 * @event: firmware event
2829 *
2830 * This will turn on firmware event notification when application
2831 * ask for that event. We don't mask events that are already enabled.
2832 */
2833void
2834mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type)
2835{
2836 int i, j;
2837 u32 event_mask, desired_event;
2838 u8 send_update_to_fw;
2839
2840 for (i = 0, send_update_to_fw = 0; i <
2841 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) {
2842 event_mask = ~event_type[i];
2843 desired_event = 1;
2844 for (j = 0; j < 32; j++) {
2845 if (!(event_mask & desired_event) &&
2846 (ioc->event_masks[i] & desired_event)) {
2847 ioc->event_masks[i] &= ~desired_event;
2848 send_update_to_fw = 1;
2849 }
2850 desired_event = (desired_event << 1);
2851 }
2852 }
2853
2854 if (!send_update_to_fw)
2855 return;
2856
2857 mutex_lock(&ioc->base_cmds.mutex);
2858 _base_event_notification(ioc, 0, CAN_SLEEP);
2859 mutex_unlock(&ioc->base_cmds.mutex);
2860}
2861
2862/**
2863 * _base_diag_reset - the "big hammer" start of day reset
2864 * @ioc: per adapter object
2865 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2866 *
2867 * Returns 0 for success, non-zero for failure.
2868 */
2869static int
2870_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2871{
2872 u32 host_diagnostic;
2873 u32 ioc_state;
2874 u32 count;
2875 u32 hcb_size;
2876
2877 printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name);
2878
2879 _base_save_msix_table(ioc);
2880
2881 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n",
2882 ioc->name));
2883 writel(0, &ioc->chip->HostInterruptStatus);
2884
2885 count = 0;
2886 do {
2887 /* Write magic sequence to WriteSequence register
2888 * Loop until in diagnostic mode
2889 */
2890 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "write magic "
2891 "sequence\n", ioc->name));
2892 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
2893 writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence);
2894 writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence);
2895 writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence);
2896 writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence);
2897 writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence);
2898 writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
2899
2900 /* wait 100 msec */
2901 if (sleep_flag == CAN_SLEEP)
2902 msleep(100);
2903 else
2904 mdelay(100);
2905
2906 if (count++ > 20)
2907 goto out;
2908
2909 host_diagnostic = readl(&ioc->chip->HostDiagnostic);
2910 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "wrote magic "
2911 "sequence: count(%d), host_diagnostic(0x%08x)\n",
2912 ioc->name, count, host_diagnostic));
2913
2914 } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0);
2915
2916 hcb_size = readl(&ioc->chip->HCBSize);
2917
2918 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "diag reset: issued\n",
2919 ioc->name));
2920 writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
2921 &ioc->chip->HostDiagnostic);
2922
2923 /* don't access any registers for 50 milliseconds */
2924 msleep(50);
2925
2926 /* 300 second max wait */
2927 for (count = 0; count < 3000000 ; count++) {
2928
2929 host_diagnostic = readl(&ioc->chip->HostDiagnostic);
2930
2931 if (host_diagnostic == 0xFFFFFFFF)
2932 goto out;
2933 if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
2934 break;
2935
2936 /* wait 100 msec */
2937 if (sleep_flag == CAN_SLEEP)
2938 msleep(1);
2939 else
2940 mdelay(1);
2941 }
2942
2943 if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
2944
2945 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter "
2946 "assuming the HCB Address points to good F/W\n",
2947 ioc->name));
2948 host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
2949 host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
2950 writel(host_diagnostic, &ioc->chip->HostDiagnostic);
2951
2952 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT
2953 "re-enable the HCDW\n", ioc->name));
2954 writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,
2955 &ioc->chip->HCBSize);
2956 }
2957
2958 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter\n",
2959 ioc->name));
2960 writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,
2961 &ioc->chip->HostDiagnostic);
2962
2963 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "disable writes to the "
2964 "diagnostic register\n", ioc->name));
2965 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
2966
2967 drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "Wait for FW to go to the "
2968 "READY state\n", ioc->name));
2969 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
2970 sleep_flag);
2971 if (ioc_state) {
2972 printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
2973 " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
2974 goto out;
2975 }
2976
2977 _base_restore_msix_table(ioc);
2978 printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name);
2979 return 0;
2980
2981 out:
2982 printk(MPT2SAS_ERR_FMT "diag reset: FAILED\n", ioc->name);
2983 return -EFAULT;
2984}
2985
2986/**
2987 * _base_make_ioc_ready - put controller in READY state
2988 * @ioc: per adapter object
2989 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2990 * @type: FORCE_BIG_HAMMER or SOFT_RESET
2991 *
2992 * Returns 0 for success, non-zero for failure.
2993 */
2994static int
2995_base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
2996 enum reset_type type)
2997{
2998 u32 ioc_state;
2999
3000 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
3001 __func__));
3002
3003 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
3004 dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: ioc_state(0x%08x)\n",
3005 ioc->name, __func__, ioc_state));
3006
3007 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)
3008 return 0;
3009
3010 if (ioc_state & MPI2_DOORBELL_USED) {
3011 dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell "
3012 "active!\n", ioc->name));
3013 goto issue_diag_reset;
3014 }
3015
3016 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
3017 mpt2sas_base_fault_info(ioc, ioc_state &
3018 MPI2_DOORBELL_DATA_MASK);
3019 goto issue_diag_reset;
3020 }
3021
3022 if (type == FORCE_BIG_HAMMER)
3023 goto issue_diag_reset;
3024
3025 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
3026 if (!(_base_send_ioc_reset(ioc,
3027 MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP)))
3028 return 0;
3029
3030 issue_diag_reset:
3031 return _base_diag_reset(ioc, CAN_SLEEP);
3032}
3033
3034/**
3035 * _base_make_ioc_operational - put controller in OPERATIONAL state
3036 * @ioc: per adapter object
3037 * @VF_ID: virtual function id
3038 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3039 *
3040 * Returns 0 for success, non-zero for failure.
3041 */
3042static int
3043_base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
3044 int sleep_flag)
3045{
3046 int r, i;
3047 unsigned long flags;
3048 u32 reply_address;
3049
3050 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
3051 __func__));
3052
3053 /* initialize the scsi lookup free list */
3054 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
3055 INIT_LIST_HEAD(&ioc->free_list);
3056 for (i = 0; i < ioc->request_depth; i++) {
3057 ioc->scsi_lookup[i].cb_idx = 0xFF;
3058 list_add_tail(&ioc->scsi_lookup[i].tracker_list,
3059 &ioc->free_list);
3060 }
3061 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3062
3063 /* initialize Reply Free Queue */
3064 for (i = 0, reply_address = (u32)ioc->reply_dma ;
3065 i < ioc->reply_free_queue_depth ; i++, reply_address +=
3066 ioc->reply_sz)
3067 ioc->reply_free[i] = cpu_to_le32(reply_address);
3068
3069 /* initialize Reply Post Free Queue */
3070 for (i = 0; i < ioc->reply_post_queue_depth; i++)
3071 ioc->reply_post_free[i].Words = ~0ULL;
3072
3073 r = _base_send_ioc_init(ioc, VF_ID, sleep_flag);
3074 if (r)
3075 return r;
3076
3077 /* initialize the index's */
3078 ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
3079 ioc->reply_post_host_index = 0;
3080 writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
3081 writel(0, &ioc->chip->ReplyPostHostIndex);
3082
3083 _base_unmask_interrupts(ioc);
3084 r = _base_event_notification(ioc, VF_ID, sleep_flag);
3085 if (r)
3086 return r;
3087
3088 if (sleep_flag == CAN_SLEEP)
3089 _base_static_config_pages(ioc);
3090
3091 r = _base_send_port_enable(ioc, VF_ID, sleep_flag);
3092 if (r)
3093 return r;
3094
3095 return r;
3096}
3097
3098/**
3099 * mpt2sas_base_free_resources - free resources controller resources (io/irq/memap)
3100 * @ioc: per adapter object
3101 *
3102 * Return nothing.
3103 */
3104void
3105mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
3106{
3107 struct pci_dev *pdev = ioc->pdev;
3108
3109 dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
3110 __func__));
3111
3112 _base_mask_interrupts(ioc);
3113 _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
3114 if (ioc->pci_irq) {
3115 synchronize_irq(pdev->irq);
3116 free_irq(ioc->pci_irq, ioc);
3117 }
3118 _base_disable_msix(ioc);
3119 if (ioc->chip_phys)
3120 iounmap(ioc->chip);
3121 ioc->pci_irq = -1;
3122 ioc->chip_phys = 0;
3123 pci_release_selected_regions(ioc->pdev, ioc->bars);
3124 pci_disable_device(pdev);
3125 pci_set_drvdata(pdev, NULL);
3126 return;
3127}
3128
3129/**
3130 * mpt2sas_base_attach - attach controller instance
3131 * @ioc: per adapter object
3132 *
3133 * Returns 0 for success, non-zero for failure.
3134 */
3135int
3136mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
3137{
3138 int r, i;
3139 unsigned long flags;
3140
3141 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
3142 __func__));
3143
3144 r = mpt2sas_base_map_resources(ioc);
3145 if (r)
3146 return r;
3147
3148 r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
3149 if (r)
3150 goto out_free_resources;
3151
3152 r = _base_get_ioc_facts(ioc, CAN_SLEEP);
3153 if (r)
3154 goto out_free_resources;
3155
3156 r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
3157 if (r)
3158 goto out_free_resources;
3159
3160 init_waitqueue_head(&ioc->reset_wq);
3161
3162 /* base internal command bits */
3163 mutex_init(&ioc->base_cmds.mutex);
3164 init_completion(&ioc->base_cmds.done);
3165 ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3166 ioc->base_cmds.status = MPT2_CMD_NOT_USED;
3167
3168 /* transport internal command bits */
3169 ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3170 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
3171 mutex_init(&ioc->transport_cmds.mutex);
3172 init_completion(&ioc->transport_cmds.done);
3173
3174 /* task management internal command bits */
3175 ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3176 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
3177 mutex_init(&ioc->tm_cmds.mutex);
3178 init_completion(&ioc->tm_cmds.done);
3179
3180 /* config page internal command bits */
3181 ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3182 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
3183 mutex_init(&ioc->config_cmds.mutex);
3184 init_completion(&ioc->config_cmds.done);
3185
3186 /* ctl module internal command bits */
3187 ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
3188 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
3189 mutex_init(&ioc->ctl_cmds.mutex);
3190 init_completion(&ioc->ctl_cmds.done);
3191
3192 for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
3193 ioc->event_masks[i] = -1;
3194
3195 /* here we enable the events we care about */
3196 _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY);
3197 _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
3198 _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
3199 _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
3200 _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
3201 _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
3202 _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
3203 _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
3204 _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
3205 _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL);
3206 _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
3207
3208 ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
3209 sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
3210 if (!ioc->pfacts)
3211 goto out_free_resources;
3212
3213 for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
3214 r = _base_get_port_facts(ioc, i, CAN_SLEEP);
3215 if (r)
3216 goto out_free_resources;
3217 }
3218 r = _base_make_ioc_operational(ioc, 0, CAN_SLEEP);
3219 if (r)
3220 goto out_free_resources;
3221
3222 /* initialize fault polling */
3223 INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
3224 snprintf(ioc->fault_reset_work_q_name,
3225 sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
3226 ioc->fault_reset_work_q =
3227 create_singlethread_workqueue(ioc->fault_reset_work_q_name);
3228 if (!ioc->fault_reset_work_q) {
3229 printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
3230 ioc->name, __func__, __LINE__);
3231 goto out_free_resources;
3232 }
3233 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3234 if (ioc->fault_reset_work_q)
3235 queue_delayed_work(ioc->fault_reset_work_q,
3236 &ioc->fault_reset_work,
3237 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
3238 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
3239 return 0;
3240
3241 out_free_resources:
3242
3243 ioc->remove_host = 1;
3244 mpt2sas_base_free_resources(ioc);
3245 _base_release_memory_pools(ioc);
3246 kfree(ioc->tm_cmds.reply);
3247 kfree(ioc->transport_cmds.reply);
3248 kfree(ioc->config_cmds.reply);
3249 kfree(ioc->base_cmds.reply);
3250 kfree(ioc->ctl_cmds.reply);
3251 kfree(ioc->pfacts);
3252 ioc->ctl_cmds.reply = NULL;
3253 ioc->base_cmds.reply = NULL;
3254 ioc->tm_cmds.reply = NULL;
3255 ioc->transport_cmds.reply = NULL;
3256 ioc->config_cmds.reply = NULL;
3257 ioc->pfacts = NULL;
3258 return r;
3259}
3260
3261
3262/**
3263 * mpt2sas_base_detach - remove controller instance
3264 * @ioc: per adapter object
3265 *
3266 * Return nothing.
3267 */
3268void
3269mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
3270{
3271 unsigned long flags;
3272 struct workqueue_struct *wq;
3273
3274 dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
3275 __func__));
3276
3277 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3278 wq = ioc->fault_reset_work_q;
3279 ioc->fault_reset_work_q = NULL;
3280 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
3281 if (!cancel_delayed_work(&ioc->fault_reset_work))
3282 flush_workqueue(wq);
3283 destroy_workqueue(wq);
3284
3285 mpt2sas_base_free_resources(ioc);
3286 _base_release_memory_pools(ioc);
3287 kfree(ioc->pfacts);
3288 kfree(ioc->ctl_cmds.reply);
3289 kfree(ioc->base_cmds.reply);
3290 kfree(ioc->tm_cmds.reply);
3291 kfree(ioc->transport_cmds.reply);
3292 kfree(ioc->config_cmds.reply);
3293}
3294
3295/**
3296 * _base_reset_handler - reset callback handler (for base)
3297 * @ioc: per adapter object
3298 * @reset_phase: phase
3299 *
3300 * The handler for doing any required cleanup or initialization.
3301 *
3302 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
3303 * MPT2_IOC_DONE_RESET
3304 *
3305 * Return nothing.
3306 */
3307static void
3308_base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
3309{
3310 switch (reset_phase) {
3311 case MPT2_IOC_PRE_RESET:
3312 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
3313 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
3314 break;
3315 case MPT2_IOC_AFTER_RESET:
3316 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
3317 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
3318 if (ioc->transport_cmds.status & MPT2_CMD_PENDING) {
3319 ioc->transport_cmds.status |= MPT2_CMD_RESET;
3320 mpt2sas_base_free_smid(ioc, ioc->transport_cmds.smid);
3321 complete(&ioc->transport_cmds.done);
3322 }
3323 if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
3324 ioc->base_cmds.status |= MPT2_CMD_RESET;
3325 mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid);
3326 complete(&ioc->base_cmds.done);
3327 }
3328 if (ioc->config_cmds.status & MPT2_CMD_PENDING) {
3329 ioc->config_cmds.status |= MPT2_CMD_RESET;
3330 mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid);
3331 complete(&ioc->config_cmds.done);
3332 }
3333 break;
3334 case MPT2_IOC_DONE_RESET:
3335 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
3336 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
3337 break;
3338 }
3339 mpt2sas_scsih_reset_handler(ioc, reset_phase);
3340 mpt2sas_ctl_reset_handler(ioc, reset_phase);
3341}
3342
3343/**
3344 * _wait_for_commands_to_complete - reset controller
3345 * @ioc: Pointer to MPT_ADAPTER structure
3346 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3347 *
3348 * This function waiting(3s) for all pending commands to complete
3349 * prior to putting controller in reset.
3350 */
3351static void
3352_wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
3353{
3354 u32 ioc_state;
3355 unsigned long flags;
3356 u16 i;
3357
3358 ioc->pending_io_count = 0;
3359 if (sleep_flag != CAN_SLEEP)
3360 return;
3361
3362 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
3363 if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
3364 return;
3365
3366 /* pending command count */
3367 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
3368 for (i = 0; i < ioc->request_depth; i++)
3369 if (ioc->scsi_lookup[i].cb_idx != 0xFF)
3370 ioc->pending_io_count++;
3371 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3372
3373 if (!ioc->pending_io_count)
3374 return;
3375
3376 /* wait for pending commands to complete */
3377 wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 3 * HZ);
3378}
3379
3380/**
3381 * mpt2sas_base_hard_reset_handler - reset controller
3382 * @ioc: Pointer to MPT_ADAPTER structure
3383 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3384 * @type: FORCE_BIG_HAMMER or SOFT_RESET
3385 *
3386 * Returns 0 for success, non-zero for failure.
3387 */
3388int
3389mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
3390 enum reset_type type)
3391{
3392 int r, i;
3393 unsigned long flags;
3394
3395 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
3396 __func__));
3397
3398 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3399 if (ioc->ioc_reset_in_progress) {
3400 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
3401 printk(MPT2SAS_ERR_FMT "%s: busy\n",
3402 ioc->name, __func__);
3403 return -EBUSY;
3404 }
3405 ioc->ioc_reset_in_progress = 1;
3406 ioc->shost_recovery = 1;
3407 if (ioc->shost->shost_state == SHOST_RUNNING) {
3408 /* set back to SHOST_RUNNING in mpt2sas_scsih.c */
3409 scsi_host_set_state(ioc->shost, SHOST_RECOVERY);
3410 printk(MPT2SAS_INFO_FMT "putting controller into "
3411 "SHOST_RECOVERY\n", ioc->name);
3412 }
3413 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
3414
3415 _base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
3416 _wait_for_commands_to_complete(ioc, sleep_flag);
3417 _base_mask_interrupts(ioc);
3418 r = _base_make_ioc_ready(ioc, sleep_flag, type);
3419 if (r)
3420 goto out;
3421 _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
3422 for (i = 0 ; i < ioc->facts.NumberOfPorts; i++)
3423 r = _base_make_ioc_operational(ioc, ioc->pfacts[i].VF_ID,
3424 sleep_flag);
3425 if (!r)
3426 _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
3427 out:
3428 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: %s\n",
3429 ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
3430
3431 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
3432 ioc->ioc_reset_in_progress = 0;
3433 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
3434 return r;
3435}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
new file mode 100644
index 000000000000..11fc17f218c8
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -0,0 +1,779 @@
1/*
2 * This is the Fusion MPT base driver providing common API layer interface
3 * for access to MPT (Message Passing Technology) firmware.
4 *
5 * This code is based on drivers/scsi/mpt2sas/mpt2_base.h
6 * Copyright (C) 2007-2008 LSI Corporation
7 * (mailto:DL-MPTFusionLinux@lsi.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * NO WARRANTY
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
29
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
42 * USA.
43 */
44
45#ifndef MPT2SAS_BASE_H_INCLUDED
46#define MPT2SAS_BASE_H_INCLUDED
47
48#include "mpi/mpi2_type.h"
49#include "mpi/mpi2.h"
50#include "mpi/mpi2_ioc.h"
51#include "mpi/mpi2_cnfg.h"
52#include "mpi/mpi2_init.h"
53#include "mpi/mpi2_raid.h"
54#include "mpi/mpi2_tool.h"
55#include "mpi/mpi2_sas.h"
56
57#include <scsi/scsi.h>
58#include <scsi/scsi_cmnd.h>
59#include <scsi/scsi_device.h>
60#include <scsi/scsi_host.h>
61#include <scsi/scsi_tcq.h>
62#include <scsi/scsi_transport_sas.h>
63#include <scsi/scsi_dbg.h>
64
65#include "mpt2sas_debug.h"
66
67/* driver versioning info */
68#define MPT2SAS_DRIVER_NAME "mpt2sas"
69#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
70#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
71#define MPT2SAS_DRIVER_VERSION "00.100.11.15"
72#define MPT2SAS_MAJOR_VERSION 00
73#define MPT2SAS_MINOR_VERSION 100
74#define MPT2SAS_BUILD_VERSION 11
75#define MPT2SAS_RELEASE_VERSION 15
76
77/*
78 * Set MPT2SAS_SG_DEPTH value based on user input.
79 */
80#ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE
81#if CONFIG_SCSI_MPT2SAS_MAX_SGE < 16
82#define MPT2SAS_SG_DEPTH 16
83#elif CONFIG_SCSI_MPT2SAS_MAX_SGE > 128
84#define MPT2SAS_SG_DEPTH 128
85#else
86#define MPT2SAS_SG_DEPTH CONFIG_SCSI_MPT2SAS_MAX_SGE
87#endif
88#else
89#define MPT2SAS_SG_DEPTH 128 /* MAX_HW_SEGMENTS */
90#endif
91
92
93/*
94 * Generic Defines
95 */
96#define MPT2SAS_SATA_QUEUE_DEPTH 32
97#define MPT2SAS_SAS_QUEUE_DEPTH 254
98#define MPT2SAS_RAID_QUEUE_DEPTH 128
99
100#define MPT_NAME_LENGTH 32 /* generic length of strings */
101#define MPT_STRING_LENGTH 64
102
103#define MPT_MAX_CALLBACKS 16
104
105#define CAN_SLEEP 1
106#define NO_SLEEP 0
107
108#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */
109
110#define MPI2_HIM_MASK 0xFFFFFFFF /* mask every bit*/
111
112#define MPT2SAS_INVALID_DEVICE_HANDLE 0xFFFF
113
114
115/*
116 * reset phases
117 */
118#define MPT2_IOC_PRE_RESET 1 /* prior to host reset */
119#define MPT2_IOC_AFTER_RESET 2 /* just after host reset */
120#define MPT2_IOC_DONE_RESET 3 /* links re-initialized */
121
122/*
123 * logging format
124 */
125#define MPT2SAS_FMT "%s: "
126#define MPT2SAS_DEBUG_FMT KERN_DEBUG MPT2SAS_FMT
127#define MPT2SAS_INFO_FMT KERN_INFO MPT2SAS_FMT
128#define MPT2SAS_NOTE_FMT KERN_NOTICE MPT2SAS_FMT
129#define MPT2SAS_WARN_FMT KERN_WARNING MPT2SAS_FMT
130#define MPT2SAS_ERR_FMT KERN_ERR MPT2SAS_FMT
131
132/*
133 * per target private data
134 */
135#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01
136#define MPT_TARGET_FLAGS_VOLUME 0x02
137#define MPT_TARGET_FLAGS_DELETED 0x04
138
139/**
140 * struct MPT2SAS_TARGET - starget private hostdata
141 * @starget: starget object
142 * @sas_address: target sas address
143 * @handle: device handle
144 * @num_luns: number luns
145 * @flags: MPT_TARGET_FLAGS_XXX flags
146 * @deleted: target flaged for deletion
147 * @tm_busy: target is busy with TM request.
148 */
149struct MPT2SAS_TARGET {
150 struct scsi_target *starget;
151 u64 sas_address;
152 u16 handle;
153 int num_luns;
154 u32 flags;
155 u8 deleted;
156 u8 tm_busy;
157};
158
159/*
160 * per device private data
161 */
162#define MPT_DEVICE_FLAGS_INIT 0x01
163#define MPT_DEVICE_TLR_ON 0x02
164
165/**
166 * struct MPT2SAS_DEVICE - sdev private hostdata
167 * @sas_target: starget private hostdata
168 * @lun: lun number
169 * @flags: MPT_DEVICE_XXX flags
170 * @configured_lun: lun is configured
171 * @block: device is in SDEV_BLOCK state
172 * @tlr_snoop_check: flag used in determining whether to disable TLR
173 */
174struct MPT2SAS_DEVICE {
175 struct MPT2SAS_TARGET *sas_target;
176 unsigned int lun;
177 u32 flags;
178 u8 configured_lun;
179 u8 block;
180 u8 tlr_snoop_check;
181};
182
183#define MPT2_CMD_NOT_USED 0x8000 /* free */
184#define MPT2_CMD_COMPLETE 0x0001 /* completed */
185#define MPT2_CMD_PENDING 0x0002 /* pending */
186#define MPT2_CMD_REPLY_VALID 0x0004 /* reply is valid */
187#define MPT2_CMD_RESET 0x0008 /* host reset dropped the command */
188
189/**
190 * struct _internal_cmd - internal commands struct
191 * @mutex: mutex
192 * @done: completion
193 * @reply: reply message pointer
194 * @status: MPT2_CMD_XXX status
195 * @smid: system message id
196 */
197struct _internal_cmd {
198 struct mutex mutex;
199 struct completion done;
200 void *reply;
201 u16 status;
202 u16 smid;
203};
204
205/*
206 * SAS Topology Structures
207 */
208
209/**
210 * struct _sas_device - attached device information
211 * @list: sas device list
212 * @starget: starget object
213 * @sas_address: device sas address
214 * @device_name: retrieved from the SAS IDENTIFY frame.
215 * @handle: device handle
216 * @parent_handle: handle to parent device
217 * @enclosure_handle: enclosure handle
218 * @enclosure_logical_id: enclosure logical identifier
219 * @volume_handle: volume handle (valid when hidden raid member)
220 * @volume_wwid: volume unique identifier
221 * @device_info: bitfield provides detailed info about the device
222 * @id: target id
223 * @channel: target channel
224 * @slot: number number
225 * @hidden_raid_component: set to 1 when this is a raid member
226 * @responding: used in _scsih_sas_device_mark_responding
227 */
228struct _sas_device {
229 struct list_head list;
230 struct scsi_target *starget;
231 u64 sas_address;
232 u64 device_name;
233 u16 handle;
234 u16 parent_handle;
235 u16 enclosure_handle;
236 u64 enclosure_logical_id;
237 u16 volume_handle;
238 u64 volume_wwid;
239 u32 device_info;
240 int id;
241 int channel;
242 u16 slot;
243 u8 hidden_raid_component;
244 u8 responding;
245};
246
247/**
248 * struct _raid_device - raid volume link list
249 * @list: sas device list
250 * @starget: starget object
251 * @sdev: scsi device struct (volumes are single lun)
252 * @wwid: unique identifier for the volume
253 * @handle: device handle
254 * @id: target id
255 * @channel: target channel
256 * @volume_type: the raid level
257 * @device_info: bitfield provides detailed info about the hidden components
258 * @num_pds: number of hidden raid components
259 * @responding: used in _scsih_raid_device_mark_responding
260 */
261struct _raid_device {
262 struct list_head list;
263 struct scsi_target *starget;
264 struct scsi_device *sdev;
265 u64 wwid;
266 u16 handle;
267 int id;
268 int channel;
269 u8 volume_type;
270 u32 device_info;
271 u8 num_pds;
272 u8 responding;
273};
274
275/**
276 * struct _boot_device - boot device info
277 * @is_raid: flag to indicate whether this is volume
278 * @device: holds pointer for either struct _sas_device or
279 * struct _raid_device
280 */
281struct _boot_device {
282 u8 is_raid;
283 void *device;
284};
285
286/**
287 * struct _sas_port - wide/narrow sas port information
288 * @port_list: list of ports belonging to expander
289 * @handle: device handle for this port
290 * @sas_address: sas address of this port
291 * @num_phys: number of phys belonging to this port
292 * @remote_identify: attached device identification
293 * @rphy: sas transport rphy object
294 * @port: sas transport wide/narrow port object
295 * @phy_list: _sas_phy list objects belonging to this port
296 */
297struct _sas_port {
298 struct list_head port_list;
299 u16 handle;
300 u64 sas_address;
301 u8 num_phys;
302 struct sas_identify remote_identify;
303 struct sas_rphy *rphy;
304 struct sas_port *port;
305 struct list_head phy_list;
306};
307
308/**
309 * struct _sas_phy - phy information
310 * @port_siblings: list of phys belonging to a port
311 * @identify: phy identification
312 * @remote_identify: attached device identification
313 * @phy: sas transport phy object
314 * @phy_id: unique phy id
315 * @handle: device handle for this phy
316 * @attached_handle: device handle for attached device
317 */
318struct _sas_phy {
319 struct list_head port_siblings;
320 struct sas_identify identify;
321 struct sas_identify remote_identify;
322 struct sas_phy *phy;
323 u8 phy_id;
324 u16 handle;
325 u16 attached_handle;
326};
327
328/**
329 * struct _sas_node - sas_host/expander information
330 * @list: list of expanders
331 * @parent_dev: parent device class
332 * @num_phys: number phys belonging to this sas_host/expander
333 * @sas_address: sas address of this sas_host/expander
334 * @handle: handle for this sas_host/expander
335 * @parent_handle: parent handle
336 * @enclosure_handle: handle for this a member of an enclosure
337 * @device_info: bitwise defining capabilities of this sas_host/expander
338 * @responding: used in _scsih_expander_device_mark_responding
339 * @phy: a list of phys that make up this sas_host/expander
340 * @sas_port_list: list of ports attached to this sas_host/expander
341 */
342struct _sas_node {
343 struct list_head list;
344 struct device *parent_dev;
345 u8 num_phys;
346 u64 sas_address;
347 u16 handle;
348 u16 parent_handle;
349 u16 enclosure_handle;
350 u64 enclosure_logical_id;
351 u8 responding;
352 struct _sas_phy *phy;
353 struct list_head sas_port_list;
354};
355
356/**
357 * enum reset_type - reset state
358 * @FORCE_BIG_HAMMER: issue diagnostic reset
359 * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer
360 */
361enum reset_type {
362 FORCE_BIG_HAMMER,
363 SOFT_RESET,
364};
365
366/**
367 * struct request_tracker - firmware request tracker
368 * @smid: system message id
369 * @scmd: scsi request pointer
370 * @cb_idx: callback index
371 * @chain_list: list of chains associated to this IO
372 * @tracker_list: list of free request (ioc->free_list)
373 */
374struct request_tracker {
375 u16 smid;
376 struct scsi_cmnd *scmd;
377 u8 cb_idx;
378 struct list_head tracker_list;
379};
380
381typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
382
383/**
384 * struct MPT2SAS_ADAPTER - per adapter struct
385 * @list: ioc_list
386 * @shost: shost object
387 * @id: unique adapter id
388 * @pci_irq: irq number
389 * @name: generic ioc string
390 * @tmp_string: tmp string used for logging
391 * @pdev: pci pdev object
392 * @chip: memory mapped register space
393 * @chip_phys: physical addrss prior to mapping
394 * @pio_chip: I/O mapped register space
395 * @logging_level: see mpt2sas_debug.h
396 * @ir_firmware: IR firmware present
397 * @bars: bitmask of BAR's that must be configured
398 * @mask_interrupts: ignore interrupt
399 * @fault_reset_work_q_name: fw fault work queue
400 * @fault_reset_work_q: ""
401 * @fault_reset_work: ""
402 * @firmware_event_name: fw event work queue
403 * @firmware_event_thread: ""
404 * @fw_events_off: flag to turn off fw event handling
405 * @fw_event_lock:
406 * @fw_event_list: list of fw events
407 * @aen_event_read_flag: event log was read
408 * @broadcast_aen_busy: broadcast aen waiting to be serviced
409 * @ioc_reset_in_progress: host reset in progress
410 * @ioc_reset_in_progress_lock:
411 * @ioc_link_reset_in_progress: phy/hard reset in progress
412 * @ignore_loginfos: ignore loginfos during task managment
413 * @remove_host: flag for when driver unloads, to avoid sending dev resets
414 * @wait_for_port_enable_to_complete:
415 * @msix_enable: flag indicating msix is enabled
416 * @msix_vector_count: number msix vectors
417 * @msix_table: virt address to the msix table
418 * @msix_table_backup: backup msix table
419 * @scsi_io_cb_idx: shost generated commands
420 * @tm_cb_idx: task management commands
421 * @transport_cb_idx: transport internal commands
422 * @ctl_cb_idx: clt internal commands
423 * @base_cb_idx: base internal commands
424 * @config_cb_idx: base internal commands
425 * @base_cmds:
426 * @transport_cmds:
427 * @tm_cmds:
428 * @ctl_cmds:
429 * @config_cmds:
430 * @base_add_sg_single: handler for either 32/64 bit sgl's
431 * @event_type: bits indicating which events to log
432 * @event_context: unique id for each logged event
433 * @event_log: event log pointer
434 * @event_masks: events that are masked
435 * @facts: static facts data
436 * @pfacts: static port facts data
437 * @manu_pg0: static manufacturing page 0
438 * @bios_pg2: static bios page 2
439 * @bios_pg3: static bios page 3
440 * @ioc_pg8: static ioc page 8
441 * @iounit_pg0: static iounit page 0
442 * @iounit_pg1: static iounit page 1
443 * @sas_hba: sas host object
444 * @sas_expander_list: expander object list
445 * @sas_node_lock:
446 * @sas_device_list: sas device object list
447 * @sas_device_init_list: sas device object list (used only at init time)
448 * @sas_device_lock:
449 * @io_missing_delay: time for IO completed by fw when PDR enabled
450 * @device_missing_delay: time for device missing by fw when PDR enabled
451 * @config_page_sz: config page size
452 * @config_page: reserve memory for config page payload
453 * @config_page_dma:
454 * @sge_size: sg element size for either 32/64 bit
455 * @request_depth: hba request queue depth
456 * @request_sz: per request frame size
457 * @request: pool of request frames
458 * @request_dma:
459 * @request_dma_sz:
460 * @scsi_lookup: firmware request tracker list
461 * @scsi_lookup_lock:
462 * @free_list: free list of request
463 * @chain: pool of chains
464 * @pending_io_count:
465 * @reset_wq:
466 * @chain_dma:
467 * @max_sges_in_main_message: number sg elements in main message
468 * @max_sges_in_chain_message: number sg elements per chain
469 * @chains_needed_per_io: max chains per io
470 * @chain_offset_value_for_main_message: location 1st sg in main
471 * @chain_depth: total chains allocated
472 * @sense: pool of sense
473 * @sense_dma:
474 * @sense_dma_pool:
475 * @reply_depth: hba reply queue depth:
476 * @reply_sz: per reply frame size:
477 * @reply: pool of replys:
478 * @reply_dma:
479 * @reply_dma_pool:
480 * @reply_free_queue_depth: reply free depth
481 * @reply_free: pool for reply free queue (32 bit addr)
482 * @reply_free_dma:
483 * @reply_free_dma_pool:
484 * @reply_free_host_index: tail index in pool to insert free replys
485 * @reply_post_queue_depth: reply post queue depth
486 * @reply_post_free: pool for reply post (64bit descriptor)
487 * @reply_post_free_dma:
488 * @reply_post_free_dma_pool:
489 * @reply_post_host_index: head index in the pool where FW completes IO
490 */
491struct MPT2SAS_ADAPTER {
492 struct list_head list;
493 struct Scsi_Host *shost;
494 u8 id;
495 u32 pci_irq;
496 char name[MPT_NAME_LENGTH];
497 char tmp_string[MPT_STRING_LENGTH];
498 struct pci_dev *pdev;
499 Mpi2SystemInterfaceRegs_t __iomem *chip;
500 unsigned long chip_phys;
501 unsigned long pio_chip;
502 int logging_level;
503 u8 ir_firmware;
504 int bars;
505 u8 mask_interrupts;
506
507 /* fw fault handler */
508 char fault_reset_work_q_name[20];
509 struct workqueue_struct *fault_reset_work_q;
510 struct delayed_work fault_reset_work;
511
512 /* fw event handler */
513 char firmware_event_name[20];
514 struct workqueue_struct *firmware_event_thread;
515 u8 fw_events_off;
516 spinlock_t fw_event_lock;
517 struct list_head fw_event_list;
518
519 /* misc flags */
520 int aen_event_read_flag;
521 u8 broadcast_aen_busy;
522 u8 ioc_reset_in_progress;
523 u8 shost_recovery;
524 spinlock_t ioc_reset_in_progress_lock;
525 u8 ioc_link_reset_in_progress;
526 u8 ignore_loginfos;
527 u8 remove_host;
528 u8 wait_for_port_enable_to_complete;
529
530 u8 msix_enable;
531 u16 msix_vector_count;
532 u32 *msix_table;
533 u32 *msix_table_backup;
534
535 /* internal commands, callback index */
536 u8 scsi_io_cb_idx;
537 u8 tm_cb_idx;
538 u8 transport_cb_idx;
539 u8 ctl_cb_idx;
540 u8 base_cb_idx;
541 u8 config_cb_idx;
542 struct _internal_cmd base_cmds;
543 struct _internal_cmd transport_cmds;
544 struct _internal_cmd tm_cmds;
545 struct _internal_cmd ctl_cmds;
546 struct _internal_cmd config_cmds;
547
548 MPT_ADD_SGE base_add_sg_single;
549
550 /* event log */
551 u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
552 u32 event_context;
553 void *event_log;
554 u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
555
556 /* static config pages */
557 Mpi2IOCFactsReply_t facts;
558 Mpi2PortFactsReply_t *pfacts;
559 Mpi2ManufacturingPage0_t manu_pg0;
560 Mpi2BiosPage2_t bios_pg2;
561 Mpi2BiosPage3_t bios_pg3;
562 Mpi2IOCPage8_t ioc_pg8;
563 Mpi2IOUnitPage0_t iounit_pg0;
564 Mpi2IOUnitPage1_t iounit_pg1;
565
566 struct _boot_device req_boot_device;
567 struct _boot_device req_alt_boot_device;
568 struct _boot_device current_boot_device;
569
570 /* sas hba, expander, and device list */
571 struct _sas_node sas_hba;
572 struct list_head sas_expander_list;
573 spinlock_t sas_node_lock;
574 struct list_head sas_device_list;
575 struct list_head sas_device_init_list;
576 spinlock_t sas_device_lock;
577 struct list_head raid_device_list;
578 spinlock_t raid_device_lock;
579 u8 io_missing_delay;
580 u16 device_missing_delay;
581 int sas_id;
582
583 /* config page */
584 u16 config_page_sz;
585 void *config_page;
586 dma_addr_t config_page_dma;
587
588 /* request */
589 u16 sge_size;
590 u16 request_depth;
591 u16 request_sz;
592 u8 *request;
593 dma_addr_t request_dma;
594 u32 request_dma_sz;
595 struct request_tracker *scsi_lookup;
596 spinlock_t scsi_lookup_lock;
597 struct list_head free_list;
598 int pending_io_count;
599 wait_queue_head_t reset_wq;
600
601 /* chain */
602 u8 *chain;
603 dma_addr_t chain_dma;
604 u16 max_sges_in_main_message;
605 u16 max_sges_in_chain_message;
606 u16 chains_needed_per_io;
607 u16 chain_offset_value_for_main_message;
608 u16 chain_depth;
609
610 /* sense */
611 u8 *sense;
612 dma_addr_t sense_dma;
613 struct dma_pool *sense_dma_pool;
614
615 /* reply */
616 u16 reply_sz;
617 u8 *reply;
618 dma_addr_t reply_dma;
619 struct dma_pool *reply_dma_pool;
620
621 /* reply free queue */
622 u16 reply_free_queue_depth;
623 u32 *reply_free;
624 dma_addr_t reply_free_dma;
625 struct dma_pool *reply_free_dma_pool;
626 u32 reply_free_host_index;
627
628 /* reply post queue */
629 u16 reply_post_queue_depth;
630 Mpi2ReplyDescriptorsUnion_t *reply_post_free;
631 dma_addr_t reply_post_free_dma;
632 struct dma_pool *reply_post_free_dma_pool;
633 u32 reply_post_host_index;
634
635 /* diag buffer support */
636 u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
637 u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT];
638 dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT];
639 u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT];
640 u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT];
641 u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
642 u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
643};
644
645typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
646 u32 reply);
647
648
649/* base shared API */
650extern struct list_head ioc_list;
651
652int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc);
653void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc);
654int mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc);
655void mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc);
656int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
657 enum reset_type type);
658
659void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid);
660void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid);
661void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr);
662dma_addr_t mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid);
663dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid);
664
665u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx);
666void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid);
667void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id,
668 u16 handle);
669void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id);
670void mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
671 u8 vf_id, u16 io_index);
672void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id);
673void mpt2sas_base_initialize_callback_handler(void);
674u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func);
675void mpt2sas_base_release_callback_handler(u8 cb_idx);
676
677void mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
678void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr);
679
680u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked);
681
682void mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code);
683int mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
684 Mpi2SasIoUnitControlReply_t *mpi_reply, Mpi2SasIoUnitControlRequest_t
685 *mpi_request);
686int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
687 Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request);
688void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type);
689
690/* scsih shared API */
691void mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
692 u8 type, u16 smid_task, ulong timeout);
693void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
694void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
695struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc,
696 u16 handle);
697struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
698 *ioc, u64 sas_address);
699struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address(
700 struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
701
702void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply);
703void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
704
705/* config shared API */
706void mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
707int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys);
708int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
709 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
710int mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
711 *mpi_reply, Mpi2BiosPage2_t *config_page);
712int mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
713 *mpi_reply, Mpi2BiosPage3_t *config_page);
714int mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
715 *mpi_reply, Mpi2IOUnitPage0_t *config_page);
716int mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
717 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle);
718int mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
719 *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle);
720int mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
721 *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz);
722int mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
723 *mpi_reply, Mpi2IOUnitPage1_t *config_page);
724int mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
725 *mpi_reply, Mpi2IOUnitPage1_t config_page);
726int mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
727 *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz);
728int mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
729 *mpi_reply, Mpi2IOCPage8_t *config_page);
730int mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
731 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle);
732int mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
733 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, u16 handle);
734int mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
735 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle);
736int mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
737 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number);
738int mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
739 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number);
740int mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
741 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u32 handle);
742int mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 *num_pds);
743int mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
744 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, u32 handle, u16 sz);
745int mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
746 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
747 u32 form_specific);
748int mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
749 u16 *volume_handle);
750int mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
751 u64 *wwid);
752
753/* ctl shared API */
754extern struct device_attribute *mpt2sas_host_attrs[];
755extern struct device_attribute *mpt2sas_dev_attrs[];
756void mpt2sas_ctl_init(void);
757void mpt2sas_ctl_exit(void);
758void mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
759void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
760void mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply);
761void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
762 Mpi2EventNotificationReply_t *mpi_reply);
763
764/* transport shared API */
765void mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
766struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc,
767 u16 handle, u16 parent_handle);
768void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
769 u16 parent_handle);
770int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
771 *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);
772int mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
773 *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev);
774void mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc, u16 handle,
775 u16 attached_handle, u8 phy_number, u8 link_rate);
776extern struct sas_function_template mpt2sas_transport_functions;
777extern struct scsi_transport_template *mpt2sas_transport_template;
778
779#endif /* MPT2SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
new file mode 100644
index 000000000000..58cfb97846f7
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -0,0 +1,1873 @@
1/*
2 * This module provides common API for accessing firmware configuration pages
3 *
4 * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
5 * Copyright (C) 2007-2008 LSI Corporation
6 * (mailto:DL-MPTFusionLinux@lsi.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * NO WARRANTY
19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23 * solely responsible for determining the appropriateness of using and
24 * distributing the Program and assumes all risks associated with its
25 * exercise of rights under this Agreement, including but not limited to
26 * the risks and costs of program errors, damage to or loss of data,
27 * programs or equipment, and unavailability or interruption of operations.
28
29 * DISCLAIMER OF LIABILITY
30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
41 * USA.
42 */
43
44#include <linux/version.h>
45#include <linux/module.h>
46#include <linux/kernel.h>
47#include <linux/init.h>
48#include <linux/errno.h>
49#include <linux/blkdev.h>
50#include <linux/sched.h>
51#include <linux/workqueue.h>
52#include <linux/delay.h>
53#include <linux/pci.h>
54
55#include "mpt2sas_base.h"
56
57/* local definitions */
58
59/* Timeout for config page request (in seconds) */
60#define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15
61
62/* Common sgl flags for READING a config page. */
63#define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
64 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
65 | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
66
67/* Common sgl flags for WRITING a config page. */
68#define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
69 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
70 | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
71 << MPI2_SGE_FLAGS_SHIFT)
72
73/**
74 * struct config_request - obtain dma memory via routine
75 * @config_page_sz: size
76 * @config_page: virt pointer
77 * @config_page_dma: phys pointer
78 *
79 */
80struct config_request{
81 u16 config_page_sz;
82 void *config_page;
83 dma_addr_t config_page_dma;
84};
85
86#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
87/**
88 * _config_display_some_debug - debug routine
89 * @ioc: per adapter object
90 * @smid: system request message index
91 * @calling_function_name: string pass from calling function
92 * @mpi_reply: reply message frame
93 * Context: none.
94 *
95 * Function for displaying debug info helpfull when debugging issues
96 * in this module.
97 */
98static void
99_config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
100 char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
101{
102 Mpi2ConfigRequest_t *mpi_request;
103 char *desc = NULL;
104
105 if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
106 return;
107
108 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
109 switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
110 case MPI2_CONFIG_PAGETYPE_IO_UNIT:
111 desc = "io_unit";
112 break;
113 case MPI2_CONFIG_PAGETYPE_IOC:
114 desc = "ioc";
115 break;
116 case MPI2_CONFIG_PAGETYPE_BIOS:
117 desc = "bios";
118 break;
119 case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
120 desc = "raid_volume";
121 break;
122 case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
123 desc = "manufaucturing";
124 break;
125 case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
126 desc = "physdisk";
127 break;
128 case MPI2_CONFIG_PAGETYPE_EXTENDED:
129 switch (mpi_request->ExtPageType) {
130 case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
131 desc = "sas_io_unit";
132 break;
133 case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
134 desc = "sas_expander";
135 break;
136 case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
137 desc = "sas_device";
138 break;
139 case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
140 desc = "sas_phy";
141 break;
142 case MPI2_CONFIG_EXTPAGETYPE_LOG:
143 desc = "log";
144 break;
145 case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
146 desc = "enclosure";
147 break;
148 case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
149 desc = "raid_config";
150 break;
151 case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
152 desc = "driver_mappping";
153 break;
154 }
155 break;
156 }
157
158 if (!desc)
159 return;
160
161 printk(MPT2SAS_DEBUG_FMT "%s: %s(%d), action(%d), form(0x%08x), "
162 "smid(%d)\n", ioc->name, calling_function_name, desc,
163 mpi_request->Header.PageNumber, mpi_request->Action,
164 le32_to_cpu(mpi_request->PageAddress), smid);
165
166 if (!mpi_reply)
167 return;
168
169 if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
170 printk(MPT2SAS_DEBUG_FMT
171 "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
172 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
173 le32_to_cpu(mpi_reply->IOCLogInfo));
174}
175#endif
176
177/**
178 * mpt2sas_config_done - config page completion routine
179 * @ioc: per adapter object
180 * @smid: system request message index
181 * @VF_ID: virtual function id
182 * @reply: reply message frame(lower 32bit addr)
183 * Context: none.
184 *
185 * The callback handler when using _config_request.
186 *
187 * Return nothing.
188 */
189void
190mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
191{
192 MPI2DefaultReply_t *mpi_reply;
193
194 if (ioc->config_cmds.status == MPT2_CMD_NOT_USED)
195 return;
196 if (ioc->config_cmds.smid != smid)
197 return;
198 ioc->config_cmds.status |= MPT2_CMD_COMPLETE;
199 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
200 if (mpi_reply) {
201 ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID;
202 memcpy(ioc->config_cmds.reply, mpi_reply,
203 mpi_reply->MsgLength*4);
204 }
205 ioc->config_cmds.status &= ~MPT2_CMD_PENDING;
206#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
207 _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
208#endif
209 complete(&ioc->config_cmds.done);
210}
211
212/**
213 * _config_request - main routine for sending config page requests
214 * @ioc: per adapter object
215 * @mpi_request: request message frame
216 * @mpi_reply: reply mf payload returned from firmware
217 * @timeout: timeout in seconds
218 * Context: sleep, the calling function needs to acquire the config_cmds.mutex
219 *
220 * A generic API for config page requests to firmware.
221 *
222 * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling
223 * this API.
224 *
225 * The callback index is set inside `ioc->config_cb_idx.
226 *
227 * Returns 0 for success, non-zero for failure.
228 */
229static int
230_config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
231 *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout)
232{
233 u16 smid;
234 u32 ioc_state;
235 unsigned long timeleft;
236 Mpi2ConfigRequest_t *config_request;
237 int r;
238 u8 retry_count;
239 u8 issue_reset;
240 u16 wait_state_count;
241
242 if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
243 printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
244 ioc->name, __func__);
245 return -EAGAIN;
246 }
247 retry_count = 0;
248
249 retry_config:
250 wait_state_count = 0;
251 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
252 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
253 if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) {
254 printk(MPT2SAS_ERR_FMT
255 "%s: failed due to ioc not operational\n",
256 ioc->name, __func__);
257 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
258 return -EFAULT;
259 }
260 ssleep(1);
261 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
262 printk(MPT2SAS_INFO_FMT "%s: waiting for "
263 "operational state(count=%d)\n", ioc->name,
264 __func__, wait_state_count);
265 }
266 if (wait_state_count)
267 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
268 ioc->name, __func__);
269
270 smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx);
271 if (!smid) {
272 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
273 ioc->name, __func__);
274 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
275 return -EAGAIN;
276 }
277
278 r = 0;
279 memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
280 ioc->config_cmds.status = MPT2_CMD_PENDING;
281 config_request = mpt2sas_base_get_msg_frame(ioc, smid);
282 ioc->config_cmds.smid = smid;
283 memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
284#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
285 _config_display_some_debug(ioc, smid, "config_request", NULL);
286#endif
287 mpt2sas_base_put_smid_default(ioc, smid, config_request->VF_ID);
288 timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
289 timeout*HZ);
290 if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) {
291 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
292 ioc->name, __func__);
293 _debug_dump_mf(mpi_request,
294 sizeof(Mpi2ConfigRequest_t)/4);
295 if (!(ioc->config_cmds.status & MPT2_CMD_RESET))
296 issue_reset = 1;
297 goto issue_host_reset;
298 }
299 if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
300 memcpy(mpi_reply, ioc->config_cmds.reply,
301 sizeof(Mpi2ConfigReply_t));
302 if (retry_count)
303 printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n",
304 ioc->name, __func__);
305 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
306 return r;
307
308 issue_host_reset:
309 if (issue_reset)
310 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
311 FORCE_BIG_HAMMER);
312 ioc->config_cmds.status = MPT2_CMD_NOT_USED;
313 if (!retry_count) {
314 printk(MPT2SAS_INFO_FMT "%s: attempting retry\n",
315 ioc->name, __func__);
316 retry_count++;
317 goto retry_config;
318 }
319 return -EFAULT;
320}
321
322/**
323 * _config_alloc_config_dma_memory - obtain physical memory
324 * @ioc: per adapter object
325 * @mem: struct config_request
326 *
327 * A wrapper for obtaining dma-able memory for config page request.
328 *
329 * Returns 0 for success, non-zero for failure.
330 */
331static int
332_config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
333 struct config_request *mem)
334{
335 int r = 0;
336
337 mem->config_page = pci_alloc_consistent(ioc->pdev, mem->config_page_sz,
338 &mem->config_page_dma);
339 if (!mem->config_page)
340 r = -ENOMEM;
341 return r;
342}
343
344/**
345 * _config_free_config_dma_memory - wrapper to free the memory
346 * @ioc: per adapter object
347 * @mem: struct config_request
348 *
349 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
350 *
351 * Returns 0 for success, non-zero for failure.
352 */
353static void
354_config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
355 struct config_request *mem)
356{
357 pci_free_consistent(ioc->pdev, mem->config_page_sz, mem->config_page,
358 mem->config_page_dma);
359}
360
361/**
362 * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
363 * @ioc: per adapter object
364 * @mpi_reply: reply mf payload returned from firmware
365 * @config_page: contents of the config page
366 * Context: sleep.
367 *
368 * Returns 0 for success, non-zero for failure.
369 */
370int
371mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
372 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
373{
374 Mpi2ConfigRequest_t mpi_request;
375 int r;
376 struct config_request mem;
377
378 mutex_lock(&ioc->config_cmds.mutex);
379 memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t));
380 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
381 mpi_request.Function = MPI2_FUNCTION_CONFIG;
382 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
383 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
384 mpi_request.Header.PageNumber = 0;
385 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
386 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
387 r = _config_request(ioc, &mpi_request, mpi_reply,
388 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
389 if (r)
390 goto out;
391
392 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
393 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
394 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
395 mpi_request.Header.PageType = mpi_reply->Header.PageType;
396 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
397 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
398 if (mem.config_page_sz > ioc->config_page_sz) {
399 r = _config_alloc_config_dma_memory(ioc, &mem);
400 if (r)
401 goto out;
402 } else {
403 mem.config_page_dma = ioc->config_page_dma;
404 mem.config_page = ioc->config_page;
405 }
406 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
407 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
408 mem.config_page_dma);
409 r = _config_request(ioc, &mpi_request, mpi_reply,
410 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
411 if (!r)
412 memcpy(config_page, mem.config_page,
413 min_t(u16, mem.config_page_sz,
414 sizeof(Mpi2ManufacturingPage0_t)));
415
416 if (mem.config_page_sz > ioc->config_page_sz)
417 _config_free_config_dma_memory(ioc, &mem);
418
419 out:
420 mutex_unlock(&ioc->config_cmds.mutex);
421 return r;
422}
423
424/**
425 * mpt2sas_config_get_bios_pg2 - obtain bios page 2
426 * @ioc: per adapter object
427 * @mpi_reply: reply mf payload returned from firmware
428 * @config_page: contents of the config page
429 * Context: sleep.
430 *
431 * Returns 0 for success, non-zero for failure.
432 */
433int
434mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
435 Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
436{
437 Mpi2ConfigRequest_t mpi_request;
438 int r;
439 struct config_request mem;
440
441 mutex_lock(&ioc->config_cmds.mutex);
442 memset(config_page, 0, sizeof(Mpi2BiosPage2_t));
443 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
444 mpi_request.Function = MPI2_FUNCTION_CONFIG;
445 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
446 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
447 mpi_request.Header.PageNumber = 2;
448 mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
449 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
450 r = _config_request(ioc, &mpi_request, mpi_reply,
451 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
452 if (r)
453 goto out;
454
455 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
456 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
457 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
458 mpi_request.Header.PageType = mpi_reply->Header.PageType;
459 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
460 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
461 if (mem.config_page_sz > ioc->config_page_sz) {
462 r = _config_alloc_config_dma_memory(ioc, &mem);
463 if (r)
464 goto out;
465 } else {
466 mem.config_page_dma = ioc->config_page_dma;
467 mem.config_page = ioc->config_page;
468 }
469 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
470 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
471 mem.config_page_dma);
472 r = _config_request(ioc, &mpi_request, mpi_reply,
473 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
474 if (!r)
475 memcpy(config_page, mem.config_page,
476 min_t(u16, mem.config_page_sz,
477 sizeof(Mpi2BiosPage2_t)));
478
479 if (mem.config_page_sz > ioc->config_page_sz)
480 _config_free_config_dma_memory(ioc, &mem);
481
482 out:
483 mutex_unlock(&ioc->config_cmds.mutex);
484 return r;
485}
486
487/**
488 * mpt2sas_config_get_bios_pg3 - obtain bios page 3
489 * @ioc: per adapter object
490 * @mpi_reply: reply mf payload returned from firmware
491 * @config_page: contents of the config page
492 * Context: sleep.
493 *
494 * Returns 0 for success, non-zero for failure.
495 */
496int
497mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
498 *mpi_reply, Mpi2BiosPage3_t *config_page)
499{
500 Mpi2ConfigRequest_t mpi_request;
501 int r;
502 struct config_request mem;
503
504 mutex_lock(&ioc->config_cmds.mutex);
505 memset(config_page, 0, sizeof(Mpi2BiosPage3_t));
506 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
507 mpi_request.Function = MPI2_FUNCTION_CONFIG;
508 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
509 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
510 mpi_request.Header.PageNumber = 3;
511 mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
512 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
513 r = _config_request(ioc, &mpi_request, mpi_reply,
514 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
515 if (r)
516 goto out;
517
518 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
519 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
520 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
521 mpi_request.Header.PageType = mpi_reply->Header.PageType;
522 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
523 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
524 if (mem.config_page_sz > ioc->config_page_sz) {
525 r = _config_alloc_config_dma_memory(ioc, &mem);
526 if (r)
527 goto out;
528 } else {
529 mem.config_page_dma = ioc->config_page_dma;
530 mem.config_page = ioc->config_page;
531 }
532 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
533 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
534 mem.config_page_dma);
535 r = _config_request(ioc, &mpi_request, mpi_reply,
536 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
537 if (!r)
538 memcpy(config_page, mem.config_page,
539 min_t(u16, mem.config_page_sz,
540 sizeof(Mpi2BiosPage3_t)));
541
542 if (mem.config_page_sz > ioc->config_page_sz)
543 _config_free_config_dma_memory(ioc, &mem);
544
545 out:
546 mutex_unlock(&ioc->config_cmds.mutex);
547 return r;
548}
549
550/**
551 * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0
552 * @ioc: per adapter object
553 * @mpi_reply: reply mf payload returned from firmware
554 * @config_page: contents of the config page
555 * Context: sleep.
556 *
557 * Returns 0 for success, non-zero for failure.
558 */
559int
560mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
561 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
562{
563 Mpi2ConfigRequest_t mpi_request;
564 int r;
565 struct config_request mem;
566
567 mutex_lock(&ioc->config_cmds.mutex);
568 memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t));
569 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
570 mpi_request.Function = MPI2_FUNCTION_CONFIG;
571 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
572 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
573 mpi_request.Header.PageNumber = 0;
574 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
575 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
576 r = _config_request(ioc, &mpi_request, mpi_reply,
577 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
578 if (r)
579 goto out;
580
581 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
582 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
583 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
584 mpi_request.Header.PageType = mpi_reply->Header.PageType;
585 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
586 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
587 if (mem.config_page_sz > ioc->config_page_sz) {
588 r = _config_alloc_config_dma_memory(ioc, &mem);
589 if (r)
590 goto out;
591 } else {
592 mem.config_page_dma = ioc->config_page_dma;
593 mem.config_page = ioc->config_page;
594 }
595 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
596 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
597 mem.config_page_dma);
598 r = _config_request(ioc, &mpi_request, mpi_reply,
599 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
600 if (!r)
601 memcpy(config_page, mem.config_page,
602 min_t(u16, mem.config_page_sz,
603 sizeof(Mpi2IOUnitPage0_t)));
604
605 if (mem.config_page_sz > ioc->config_page_sz)
606 _config_free_config_dma_memory(ioc, &mem);
607
608 out:
609 mutex_unlock(&ioc->config_cmds.mutex);
610 return r;
611}
612
613/**
614 * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1
615 * @ioc: per adapter object
616 * @mpi_reply: reply mf payload returned from firmware
617 * @config_page: contents of the config page
618 * Context: sleep.
619 *
620 * Returns 0 for success, non-zero for failure.
621 */
622int
623mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
624 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
625{
626 Mpi2ConfigRequest_t mpi_request;
627 int r;
628 struct config_request mem;
629
630 mutex_lock(&ioc->config_cmds.mutex);
631 memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t));
632 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
633 mpi_request.Function = MPI2_FUNCTION_CONFIG;
634 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
635 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
636 mpi_request.Header.PageNumber = 1;
637 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
638 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
639 r = _config_request(ioc, &mpi_request, mpi_reply,
640 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
641 if (r)
642 goto out;
643
644 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
645 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
646 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
647 mpi_request.Header.PageType = mpi_reply->Header.PageType;
648 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
649 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
650 if (mem.config_page_sz > ioc->config_page_sz) {
651 r = _config_alloc_config_dma_memory(ioc, &mem);
652 if (r)
653 goto out;
654 } else {
655 mem.config_page_dma = ioc->config_page_dma;
656 mem.config_page = ioc->config_page;
657 }
658 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
659 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
660 mem.config_page_dma);
661 r = _config_request(ioc, &mpi_request, mpi_reply,
662 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
663 if (!r)
664 memcpy(config_page, mem.config_page,
665 min_t(u16, mem.config_page_sz,
666 sizeof(Mpi2IOUnitPage1_t)));
667
668 if (mem.config_page_sz > ioc->config_page_sz)
669 _config_free_config_dma_memory(ioc, &mem);
670
671 out:
672 mutex_unlock(&ioc->config_cmds.mutex);
673 return r;
674}
675
676/**
677 * mpt2sas_config_set_iounit_pg1 - set iounit page 1
678 * @ioc: per adapter object
679 * @mpi_reply: reply mf payload returned from firmware
680 * @config_page: contents of the config page
681 * Context: sleep.
682 *
683 * Returns 0 for success, non-zero for failure.
684 */
685int
686mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
687 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t config_page)
688{
689 Mpi2ConfigRequest_t mpi_request;
690 int r;
691 struct config_request mem;
692
693 mutex_lock(&ioc->config_cmds.mutex);
694 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
695 mpi_request.Function = MPI2_FUNCTION_CONFIG;
696 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
697 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
698 mpi_request.Header.PageNumber = 1;
699 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
700 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
701 r = _config_request(ioc, &mpi_request, mpi_reply,
702 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
703 if (r)
704 goto out;
705
706 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
707 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
708 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
709 mpi_request.Header.PageType = mpi_reply->Header.PageType;
710 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
711 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
712 if (mem.config_page_sz > ioc->config_page_sz) {
713 r = _config_alloc_config_dma_memory(ioc, &mem);
714 if (r)
715 goto out;
716 } else {
717 mem.config_page_dma = ioc->config_page_dma;
718 mem.config_page = ioc->config_page;
719 }
720
721 memset(mem.config_page, 0, mem.config_page_sz);
722 memcpy(mem.config_page, &config_page,
723 sizeof(Mpi2IOUnitPage1_t));
724
725 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
726 MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.config_page_sz,
727 mem.config_page_dma);
728 r = _config_request(ioc, &mpi_request, mpi_reply,
729 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
730
731 if (mem.config_page_sz > ioc->config_page_sz)
732 _config_free_config_dma_memory(ioc, &mem);
733
734 out:
735 mutex_unlock(&ioc->config_cmds.mutex);
736 return r;
737}
738
739/**
740 * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8
741 * @ioc: per adapter object
742 * @mpi_reply: reply mf payload returned from firmware
743 * @config_page: contents of the config page
744 * Context: sleep.
745 *
746 * Returns 0 for success, non-zero for failure.
747 */
748int
749mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
750 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
751{
752 Mpi2ConfigRequest_t mpi_request;
753 int r;
754 struct config_request mem;
755
756 mutex_lock(&ioc->config_cmds.mutex);
757 memset(config_page, 0, sizeof(Mpi2IOCPage8_t));
758 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
759 mpi_request.Function = MPI2_FUNCTION_CONFIG;
760 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
761 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
762 mpi_request.Header.PageNumber = 8;
763 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
764 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
765 r = _config_request(ioc, &mpi_request, mpi_reply,
766 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
767 if (r)
768 goto out;
769
770 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
771 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
772 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
773 mpi_request.Header.PageType = mpi_reply->Header.PageType;
774 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
775 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
776 if (mem.config_page_sz > ioc->config_page_sz) {
777 r = _config_alloc_config_dma_memory(ioc, &mem);
778 if (r)
779 goto out;
780 } else {
781 mem.config_page_dma = ioc->config_page_dma;
782 mem.config_page = ioc->config_page;
783 }
784 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
785 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
786 mem.config_page_dma);
787 r = _config_request(ioc, &mpi_request, mpi_reply,
788 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
789 if (!r)
790 memcpy(config_page, mem.config_page,
791 min_t(u16, mem.config_page_sz,
792 sizeof(Mpi2IOCPage8_t)));
793
794 if (mem.config_page_sz > ioc->config_page_sz)
795 _config_free_config_dma_memory(ioc, &mem);
796
797 out:
798 mutex_unlock(&ioc->config_cmds.mutex);
799 return r;
800}
801
802/**
803 * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0
804 * @ioc: per adapter object
805 * @mpi_reply: reply mf payload returned from firmware
806 * @config_page: contents of the config page
807 * @form: GET_NEXT_HANDLE or HANDLE
808 * @handle: device handle
809 * Context: sleep.
810 *
811 * Returns 0 for success, non-zero for failure.
812 */
813int
814mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
815 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle)
816{
817 Mpi2ConfigRequest_t mpi_request;
818 int r;
819 struct config_request mem;
820
821 mutex_lock(&ioc->config_cmds.mutex);
822 memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t));
823 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
824 mpi_request.Function = MPI2_FUNCTION_CONFIG;
825 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
826 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
827 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
828 mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
829 mpi_request.Header.PageNumber = 0;
830 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
831 r = _config_request(ioc, &mpi_request, mpi_reply,
832 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
833 if (r)
834 goto out;
835
836 mpi_request.PageAddress = cpu_to_le32(form | handle);
837 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
838 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
839 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
840 mpi_request.Header.PageType = mpi_reply->Header.PageType;
841 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
842 mpi_request.ExtPageType = mpi_reply->ExtPageType;
843 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
844 if (mem.config_page_sz > ioc->config_page_sz) {
845 r = _config_alloc_config_dma_memory(ioc, &mem);
846 if (r)
847 goto out;
848 } else {
849 mem.config_page_dma = ioc->config_page_dma;
850 mem.config_page = ioc->config_page;
851 }
852 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
853 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
854 mem.config_page_dma);
855 r = _config_request(ioc, &mpi_request, mpi_reply,
856 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
857 if (!r)
858 memcpy(config_page, mem.config_page,
859 min_t(u16, mem.config_page_sz,
860 sizeof(Mpi2SasDevicePage0_t)));
861
862 if (mem.config_page_sz > ioc->config_page_sz)
863 _config_free_config_dma_memory(ioc, &mem);
864
865 out:
866 mutex_unlock(&ioc->config_cmds.mutex);
867 return r;
868}
869
870/**
871 * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1
872 * @ioc: per adapter object
873 * @mpi_reply: reply mf payload returned from firmware
874 * @config_page: contents of the config page
875 * @form: GET_NEXT_HANDLE or HANDLE
876 * @handle: device handle
877 * Context: sleep.
878 *
879 * Returns 0 for success, non-zero for failure.
880 */
881int
882mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
883 *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle)
884{
885 Mpi2ConfigRequest_t mpi_request;
886 int r;
887 struct config_request mem;
888
889 mutex_lock(&ioc->config_cmds.mutex);
890 memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t));
891 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
892 mpi_request.Function = MPI2_FUNCTION_CONFIG;
893 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
894 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
895 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
896 mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
897 mpi_request.Header.PageNumber = 1;
898 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
899 r = _config_request(ioc, &mpi_request, mpi_reply,
900 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
901 if (r)
902 goto out;
903
904 mpi_request.PageAddress = cpu_to_le32(form | handle);
905 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
906 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
907 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
908 mpi_request.Header.PageType = mpi_reply->Header.PageType;
909 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
910 mpi_request.ExtPageType = mpi_reply->ExtPageType;
911 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
912 if (mem.config_page_sz > ioc->config_page_sz) {
913 r = _config_alloc_config_dma_memory(ioc, &mem);
914 if (r)
915 goto out;
916 } else {
917 mem.config_page_dma = ioc->config_page_dma;
918 mem.config_page = ioc->config_page;
919 }
920 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
921 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
922 mem.config_page_dma);
923 r = _config_request(ioc, &mpi_request, mpi_reply,
924 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
925 if (!r)
926 memcpy(config_page, mem.config_page,
927 min_t(u16, mem.config_page_sz,
928 sizeof(Mpi2SasDevicePage1_t)));
929
930 if (mem.config_page_sz > ioc->config_page_sz)
931 _config_free_config_dma_memory(ioc, &mem);
932
933 out:
934 mutex_unlock(&ioc->config_cmds.mutex);
935 return r;
936}
937
938/**
939 * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host
940 * @ioc: per adapter object
941 * @num_phys: pointer returned with the number of phys
942 * Context: sleep.
943 *
944 * Returns 0 for success, non-zero for failure.
945 */
946int
947mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
948{
949 Mpi2ConfigRequest_t mpi_request;
950 int r;
951 struct config_request mem;
952 u16 ioc_status;
953 Mpi2ConfigReply_t mpi_reply;
954 Mpi2SasIOUnitPage0_t config_page;
955
956 mutex_lock(&ioc->config_cmds.mutex);
957 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
958 mpi_request.Function = MPI2_FUNCTION_CONFIG;
959 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
960 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
961 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
962 mpi_request.Header.PageNumber = 0;
963 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
964 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
965 r = _config_request(ioc, &mpi_request, &mpi_reply,
966 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
967 if (r)
968 goto out;
969
970 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
971 mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
972 mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
973 mpi_request.Header.PageType = mpi_reply.Header.PageType;
974 mpi_request.ExtPageLength = mpi_reply.ExtPageLength;
975 mpi_request.ExtPageType = mpi_reply.ExtPageType;
976 mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4;
977 if (mem.config_page_sz > ioc->config_page_sz) {
978 r = _config_alloc_config_dma_memory(ioc, &mem);
979 if (r)
980 goto out;
981 } else {
982 mem.config_page_dma = ioc->config_page_dma;
983 mem.config_page = ioc->config_page;
984 }
985 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
986 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
987 mem.config_page_dma);
988 r = _config_request(ioc, &mpi_request, &mpi_reply,
989 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
990 if (!r) {
991 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
992 MPI2_IOCSTATUS_MASK;
993 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
994 memcpy(&config_page, mem.config_page,
995 min_t(u16, mem.config_page_sz,
996 sizeof(Mpi2SasIOUnitPage0_t)));
997 *num_phys = config_page.NumPhys;
998 }
999 }
1000
1001 if (mem.config_page_sz > ioc->config_page_sz)
1002 _config_free_config_dma_memory(ioc, &mem);
1003
1004 out:
1005 mutex_unlock(&ioc->config_cmds.mutex);
1006 return r;
1007}
1008
1009/**
1010 * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1011 * @ioc: per adapter object
1012 * @mpi_reply: reply mf payload returned from firmware
1013 * @config_page: contents of the config page
1014 * @sz: size of buffer passed in config_page
1015 * Context: sleep.
1016 *
1017 * Calling function should call config_get_number_hba_phys prior to
1018 * this function, so enough memory is allocated for config_page.
1019 *
1020 * Returns 0 for success, non-zero for failure.
1021 */
1022int
1023mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1024 *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz)
1025{
1026 Mpi2ConfigRequest_t mpi_request;
1027 int r;
1028 struct config_request mem;
1029
1030 mutex_lock(&ioc->config_cmds.mutex);
1031 memset(config_page, 0, sz);
1032 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1033 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1034 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1035 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1036 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1037 mpi_request.Header.PageNumber = 0;
1038 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1039 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1040 r = _config_request(ioc, &mpi_request, mpi_reply,
1041 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1042 if (r)
1043 goto out;
1044
1045 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1046 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1047 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1048 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1049 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1050 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1051 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1052 if (mem.config_page_sz > ioc->config_page_sz) {
1053 r = _config_alloc_config_dma_memory(ioc, &mem);
1054 if (r)
1055 goto out;
1056 } else {
1057 mem.config_page_dma = ioc->config_page_dma;
1058 mem.config_page = ioc->config_page;
1059 }
1060 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1061 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1062 mem.config_page_dma);
1063 r = _config_request(ioc, &mpi_request, mpi_reply,
1064 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1065 if (!r)
1066 memcpy(config_page, mem.config_page,
1067 min_t(u16, sz, mem.config_page_sz));
1068
1069 if (mem.config_page_sz > ioc->config_page_sz)
1070 _config_free_config_dma_memory(ioc, &mem);
1071
1072 out:
1073 mutex_unlock(&ioc->config_cmds.mutex);
1074 return r;
1075}
1076
1077/**
1078 * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 0
1079 * @ioc: per adapter object
1080 * @mpi_reply: reply mf payload returned from firmware
1081 * @config_page: contents of the config page
1082 * @sz: size of buffer passed in config_page
1083 * Context: sleep.
1084 *
1085 * Calling function should call config_get_number_hba_phys prior to
1086 * this function, so enough memory is allocated for config_page.
1087 *
1088 * Returns 0 for success, non-zero for failure.
1089 */
1090int
1091mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1092 *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
1093{
1094 Mpi2ConfigRequest_t mpi_request;
1095 int r;
1096 struct config_request mem;
1097
1098 mutex_lock(&ioc->config_cmds.mutex);
1099 memset(config_page, 0, sz);
1100 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1101 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1102 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1103 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1104 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1105 mpi_request.Header.PageNumber = 1;
1106 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1107 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1108 r = _config_request(ioc, &mpi_request, mpi_reply,
1109 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1110 if (r)
1111 goto out;
1112
1113 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1114 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1115 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1116 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1117 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1118 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1119 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1120 if (mem.config_page_sz > ioc->config_page_sz) {
1121 r = _config_alloc_config_dma_memory(ioc, &mem);
1122 if (r)
1123 goto out;
1124 } else {
1125 mem.config_page_dma = ioc->config_page_dma;
1126 mem.config_page = ioc->config_page;
1127 }
1128 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1129 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1130 mem.config_page_dma);
1131 r = _config_request(ioc, &mpi_request, mpi_reply,
1132 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1133 if (!r)
1134 memcpy(config_page, mem.config_page,
1135 min_t(u16, sz, mem.config_page_sz));
1136
1137 if (mem.config_page_sz > ioc->config_page_sz)
1138 _config_free_config_dma_memory(ioc, &mem);
1139
1140 out:
1141 mutex_unlock(&ioc->config_cmds.mutex);
1142 return r;
1143}
1144
1145/**
1146 * mpt2sas_config_get_expander_pg0 - obtain expander page 0
1147 * @ioc: per adapter object
1148 * @mpi_reply: reply mf payload returned from firmware
1149 * @config_page: contents of the config page
1150 * @form: GET_NEXT_HANDLE or HANDLE
1151 * @handle: expander handle
1152 * Context: sleep.
1153 *
1154 * Returns 0 for success, non-zero for failure.
1155 */
1156int
1157mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1158 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1159{
1160 Mpi2ConfigRequest_t mpi_request;
1161 int r;
1162 struct config_request mem;
1163
1164 mutex_lock(&ioc->config_cmds.mutex);
1165 memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t));
1166 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1167 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1168 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1169 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1170 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1171 mpi_request.Header.PageNumber = 0;
1172 mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1173 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1174 r = _config_request(ioc, &mpi_request, mpi_reply,
1175 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1176 if (r)
1177 goto out;
1178
1179 mpi_request.PageAddress = cpu_to_le32(form | handle);
1180 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1181 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1182 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1183 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1184 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1185 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1186 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1187 if (mem.config_page_sz > ioc->config_page_sz) {
1188 r = _config_alloc_config_dma_memory(ioc, &mem);
1189 if (r)
1190 goto out;
1191 } else {
1192 mem.config_page_dma = ioc->config_page_dma;
1193 mem.config_page = ioc->config_page;
1194 }
1195 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1196 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1197 mem.config_page_dma);
1198 r = _config_request(ioc, &mpi_request, mpi_reply,
1199 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1200 if (!r)
1201 memcpy(config_page, mem.config_page,
1202 min_t(u16, mem.config_page_sz,
1203 sizeof(Mpi2ExpanderPage0_t)));
1204
1205 if (mem.config_page_sz > ioc->config_page_sz)
1206 _config_free_config_dma_memory(ioc, &mem);
1207
1208 out:
1209 mutex_unlock(&ioc->config_cmds.mutex);
1210 return r;
1211}
1212
1213/**
1214 * mpt2sas_config_get_expander_pg1 - obtain expander page 1
1215 * @ioc: per adapter object
1216 * @mpi_reply: reply mf payload returned from firmware
1217 * @config_page: contents of the config page
1218 * @phy_number: phy number
1219 * @handle: expander handle
1220 * Context: sleep.
1221 *
1222 * Returns 0 for success, non-zero for failure.
1223 */
1224int
1225mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1226 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1227 u16 handle)
1228{
1229 Mpi2ConfigRequest_t mpi_request;
1230 int r;
1231 struct config_request mem;
1232
1233 mutex_lock(&ioc->config_cmds.mutex);
1234 memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t));
1235 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1236 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1237 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1238 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1239 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1240 mpi_request.Header.PageNumber = 1;
1241 mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1242 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1243 r = _config_request(ioc, &mpi_request, mpi_reply,
1244 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1245 if (r)
1246 goto out;
1247
1248 mpi_request.PageAddress =
1249 cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1250 (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1251 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1252 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1253 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1254 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1255 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1256 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1257 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1258 if (mem.config_page_sz > ioc->config_page_sz) {
1259 r = _config_alloc_config_dma_memory(ioc, &mem);
1260 if (r)
1261 goto out;
1262 } else {
1263 mem.config_page_dma = ioc->config_page_dma;
1264 mem.config_page = ioc->config_page;
1265 }
1266 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1267 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1268 mem.config_page_dma);
1269 r = _config_request(ioc, &mpi_request, mpi_reply,
1270 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1271 if (!r)
1272 memcpy(config_page, mem.config_page,
1273 min_t(u16, mem.config_page_sz,
1274 sizeof(Mpi2ExpanderPage1_t)));
1275
1276 if (mem.config_page_sz > ioc->config_page_sz)
1277 _config_free_config_dma_memory(ioc, &mem);
1278
1279 out:
1280 mutex_unlock(&ioc->config_cmds.mutex);
1281 return r;
1282}
1283
1284/**
1285 * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0
1286 * @ioc: per adapter object
1287 * @mpi_reply: reply mf payload returned from firmware
1288 * @config_page: contents of the config page
1289 * @form: GET_NEXT_HANDLE or HANDLE
1290 * @handle: expander handle
1291 * Context: sleep.
1292 *
1293 * Returns 0 for success, non-zero for failure.
1294 */
1295int
1296mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1297 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1298{
1299 Mpi2ConfigRequest_t mpi_request;
1300 int r;
1301 struct config_request mem;
1302
1303 mutex_lock(&ioc->config_cmds.mutex);
1304 memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t));
1305 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1306 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1307 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1308 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1309 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1310 mpi_request.Header.PageNumber = 0;
1311 mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1312 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1313 r = _config_request(ioc, &mpi_request, mpi_reply,
1314 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1315 if (r)
1316 goto out;
1317
1318 mpi_request.PageAddress = cpu_to_le32(form | handle);
1319 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1320 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1321 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1322 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1323 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1324 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1325 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1326 if (mem.config_page_sz > ioc->config_page_sz) {
1327 r = _config_alloc_config_dma_memory(ioc, &mem);
1328 if (r)
1329 goto out;
1330 } else {
1331 mem.config_page_dma = ioc->config_page_dma;
1332 mem.config_page = ioc->config_page;
1333 }
1334 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1335 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1336 mem.config_page_dma);
1337 r = _config_request(ioc, &mpi_request, mpi_reply,
1338 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1339 if (!r)
1340 memcpy(config_page, mem.config_page,
1341 min_t(u16, mem.config_page_sz,
1342 sizeof(Mpi2SasEnclosurePage0_t)));
1343
1344 if (mem.config_page_sz > ioc->config_page_sz)
1345 _config_free_config_dma_memory(ioc, &mem);
1346
1347 out:
1348 mutex_unlock(&ioc->config_cmds.mutex);
1349 return r;
1350}
1351
1352/**
1353 * mpt2sas_config_get_phy_pg0 - obtain phy page 0
1354 * @ioc: per adapter object
1355 * @mpi_reply: reply mf payload returned from firmware
1356 * @config_page: contents of the config page
1357 * @phy_number: phy number
1358 * Context: sleep.
1359 *
1360 * Returns 0 for success, non-zero for failure.
1361 */
1362int
1363mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1364 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1365{
1366 Mpi2ConfigRequest_t mpi_request;
1367 int r;
1368 struct config_request mem;
1369
1370 mutex_lock(&ioc->config_cmds.mutex);
1371 memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t));
1372 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1373 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1374 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1375 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1376 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1377 mpi_request.Header.PageNumber = 0;
1378 mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1379 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1380 r = _config_request(ioc, &mpi_request, mpi_reply,
1381 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1382 if (r)
1383 goto out;
1384
1385 mpi_request.PageAddress =
1386 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1387 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1388 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1389 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1390 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1391 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1392 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1393 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1394 if (mem.config_page_sz > ioc->config_page_sz) {
1395 r = _config_alloc_config_dma_memory(ioc, &mem);
1396 if (r)
1397 goto out;
1398 } else {
1399 mem.config_page_dma = ioc->config_page_dma;
1400 mem.config_page = ioc->config_page;
1401 }
1402 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1403 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1404 mem.config_page_dma);
1405 r = _config_request(ioc, &mpi_request, mpi_reply,
1406 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1407 if (!r)
1408 memcpy(config_page, mem.config_page,
1409 min_t(u16, mem.config_page_sz,
1410 sizeof(Mpi2SasPhyPage0_t)));
1411
1412 if (mem.config_page_sz > ioc->config_page_sz)
1413 _config_free_config_dma_memory(ioc, &mem);
1414
1415 out:
1416 mutex_unlock(&ioc->config_cmds.mutex);
1417 return r;
1418}
1419
1420/**
1421 * mpt2sas_config_get_phy_pg1 - obtain phy page 1
1422 * @ioc: per adapter object
1423 * @mpi_reply: reply mf payload returned from firmware
1424 * @config_page: contents of the config page
1425 * @phy_number: phy number
1426 * Context: sleep.
1427 *
1428 * Returns 0 for success, non-zero for failure.
1429 */
1430int
1431mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1432 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1433{
1434 Mpi2ConfigRequest_t mpi_request;
1435 int r;
1436 struct config_request mem;
1437
1438 mutex_lock(&ioc->config_cmds.mutex);
1439 memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t));
1440 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1441 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1442 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1443 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1444 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1445 mpi_request.Header.PageNumber = 1;
1446 mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1447 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1448 r = _config_request(ioc, &mpi_request, mpi_reply,
1449 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1450 if (r)
1451 goto out;
1452
1453 mpi_request.PageAddress =
1454 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1455 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1456 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1457 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1458 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1459 mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
1460 mpi_request.ExtPageType = mpi_reply->ExtPageType;
1461 mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
1462 if (mem.config_page_sz > ioc->config_page_sz) {
1463 r = _config_alloc_config_dma_memory(ioc, &mem);
1464 if (r)
1465 goto out;
1466 } else {
1467 mem.config_page_dma = ioc->config_page_dma;
1468 mem.config_page = ioc->config_page;
1469 }
1470 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1471 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1472 mem.config_page_dma);
1473 r = _config_request(ioc, &mpi_request, mpi_reply,
1474 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1475 if (!r)
1476 memcpy(config_page, mem.config_page,
1477 min_t(u16, mem.config_page_sz,
1478 sizeof(Mpi2SasPhyPage1_t)));
1479
1480 if (mem.config_page_sz > ioc->config_page_sz)
1481 _config_free_config_dma_memory(ioc, &mem);
1482
1483 out:
1484 mutex_unlock(&ioc->config_cmds.mutex);
1485 return r;
1486}
1487
1488/**
1489 * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1490 * @ioc: per adapter object
1491 * @mpi_reply: reply mf payload returned from firmware
1492 * @config_page: contents of the config page
1493 * @form: GET_NEXT_HANDLE or HANDLE
1494 * @handle: volume handle
1495 * Context: sleep.
1496 *
1497 * Returns 0 for success, non-zero for failure.
1498 */
1499int
1500mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
1501 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1502 u32 handle)
1503{
1504 Mpi2ConfigRequest_t mpi_request;
1505 int r;
1506 struct config_request mem;
1507
1508 mutex_lock(&ioc->config_cmds.mutex);
1509 memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t));
1510 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1511 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1512 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1513 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1514 mpi_request.Header.PageNumber = 1;
1515 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1516 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1517 r = _config_request(ioc, &mpi_request, mpi_reply,
1518 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1519 if (r)
1520 goto out;
1521
1522 mpi_request.PageAddress = cpu_to_le32(form | handle);
1523 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1524 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1525 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1526 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1527 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
1528 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
1529 if (mem.config_page_sz > ioc->config_page_sz) {
1530 r = _config_alloc_config_dma_memory(ioc, &mem);
1531 if (r)
1532 goto out;
1533 } else {
1534 mem.config_page_dma = ioc->config_page_dma;
1535 mem.config_page = ioc->config_page;
1536 }
1537 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1538 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1539 mem.config_page_dma);
1540 r = _config_request(ioc, &mpi_request, mpi_reply,
1541 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1542 if (!r)
1543 memcpy(config_page, mem.config_page,
1544 min_t(u16, mem.config_page_sz,
1545 sizeof(Mpi2RaidVolPage1_t)));
1546
1547 if (mem.config_page_sz > ioc->config_page_sz)
1548 _config_free_config_dma_memory(ioc, &mem);
1549
1550 out:
1551 mutex_unlock(&ioc->config_cmds.mutex);
1552 return r;
1553}
1554
1555/**
1556 * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume
1557 * @ioc: per adapter object
1558 * @handle: volume handle
1559 * @num_pds: returns pds count
1560 * Context: sleep.
1561 *
1562 * Returns 0 for success, non-zero for failure.
1563 */
1564int
1565mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
1566 u8 *num_pds)
1567{
1568 Mpi2ConfigRequest_t mpi_request;
1569 Mpi2RaidVolPage0_t *config_page;
1570 Mpi2ConfigReply_t mpi_reply;
1571 int r;
1572 struct config_request mem;
1573 u16 ioc_status;
1574
1575 mutex_lock(&ioc->config_cmds.mutex);
1576 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1577 *num_pds = 0;
1578 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1579 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1580 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1581 mpi_request.Header.PageNumber = 0;
1582 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1583 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1584 r = _config_request(ioc, &mpi_request, &mpi_reply,
1585 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1586 if (r)
1587 goto out;
1588
1589 mpi_request.PageAddress =
1590 cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1591 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1592 mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
1593 mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
1594 mpi_request.Header.PageType = mpi_reply.Header.PageType;
1595 mpi_request.Header.PageLength = mpi_reply.Header.PageLength;
1596 mem.config_page_sz = le16_to_cpu(mpi_reply.Header.PageLength) * 4;
1597 if (mem.config_page_sz > ioc->config_page_sz) {
1598 r = _config_alloc_config_dma_memory(ioc, &mem);
1599 if (r)
1600 goto out;
1601 } else {
1602 mem.config_page_dma = ioc->config_page_dma;
1603 mem.config_page = ioc->config_page;
1604 }
1605 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1606 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1607 mem.config_page_dma);
1608 r = _config_request(ioc, &mpi_request, &mpi_reply,
1609 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1610 if (!r) {
1611 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1612 MPI2_IOCSTATUS_MASK;
1613 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1614 config_page = mem.config_page;
1615 *num_pds = config_page->NumPhysDisks;
1616 }
1617 }
1618
1619 if (mem.config_page_sz > ioc->config_page_sz)
1620 _config_free_config_dma_memory(ioc, &mem);
1621
1622 out:
1623 mutex_unlock(&ioc->config_cmds.mutex);
1624 return r;
1625}
1626
1627/**
1628 * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1629 * @ioc: per adapter object
1630 * @mpi_reply: reply mf payload returned from firmware
1631 * @config_page: contents of the config page
1632 * @form: GET_NEXT_HANDLE or HANDLE
1633 * @handle: volume handle
1634 * @sz: size of buffer passed in config_page
1635 * Context: sleep.
1636 *
1637 * Returns 0 for success, non-zero for failure.
1638 */
1639int
1640mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
1641 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1642 u32 handle, u16 sz)
1643{
1644 Mpi2ConfigRequest_t mpi_request;
1645 int r;
1646 struct config_request mem;
1647
1648 mutex_lock(&ioc->config_cmds.mutex);
1649 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1650 memset(config_page, 0, sz);
1651 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1652 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1653 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1654 mpi_request.Header.PageNumber = 0;
1655 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1656 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1657 r = _config_request(ioc, &mpi_request, mpi_reply,
1658 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1659 if (r)
1660 goto out;
1661
1662 mpi_request.PageAddress = cpu_to_le32(form | handle);
1663 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1664 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1665 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1666 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1667 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
1668 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
1669 if (mem.config_page_sz > ioc->config_page_sz) {
1670 r = _config_alloc_config_dma_memory(ioc, &mem);
1671 if (r)
1672 goto out;
1673 } else {
1674 mem.config_page_dma = ioc->config_page_dma;
1675 mem.config_page = ioc->config_page;
1676 }
1677 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1678 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1679 mem.config_page_dma);
1680 r = _config_request(ioc, &mpi_request, mpi_reply,
1681 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1682 if (!r)
1683 memcpy(config_page, mem.config_page,
1684 min_t(u16, sz, mem.config_page_sz));
1685
1686 if (mem.config_page_sz > ioc->config_page_sz)
1687 _config_free_config_dma_memory(ioc, &mem);
1688
1689 out:
1690 mutex_unlock(&ioc->config_cmds.mutex);
1691 return r;
1692}
1693
1694/**
1695 * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1696 * @ioc: per adapter object
1697 * @mpi_reply: reply mf payload returned from firmware
1698 * @config_page: contents of the config page
1699 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1700 * @form_specific: specific to the form
1701 * Context: sleep.
1702 *
1703 * Returns 0 for success, non-zero for failure.
1704 */
1705int
1706mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1707 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1708 u32 form_specific)
1709{
1710 Mpi2ConfigRequest_t mpi_request;
1711 int r;
1712 struct config_request mem;
1713
1714 mutex_lock(&ioc->config_cmds.mutex);
1715 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1716 memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t));
1717 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1718 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1719 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1720 mpi_request.Header.PageNumber = 0;
1721 mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1722 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1723 r = _config_request(ioc, &mpi_request, mpi_reply,
1724 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1725 if (r)
1726 goto out;
1727
1728 mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1729 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1730 mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
1731 mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
1732 mpi_request.Header.PageType = mpi_reply->Header.PageType;
1733 mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
1734 mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
1735 if (mem.config_page_sz > ioc->config_page_sz) {
1736 r = _config_alloc_config_dma_memory(ioc, &mem);
1737 if (r)
1738 goto out;
1739 } else {
1740 mem.config_page_dma = ioc->config_page_dma;
1741 mem.config_page = ioc->config_page;
1742 }
1743 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1744 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1745 mem.config_page_dma);
1746 r = _config_request(ioc, &mpi_request, mpi_reply,
1747 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1748 if (!r)
1749 memcpy(config_page, mem.config_page,
1750 min_t(u16, mem.config_page_sz,
1751 sizeof(Mpi2RaidPhysDiskPage0_t)));
1752
1753 if (mem.config_page_sz > ioc->config_page_sz)
1754 _config_free_config_dma_memory(ioc, &mem);
1755
1756 out:
1757 mutex_unlock(&ioc->config_cmds.mutex);
1758 return r;
1759}
1760
1761/**
1762 * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components
1763 * @ioc: per adapter object
1764 * @pd_handle: phys disk handle
1765 * @volume_handle: volume handle
1766 * Context: sleep.
1767 *
1768 * Returns 0 for success, non-zero for failure.
1769 */
1770int
1771mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
1772 u16 *volume_handle)
1773{
1774 Mpi2RaidConfigurationPage0_t *config_page;
1775 Mpi2ConfigRequest_t mpi_request;
1776 Mpi2ConfigReply_t mpi_reply;
1777 int r, i;
1778 struct config_request mem;
1779 u16 ioc_status;
1780
1781 mutex_lock(&ioc->config_cmds.mutex);
1782 *volume_handle = 0;
1783 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1784 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1785 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1786 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1787 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1788 mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1789 mpi_request.Header.PageNumber = 0;
1790 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
1791 r = _config_request(ioc, &mpi_request, &mpi_reply,
1792 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1793 if (r)
1794 goto out;
1795
1796 mpi_request.PageAddress =
1797 cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG);
1798 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1799 mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
1800 mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
1801 mpi_request.Header.PageType = mpi_reply.Header.PageType;
1802 mpi_request.ExtPageLength = mpi_reply.ExtPageLength;
1803 mpi_request.ExtPageType = mpi_reply.ExtPageType;
1804 mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4;
1805 if (mem.config_page_sz > ioc->config_page_sz) {
1806 r = _config_alloc_config_dma_memory(ioc, &mem);
1807 if (r)
1808 goto out;
1809 } else {
1810 mem.config_page_dma = ioc->config_page_dma;
1811 mem.config_page = ioc->config_page;
1812 }
1813 ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
1814 MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
1815 mem.config_page_dma);
1816 r = _config_request(ioc, &mpi_request, &mpi_reply,
1817 MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
1818 if (r)
1819 goto out;
1820
1821 r = -1;
1822 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
1823 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1824 goto done;
1825 config_page = mem.config_page;
1826 for (i = 0; i < config_page->NumElements; i++) {
1827 if ((config_page->ConfigElement[i].ElementFlags &
1828 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) !=
1829 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT)
1830 continue;
1831 if (config_page->ConfigElement[i].PhysDiskDevHandle ==
1832 pd_handle) {
1833 *volume_handle = le16_to_cpu(config_page->
1834 ConfigElement[i].VolDevHandle);
1835 r = 0;
1836 goto done;
1837 }
1838 }
1839
1840 done:
1841 if (mem.config_page_sz > ioc->config_page_sz)
1842 _config_free_config_dma_memory(ioc, &mem);
1843
1844 out:
1845 mutex_unlock(&ioc->config_cmds.mutex);
1846 return r;
1847}
1848
1849/**
1850 * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle
1851 * @ioc: per adapter object
1852 * @volume_handle: volume handle
1853 * @wwid: volume wwid
1854 * Context: sleep.
1855 *
1856 * Returns 0 for success, non-zero for failure.
1857 */
1858int
1859mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
1860 u64 *wwid)
1861{
1862 Mpi2ConfigReply_t mpi_reply;
1863 Mpi2RaidVolPage1_t raid_vol_pg1;
1864
1865 *wwid = 0;
1866 if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1867 &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1868 volume_handle))) {
1869 *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1870 return 0;
1871 } else
1872 return -1;
1873}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
new file mode 100644
index 000000000000..4fbe3f83319b
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -0,0 +1,2516 @@
1/*
2 * Management Module Support for MPT (Message Passing Technology) based
3 * controllers
4 *
5 * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c
6 * Copyright (C) 2007-2008 LSI Corporation
7 * (mailto:DL-MPTFusionLinux@lsi.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * NO WARRANTY
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
29
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
42 * USA.
43 */
44
45#include <linux/version.h>
46#include <linux/kernel.h>
47#include <linux/module.h>
48#include <linux/errno.h>
49#include <linux/init.h>
50#include <linux/slab.h>
51#include <linux/types.h>
52#include <linux/pci.h>
53#include <linux/delay.h>
54#include <linux/smp_lock.h>
55#include <linux/compat.h>
56#include <linux/poll.h>
57
58#include <linux/io.h>
59#include <linux/uaccess.h>
60
61#include "mpt2sas_base.h"
62#include "mpt2sas_ctl.h"
63
64static struct fasync_struct *async_queue;
65static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
66
67/**
68 * enum block_state - blocking state
69 * @NON_BLOCKING: non blocking
70 * @BLOCKING: blocking
71 *
72 * These states are for ioctls that need to wait for a response
73 * from firmware, so they probably require sleep.
74 */
75enum block_state {
76 NON_BLOCKING,
77 BLOCKING,
78};
79
80#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
81/**
82 * _ctl_display_some_debug - debug routine
83 * @ioc: per adapter object
84 * @smid: system request message index
85 * @calling_function_name: string pass from calling function
86 * @mpi_reply: reply message frame
87 * Context: none.
88 *
89 * Function for displaying debug info helpfull when debugging issues
90 * in this module.
91 */
92static void
93_ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
94 char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
95{
96 Mpi2ConfigRequest_t *mpi_request;
97 char *desc = NULL;
98
99 if (!(ioc->logging_level & MPT_DEBUG_IOCTL))
100 return;
101
102 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
103 switch (mpi_request->Function) {
104 case MPI2_FUNCTION_SCSI_IO_REQUEST:
105 {
106 Mpi2SCSIIORequest_t *scsi_request =
107 (Mpi2SCSIIORequest_t *)mpi_request;
108
109 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
110 "scsi_io, cmd(0x%02x), cdb_len(%d)",
111 scsi_request->CDB.CDB32[0],
112 le16_to_cpu(scsi_request->IoFlags) & 0xF);
113 desc = ioc->tmp_string;
114 break;
115 }
116 case MPI2_FUNCTION_SCSI_TASK_MGMT:
117 desc = "task_mgmt";
118 break;
119 case MPI2_FUNCTION_IOC_INIT:
120 desc = "ioc_init";
121 break;
122 case MPI2_FUNCTION_IOC_FACTS:
123 desc = "ioc_facts";
124 break;
125 case MPI2_FUNCTION_CONFIG:
126 {
127 Mpi2ConfigRequest_t *config_request =
128 (Mpi2ConfigRequest_t *)mpi_request;
129
130 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
131 "config, type(0x%02x), ext_type(0x%02x), number(%d)",
132 (config_request->Header.PageType &
133 MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType,
134 config_request->Header.PageNumber);
135 desc = ioc->tmp_string;
136 break;
137 }
138 case MPI2_FUNCTION_PORT_FACTS:
139 desc = "port_facts";
140 break;
141 case MPI2_FUNCTION_PORT_ENABLE:
142 desc = "port_enable";
143 break;
144 case MPI2_FUNCTION_EVENT_NOTIFICATION:
145 desc = "event_notification";
146 break;
147 case MPI2_FUNCTION_FW_DOWNLOAD:
148 desc = "fw_download";
149 break;
150 case MPI2_FUNCTION_FW_UPLOAD:
151 desc = "fw_upload";
152 break;
153 case MPI2_FUNCTION_RAID_ACTION:
154 desc = "raid_action";
155 break;
156 case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
157 {
158 Mpi2SCSIIORequest_t *scsi_request =
159 (Mpi2SCSIIORequest_t *)mpi_request;
160
161 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
162 "raid_pass, cmd(0x%02x), cdb_len(%d)",
163 scsi_request->CDB.CDB32[0],
164 le16_to_cpu(scsi_request->IoFlags) & 0xF);
165 desc = ioc->tmp_string;
166 break;
167 }
168 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
169 desc = "sas_iounit_cntl";
170 break;
171 case MPI2_FUNCTION_SATA_PASSTHROUGH:
172 desc = "sata_pass";
173 break;
174 case MPI2_FUNCTION_DIAG_BUFFER_POST:
175 desc = "diag_buffer_post";
176 break;
177 case MPI2_FUNCTION_DIAG_RELEASE:
178 desc = "diag_release";
179 break;
180 case MPI2_FUNCTION_SMP_PASSTHROUGH:
181 desc = "smp_passthrough";
182 break;
183 }
184
185 if (!desc)
186 return;
187
188 printk(MPT2SAS_DEBUG_FMT "%s: %s, smid(%d)\n",
189 ioc->name, calling_function_name, desc, smid);
190
191 if (!mpi_reply)
192 return;
193
194 if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
195 printk(MPT2SAS_DEBUG_FMT
196 "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
197 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
198 le32_to_cpu(mpi_reply->IOCLogInfo));
199
200 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
201 mpi_request->Function ==
202 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
203 Mpi2SCSIIOReply_t *scsi_reply =
204 (Mpi2SCSIIOReply_t *)mpi_reply;
205 if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
206 printk(MPT2SAS_DEBUG_FMT
207 "\tscsi_state(0x%02x), scsi_status"
208 "(0x%02x)\n", ioc->name,
209 scsi_reply->SCSIState,
210 scsi_reply->SCSIStatus);
211 }
212}
213#endif
214
215/**
216 * mpt2sas_ctl_done - ctl module completion routine
217 * @ioc: per adapter object
218 * @smid: system request message index
219 * @VF_ID: virtual function id
220 * @reply: reply message frame(lower 32bit addr)
221 * Context: none.
222 *
223 * The callback handler when using ioc->ctl_cb_idx.
224 *
225 * Return nothing.
226 */
227void
228mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
229{
230 MPI2DefaultReply_t *mpi_reply;
231
232 if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED)
233 return;
234 if (ioc->ctl_cmds.smid != smid)
235 return;
236 ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE;
237 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
238 if (mpi_reply) {
239 memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
240 ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID;
241 }
242#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
243 _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
244#endif
245 ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING;
246 complete(&ioc->ctl_cmds.done);
247}
248
249/**
250 * _ctl_check_event_type - determines when an event needs logging
251 * @ioc: per adapter object
252 * @event: firmware event
253 *
254 * The bitmask in ioc->event_type[] indicates which events should be
255 * be saved in the driver event_log. This bitmask is set by application.
256 *
257 * Returns 1 when event should be captured, or zero means no match.
258 */
259static int
260_ctl_check_event_type(struct MPT2SAS_ADAPTER *ioc, u16 event)
261{
262 u16 i;
263 u32 desired_event;
264
265 if (event >= 128 || !event || !ioc->event_log)
266 return 0;
267
268 desired_event = (1 << (event % 32));
269 if (!desired_event)
270 desired_event = 1;
271 i = event / 32;
272 return desired_event & ioc->event_type[i];
273}
274
275/**
276 * mpt2sas_ctl_add_to_event_log - add event
277 * @ioc: per adapter object
278 * @mpi_reply: reply message frame
279 *
280 * Return nothing.
281 */
282void
283mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
284 Mpi2EventNotificationReply_t *mpi_reply)
285{
286 struct MPT2_IOCTL_EVENTS *event_log;
287 u16 event;
288 int i;
289 u32 sz, event_data_sz;
290 u8 send_aen = 0;
291
292 if (!ioc->event_log)
293 return;
294
295 event = le16_to_cpu(mpi_reply->Event);
296
297 if (_ctl_check_event_type(ioc, event)) {
298
299 /* insert entry into circular event_log */
300 i = ioc->event_context % MPT2SAS_CTL_EVENT_LOG_SIZE;
301 event_log = ioc->event_log;
302 event_log[i].event = event;
303 event_log[i].context = ioc->event_context++;
304
305 event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4;
306 sz = min_t(u32, event_data_sz, MPT2_EVENT_DATA_SIZE);
307 memset(event_log[i].data, 0, MPT2_EVENT_DATA_SIZE);
308 memcpy(event_log[i].data, mpi_reply->EventData, sz);
309 send_aen = 1;
310 }
311
312 /* This aen_event_read_flag flag is set until the
313 * application has read the event log.
314 * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify.
315 */
316 if (event == MPI2_EVENT_LOG_ENTRY_ADDED ||
317 (send_aen && !ioc->aen_event_read_flag)) {
318 ioc->aen_event_read_flag = 1;
319 wake_up_interruptible(&ctl_poll_wait);
320 if (async_queue)
321 kill_fasync(&async_queue, SIGIO, POLL_IN);
322 }
323}
324
325/**
326 * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time)
327 * @ioc: per adapter object
328 * @VF_ID: virtual function id
329 * @reply: reply message frame(lower 32bit addr)
330 * Context: interrupt.
331 *
332 * This function merely adds a new work task into ioc->firmware_event_thread.
333 * The tasks are worked from _firmware_event_work in user context.
334 *
335 * Return nothing.
336 */
337void
338mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
339{
340 Mpi2EventNotificationReply_t *mpi_reply;
341
342 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
343 mpt2sas_ctl_add_to_event_log(ioc, mpi_reply);
344}
345
346/**
347 * _ctl_verify_adapter - validates ioc_number passed from application
348 * @ioc: per adapter object
349 * @iocpp: The ioc pointer is returned in this.
350 *
351 * Return (-1) means error, else ioc_number.
352 */
353static int
354_ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp)
355{
356 struct MPT2SAS_ADAPTER *ioc;
357
358 list_for_each_entry(ioc, &ioc_list, list) {
359 if (ioc->id != ioc_number)
360 continue;
361 *iocpp = ioc;
362 return ioc_number;
363 }
364 *iocpp = NULL;
365 return -1;
366}
367
368/**
369 * mpt2sas_ctl_reset_handler - reset callback handler (for ctl)
370 * @ioc: per adapter object
371 * @reset_phase: phase
372 *
373 * The handler for doing any required cleanup or initialization.
374 *
375 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
376 * MPT2_IOC_DONE_RESET
377 */
378void
379mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
380{
381 switch (reset_phase) {
382 case MPT2_IOC_PRE_RESET:
383 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
384 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
385 break;
386 case MPT2_IOC_AFTER_RESET:
387 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
388 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
389 if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) {
390 ioc->ctl_cmds.status |= MPT2_CMD_RESET;
391 mpt2sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
392 complete(&ioc->ctl_cmds.done);
393 }
394 break;
395 case MPT2_IOC_DONE_RESET:
396 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
397 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
398 break;
399 }
400}
401
402/**
403 * _ctl_fasync -
404 * @fd -
405 * @filep -
406 * @mode -
407 *
408 * Called when application request fasyn callback handler.
409 */
410static int
411_ctl_fasync(int fd, struct file *filep, int mode)
412{
413 return fasync_helper(fd, filep, mode, &async_queue);
414}
415
416/**
417 * _ctl_release -
418 * @inode -
419 * @filep -
420 *
421 * Called when application releases the fasyn callback handler.
422 */
423static int
424_ctl_release(struct inode *inode, struct file *filep)
425{
426 return fasync_helper(-1, filep, 0, &async_queue);
427}
428
429/**
430 * _ctl_poll -
431 * @file -
432 * @wait -
433 *
434 */
435static unsigned int
436_ctl_poll(struct file *filep, poll_table *wait)
437{
438 struct MPT2SAS_ADAPTER *ioc;
439
440 poll_wait(filep, &ctl_poll_wait, wait);
441
442 list_for_each_entry(ioc, &ioc_list, list) {
443 if (ioc->aen_event_read_flag)
444 return POLLIN | POLLRDNORM;
445 }
446 return 0;
447}
448
449/**
450 * _ctl_do_task_abort - assign an active smid to the abort_task
451 * @ioc: per adapter object
452 * @karg - (struct mpt2_ioctl_command)
453 * @tm_request - pointer to mf from user space
454 *
455 * Returns 0 when an smid if found, else fail.
456 * during failure, the reply frame is filled.
457 */
458static int
459_ctl_do_task_abort(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
460 Mpi2SCSITaskManagementRequest_t *tm_request)
461{
462 u8 found = 0;
463 u16 i;
464 u16 handle;
465 struct scsi_cmnd *scmd;
466 struct MPT2SAS_DEVICE *priv_data;
467 unsigned long flags;
468 Mpi2SCSITaskManagementReply_t *tm_reply;
469 u32 sz;
470 u32 lun;
471
472 lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN);
473
474 handle = le16_to_cpu(tm_request->DevHandle);
475 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
476 for (i = ioc->request_depth; i && !found; i--) {
477 scmd = ioc->scsi_lookup[i - 1].scmd;
478 if (scmd == NULL || scmd->device == NULL ||
479 scmd->device->hostdata == NULL)
480 continue;
481 if (lun != scmd->device->lun)
482 continue;
483 priv_data = scmd->device->hostdata;
484 if (priv_data->sas_target == NULL)
485 continue;
486 if (priv_data->sas_target->handle != handle)
487 continue;
488 tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid);
489 found = 1;
490 }
491 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
492
493 if (!found) {
494 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ABORT_TASK: "
495 "DevHandle(0x%04x), lun(%d), no active mid!!\n", ioc->name,
496 tm_request->DevHandle, lun));
497 tm_reply = ioc->ctl_cmds.reply;
498 tm_reply->DevHandle = tm_request->DevHandle;
499 tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
500 tm_reply->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
501 tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4;
502 tm_reply->VP_ID = tm_request->VP_ID;
503 tm_reply->VF_ID = tm_request->VF_ID;
504 sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz);
505 if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply,
506 sz))
507 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
508 __LINE__, __func__);
509 return 1;
510 }
511
512 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ABORT_TASK: "
513 "DevHandle(0x%04x), lun(%d), smid(%d)\n", ioc->name,
514 tm_request->DevHandle, lun, tm_request->TaskMID));
515 return 0;
516}
517
518/**
519 * _ctl_do_mpt_command - main handler for MPT2COMMAND opcode
520 * @ioc: per adapter object
521 * @karg - (struct mpt2_ioctl_command)
522 * @mf - pointer to mf in user space
523 * @state - NON_BLOCKING or BLOCKING
524 */
525static long
526_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
527 struct mpt2_ioctl_command karg, void __user *mf, enum block_state state)
528{
529 MPI2RequestHeader_t *mpi_request;
530 MPI2DefaultReply_t *mpi_reply;
531 u32 ioc_state;
532 u16 ioc_status;
533 u16 smid;
534 unsigned long timeout, timeleft;
535 u8 issue_reset;
536 u32 sz;
537 void *psge;
538 void *priv_sense = NULL;
539 void *data_out = NULL;
540 dma_addr_t data_out_dma;
541 size_t data_out_sz = 0;
542 void *data_in = NULL;
543 dma_addr_t data_in_dma;
544 size_t data_in_sz = 0;
545 u32 sgl_flags;
546 long ret;
547 u16 wait_state_count;
548
549 issue_reset = 0;
550
551 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
552 return -EAGAIN;
553 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
554 return -ERESTARTSYS;
555
556 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
557 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
558 ioc->name, __func__);
559 ret = -EAGAIN;
560 goto out;
561 }
562
563 wait_state_count = 0;
564 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
565 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
566 if (wait_state_count++ == 10) {
567 printk(MPT2SAS_ERR_FMT
568 "%s: failed due to ioc not operational\n",
569 ioc->name, __func__);
570 ret = -EFAULT;
571 goto out;
572 }
573 ssleep(1);
574 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
575 printk(MPT2SAS_INFO_FMT "%s: waiting for "
576 "operational state(count=%d)\n", ioc->name,
577 __func__, wait_state_count);
578 }
579 if (wait_state_count)
580 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
581 ioc->name, __func__);
582
583 smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
584 if (!smid) {
585 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
586 ioc->name, __func__);
587 ret = -EAGAIN;
588 goto out;
589 }
590
591 ret = 0;
592 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
593 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
594 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
595 ioc->ctl_cmds.smid = smid;
596 data_out_sz = karg.data_out_size;
597 data_in_sz = karg.data_in_size;
598
599 /* copy in request message frame from user */
600 if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
601 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
602 __func__);
603 ret = -EFAULT;
604 mpt2sas_base_free_smid(ioc, smid);
605 goto out;
606 }
607
608 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
609 mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
610 if (!mpi_request->FunctionDependent1 ||
611 mpi_request->FunctionDependent1 >
612 cpu_to_le16(ioc->facts.MaxDevHandle)) {
613 ret = -EINVAL;
614 mpt2sas_base_free_smid(ioc, smid);
615 goto out;
616 }
617 }
618
619 /* obtain dma-able memory for data transfer */
620 if (data_out_sz) /* WRITE */ {
621 data_out = pci_alloc_consistent(ioc->pdev, data_out_sz,
622 &data_out_dma);
623 if (!data_out) {
624 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
625 __LINE__, __func__);
626 ret = -ENOMEM;
627 mpt2sas_base_free_smid(ioc, smid);
628 goto out;
629 }
630 if (copy_from_user(data_out, karg.data_out_buf_ptr,
631 data_out_sz)) {
632 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
633 __LINE__, __func__);
634 ret = -EFAULT;
635 mpt2sas_base_free_smid(ioc, smid);
636 goto out;
637 }
638 }
639
640 if (data_in_sz) /* READ */ {
641 data_in = pci_alloc_consistent(ioc->pdev, data_in_sz,
642 &data_in_dma);
643 if (!data_in) {
644 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
645 __LINE__, __func__);
646 ret = -ENOMEM;
647 mpt2sas_base_free_smid(ioc, smid);
648 goto out;
649 }
650 }
651
652 /* add scatter gather elements */
653 psge = (void *)mpi_request + (karg.data_sge_offset*4);
654
655 if (!data_out_sz && !data_in_sz) {
656 mpt2sas_base_build_zero_len_sge(ioc, psge);
657 } else if (data_out_sz && data_in_sz) {
658 /* WRITE sgel first */
659 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
660 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
661 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
662 ioc->base_add_sg_single(psge, sgl_flags |
663 data_out_sz, data_out_dma);
664
665 /* incr sgel */
666 psge += ioc->sge_size;
667
668 /* READ sgel last */
669 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
670 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
671 MPI2_SGE_FLAGS_END_OF_LIST);
672 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
673 ioc->base_add_sg_single(psge, sgl_flags |
674 data_in_sz, data_in_dma);
675 } else if (data_out_sz) /* WRITE */ {
676 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
677 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
678 MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC);
679 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
680 ioc->base_add_sg_single(psge, sgl_flags |
681 data_out_sz, data_out_dma);
682 } else if (data_in_sz) /* READ */ {
683 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
684 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
685 MPI2_SGE_FLAGS_END_OF_LIST);
686 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
687 ioc->base_add_sg_single(psge, sgl_flags |
688 data_in_sz, data_in_dma);
689 }
690
691 /* send command to firmware */
692#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
693 _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
694#endif
695
696 switch (mpi_request->Function) {
697 case MPI2_FUNCTION_SCSI_IO_REQUEST:
698 case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
699 {
700 Mpi2SCSIIORequest_t *scsiio_request =
701 (Mpi2SCSIIORequest_t *)mpi_request;
702 scsiio_request->SenseBufferLowAddress =
703 (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid);
704 priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid);
705 memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE);
706 mpt2sas_base_put_smid_scsi_io(ioc, smid, 0,
707 le16_to_cpu(mpi_request->FunctionDependent1));
708 break;
709 }
710 case MPI2_FUNCTION_SCSI_TASK_MGMT:
711 {
712 Mpi2SCSITaskManagementRequest_t *tm_request =
713 (Mpi2SCSITaskManagementRequest_t *)mpi_request;
714
715 if (tm_request->TaskType ==
716 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
717 if (_ctl_do_task_abort(ioc, &karg, tm_request))
718 goto out;
719 }
720
721 mutex_lock(&ioc->tm_cmds.mutex);
722 mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu(
723 tm_request->DevHandle));
724 mpt2sas_base_put_smid_hi_priority(ioc, smid,
725 mpi_request->VF_ID);
726 break;
727 }
728 case MPI2_FUNCTION_SMP_PASSTHROUGH:
729 {
730 Mpi2SmpPassthroughRequest_t *smp_request =
731 (Mpi2SmpPassthroughRequest_t *)mpi_request;
732 u8 *data;
733
734 /* ioc determines which port to use */
735 smp_request->PhysicalPort = 0xFF;
736 if (smp_request->PassthroughFlags &
737 MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
738 data = (u8 *)&smp_request->SGL;
739 else
740 data = data_out;
741
742 if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
743 ioc->ioc_link_reset_in_progress = 1;
744 ioc->ignore_loginfos = 1;
745 }
746 mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
747 break;
748 }
749 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
750 {
751 Mpi2SasIoUnitControlRequest_t *sasiounit_request =
752 (Mpi2SasIoUnitControlRequest_t *)mpi_request;
753
754 if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET
755 || sasiounit_request->Operation ==
756 MPI2_SAS_OP_PHY_LINK_RESET) {
757 ioc->ioc_link_reset_in_progress = 1;
758 ioc->ignore_loginfos = 1;
759 }
760 mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
761 break;
762 }
763 default:
764 mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
765 break;
766 }
767
768 if (karg.timeout < MPT2_IOCTL_DEFAULT_TIMEOUT)
769 timeout = MPT2_IOCTL_DEFAULT_TIMEOUT;
770 else
771 timeout = karg.timeout;
772 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
773 timeout*HZ);
774 if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
775 Mpi2SCSITaskManagementRequest_t *tm_request =
776 (Mpi2SCSITaskManagementRequest_t *)mpi_request;
777 mutex_unlock(&ioc->tm_cmds.mutex);
778 mpt2sas_scsih_clear_tm_flag(ioc, le16_to_cpu(
779 tm_request->DevHandle));
780 } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH ||
781 mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) &&
782 ioc->ioc_link_reset_in_progress) {
783 ioc->ioc_link_reset_in_progress = 0;
784 ioc->ignore_loginfos = 0;
785 }
786 if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
787 printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
788 __func__);
789 _debug_dump_mf(mpi_request, karg.data_sge_offset);
790 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
791 issue_reset = 1;
792 goto issue_host_reset;
793 }
794
795 mpi_reply = ioc->ctl_cmds.reply;
796 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
797
798#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
799 if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
800 (ioc->logging_level & MPT_DEBUG_TM)) {
801 Mpi2SCSITaskManagementReply_t *tm_reply =
802 (Mpi2SCSITaskManagementReply_t *)mpi_reply;
803
804 printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: "
805 "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
806 "TerminationCount(0x%08x)\n", ioc->name,
807 tm_reply->IOCStatus, tm_reply->IOCLogInfo,
808 tm_reply->TerminationCount);
809 }
810#endif
811 /* copy out xdata to user */
812 if (data_in_sz) {
813 if (copy_to_user(karg.data_in_buf_ptr, data_in,
814 data_in_sz)) {
815 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
816 __LINE__, __func__);
817 ret = -ENODATA;
818 goto out;
819 }
820 }
821
822 /* copy out reply message frame to user */
823 if (karg.max_reply_bytes) {
824 sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz);
825 if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply,
826 sz)) {
827 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
828 __LINE__, __func__);
829 ret = -ENODATA;
830 goto out;
831 }
832 }
833
834 /* copy out sense to user */
835 if (karg.max_sense_bytes && (mpi_request->Function ==
836 MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
837 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
838 sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
839 if (copy_to_user(karg.sense_data_ptr, priv_sense, sz)) {
840 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
841 __LINE__, __func__);
842 ret = -ENODATA;
843 goto out;
844 }
845 }
846
847 issue_host_reset:
848 if (issue_reset) {
849 if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
850 mpi_request->Function ==
851 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
852 printk(MPT2SAS_INFO_FMT "issue target reset: handle "
853 "= (0x%04x)\n", ioc->name,
854 mpi_request->FunctionDependent1);
855 mutex_lock(&ioc->tm_cmds.mutex);
856 mpt2sas_scsih_issue_tm(ioc,
857 mpi_request->FunctionDependent1, 0,
858 MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10);
859 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
860 mutex_unlock(&ioc->tm_cmds.mutex);
861 } else
862 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
863 FORCE_BIG_HAMMER);
864 }
865
866 out:
867
868 /* free memory associated with sg buffers */
869 if (data_in)
870 pci_free_consistent(ioc->pdev, data_in_sz, data_in,
871 data_in_dma);
872
873 if (data_out)
874 pci_free_consistent(ioc->pdev, data_out_sz, data_out,
875 data_out_dma);
876
877 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
878 mutex_unlock(&ioc->ctl_cmds.mutex);
879 return ret;
880}
881
882/**
883 * _ctl_getiocinfo - main handler for MPT2IOCINFO opcode
884 * @arg - user space buffer containing ioctl content
885 */
886static long
887_ctl_getiocinfo(void __user *arg)
888{
889 struct mpt2_ioctl_iocinfo karg;
890 struct MPT2SAS_ADAPTER *ioc;
891 u8 revision;
892
893 if (copy_from_user(&karg, arg, sizeof(karg))) {
894 printk(KERN_ERR "failure at %s:%d/%s()!\n",
895 __FILE__, __LINE__, __func__);
896 return -EFAULT;
897 }
898 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
899 return -ENODEV;
900
901 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
902 __func__));
903
904 memset(&karg, 0 , sizeof(karg));
905 karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
906 if (ioc->pfacts)
907 karg.port_number = ioc->pfacts[0].PortNumber;
908 pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
909 karg.hw_rev = revision;
910 karg.pci_id = ioc->pdev->device;
911 karg.subsystem_device = ioc->pdev->subsystem_device;
912 karg.subsystem_vendor = ioc->pdev->subsystem_vendor;
913 karg.pci_information.u.bits.bus = ioc->pdev->bus->number;
914 karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn);
915 karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
916 karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
917 karg.firmware_version = ioc->facts.FWVersion.Word;
918 strncpy(karg.driver_version, MPT2SAS_DRIVER_VERSION,
919 MPT2_IOCTL_VERSION_LENGTH);
920 karg.driver_version[MPT2_IOCTL_VERSION_LENGTH - 1] = '\0';
921 karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
922
923 if (copy_to_user(arg, &karg, sizeof(karg))) {
924 printk(KERN_ERR "failure at %s:%d/%s()!\n",
925 __FILE__, __LINE__, __func__);
926 return -EFAULT;
927 }
928 return 0;
929}
930
931/**
932 * _ctl_eventquery - main handler for MPT2EVENTQUERY opcode
933 * @arg - user space buffer containing ioctl content
934 */
935static long
936_ctl_eventquery(void __user *arg)
937{
938 struct mpt2_ioctl_eventquery karg;
939 struct MPT2SAS_ADAPTER *ioc;
940
941 if (copy_from_user(&karg, arg, sizeof(karg))) {
942 printk(KERN_ERR "failure at %s:%d/%s()!\n",
943 __FILE__, __LINE__, __func__);
944 return -EFAULT;
945 }
946 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
947 return -ENODEV;
948
949 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
950 __func__));
951
952 karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE;
953 memcpy(karg.event_types, ioc->event_type,
954 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
955
956 if (copy_to_user(arg, &karg, sizeof(karg))) {
957 printk(KERN_ERR "failure at %s:%d/%s()!\n",
958 __FILE__, __LINE__, __func__);
959 return -EFAULT;
960 }
961 return 0;
962}
963
964/**
965 * _ctl_eventenable - main handler for MPT2EVENTENABLE opcode
966 * @arg - user space buffer containing ioctl content
967 */
968static long
969_ctl_eventenable(void __user *arg)
970{
971 struct mpt2_ioctl_eventenable karg;
972 struct MPT2SAS_ADAPTER *ioc;
973
974 if (copy_from_user(&karg, arg, sizeof(karg))) {
975 printk(KERN_ERR "failure at %s:%d/%s()!\n",
976 __FILE__, __LINE__, __func__);
977 return -EFAULT;
978 }
979 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
980 return -ENODEV;
981
982 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
983 __func__));
984
985 if (ioc->event_log)
986 return 0;
987 memcpy(ioc->event_type, karg.event_types,
988 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
989 mpt2sas_base_validate_event_type(ioc, ioc->event_type);
990
991 /* initialize event_log */
992 ioc->event_context = 0;
993 ioc->aen_event_read_flag = 0;
994 ioc->event_log = kcalloc(MPT2SAS_CTL_EVENT_LOG_SIZE,
995 sizeof(struct MPT2_IOCTL_EVENTS), GFP_KERNEL);
996 if (!ioc->event_log) {
997 printk(KERN_ERR "failure at %s:%d/%s()!\n",
998 __FILE__, __LINE__, __func__);
999 return -ENOMEM;
1000 }
1001 return 0;
1002}
1003
1004/**
1005 * _ctl_eventreport - main handler for MPT2EVENTREPORT opcode
1006 * @arg - user space buffer containing ioctl content
1007 */
1008static long
1009_ctl_eventreport(void __user *arg)
1010{
1011 struct mpt2_ioctl_eventreport karg;
1012 struct MPT2SAS_ADAPTER *ioc;
1013 u32 number_bytes, max_events, max;
1014 struct mpt2_ioctl_eventreport __user *uarg = arg;
1015
1016 if (copy_from_user(&karg, arg, sizeof(karg))) {
1017 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1018 __FILE__, __LINE__, __func__);
1019 return -EFAULT;
1020 }
1021 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1022 return -ENODEV;
1023
1024 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
1025 __func__));
1026
1027 number_bytes = karg.hdr.max_data_size -
1028 sizeof(struct mpt2_ioctl_header);
1029 max_events = number_bytes/sizeof(struct MPT2_IOCTL_EVENTS);
1030 max = min_t(u32, MPT2SAS_CTL_EVENT_LOG_SIZE, max_events);
1031
1032 /* If fewer than 1 event is requested, there must have
1033 * been some type of error.
1034 */
1035 if (!max || !ioc->event_log)
1036 return -ENODATA;
1037
1038 number_bytes = max * sizeof(struct MPT2_IOCTL_EVENTS);
1039 if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) {
1040 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1041 __FILE__, __LINE__, __func__);
1042 return -EFAULT;
1043 }
1044
1045 /* reset flag so SIGIO can restart */
1046 ioc->aen_event_read_flag = 0;
1047 return 0;
1048}
1049
1050/**
1051 * _ctl_do_reset - main handler for MPT2HARDRESET opcode
1052 * @arg - user space buffer containing ioctl content
1053 */
1054static long
1055_ctl_do_reset(void __user *arg)
1056{
1057 struct mpt2_ioctl_diag_reset karg;
1058 struct MPT2SAS_ADAPTER *ioc;
1059 int retval;
1060
1061 if (copy_from_user(&karg, arg, sizeof(karg))) {
1062 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1063 __FILE__, __LINE__, __func__);
1064 return -EFAULT;
1065 }
1066 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1067 return -ENODEV;
1068
1069 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
1070 __func__));
1071
1072 retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1073 FORCE_BIG_HAMMER);
1074 printk(MPT2SAS_INFO_FMT "host reset: %s\n",
1075 ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
1076 return 0;
1077}
1078
1079/**
1080 * _ctl_btdh_search_sas_device - searching for sas device
1081 * @ioc: per adapter object
1082 * @btdh: btdh ioctl payload
1083 */
1084static int
1085_ctl_btdh_search_sas_device(struct MPT2SAS_ADAPTER *ioc,
1086 struct mpt2_ioctl_btdh_mapping *btdh)
1087{
1088 struct _sas_device *sas_device;
1089 unsigned long flags;
1090 int rc = 0;
1091
1092 if (list_empty(&ioc->sas_device_list))
1093 return rc;
1094
1095 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1096 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
1097 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1098 btdh->handle == sas_device->handle) {
1099 btdh->bus = sas_device->channel;
1100 btdh->id = sas_device->id;
1101 rc = 1;
1102 goto out;
1103 } else if (btdh->bus == sas_device->channel && btdh->id ==
1104 sas_device->id && btdh->handle == 0xFFFF) {
1105 btdh->handle = sas_device->handle;
1106 rc = 1;
1107 goto out;
1108 }
1109 }
1110 out:
1111 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1112 return rc;
1113}
1114
1115/**
1116 * _ctl_btdh_search_raid_device - searching for raid device
1117 * @ioc: per adapter object
1118 * @btdh: btdh ioctl payload
1119 */
1120static int
1121_ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc,
1122 struct mpt2_ioctl_btdh_mapping *btdh)
1123{
1124 struct _raid_device *raid_device;
1125 unsigned long flags;
1126 int rc = 0;
1127
1128 if (list_empty(&ioc->raid_device_list))
1129 return rc;
1130
1131 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1132 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
1133 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1134 btdh->handle == raid_device->handle) {
1135 btdh->bus = raid_device->channel;
1136 btdh->id = raid_device->id;
1137 rc = 1;
1138 goto out;
1139 } else if (btdh->bus == raid_device->channel && btdh->id ==
1140 raid_device->id && btdh->handle == 0xFFFF) {
1141 btdh->handle = raid_device->handle;
1142 rc = 1;
1143 goto out;
1144 }
1145 }
1146 out:
1147 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1148 return rc;
1149}
1150
1151/**
1152 * _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode
1153 * @arg - user space buffer containing ioctl content
1154 */
1155static long
1156_ctl_btdh_mapping(void __user *arg)
1157{
1158 struct mpt2_ioctl_btdh_mapping karg;
1159 struct MPT2SAS_ADAPTER *ioc;
1160 int rc;
1161
1162 if (copy_from_user(&karg, arg, sizeof(karg))) {
1163 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1164 __FILE__, __LINE__, __func__);
1165 return -EFAULT;
1166 }
1167 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1168 return -ENODEV;
1169
1170 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1171 __func__));
1172
1173 rc = _ctl_btdh_search_sas_device(ioc, &karg);
1174 if (!rc)
1175 _ctl_btdh_search_raid_device(ioc, &karg);
1176
1177 if (copy_to_user(arg, &karg, sizeof(karg))) {
1178 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1179 __FILE__, __LINE__, __func__);
1180 return -EFAULT;
1181 }
1182 return 0;
1183}
1184
1185/**
1186 * _ctl_diag_capability - return diag buffer capability
1187 * @ioc: per adapter object
1188 * @buffer_type: specifies either TRACE or SNAPSHOT
1189 *
1190 * returns 1 when diag buffer support is enabled in firmware
1191 */
1192static u8
1193_ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type)
1194{
1195 u8 rc = 0;
1196
1197 switch (buffer_type) {
1198 case MPI2_DIAG_BUF_TYPE_TRACE:
1199 if (ioc->facts.IOCCapabilities &
1200 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
1201 rc = 1;
1202 break;
1203 case MPI2_DIAG_BUF_TYPE_SNAPSHOT:
1204 if (ioc->facts.IOCCapabilities &
1205 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
1206 rc = 1;
1207 break;
1208 }
1209
1210 return rc;
1211}
1212
1213/**
1214 * _ctl_diag_register - application register with driver
1215 * @arg - user space buffer containing ioctl content
1216 * @state - NON_BLOCKING or BLOCKING
1217 *
1218 * This will allow the driver to setup any required buffers that will be
1219 * needed by firmware to communicate with the driver.
1220 */
1221static long
1222_ctl_diag_register(void __user *arg, enum block_state state)
1223{
1224 struct mpt2_diag_register karg;
1225 struct MPT2SAS_ADAPTER *ioc;
1226 int rc, i;
1227 void *request_data = NULL;
1228 dma_addr_t request_data_dma;
1229 u32 request_data_sz = 0;
1230 Mpi2DiagBufferPostRequest_t *mpi_request;
1231 Mpi2DiagBufferPostReply_t *mpi_reply;
1232 u8 buffer_type;
1233 unsigned long timeleft;
1234 u16 smid;
1235 u16 ioc_status;
1236 u8 issue_reset = 0;
1237
1238 if (copy_from_user(&karg, arg, sizeof(karg))) {
1239 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1240 __FILE__, __LINE__, __func__);
1241 return -EFAULT;
1242 }
1243 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1244 return -ENODEV;
1245
1246 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1247 __func__));
1248
1249 buffer_type = karg.buffer_type;
1250 if (!_ctl_diag_capability(ioc, buffer_type)) {
1251 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1252 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1253 return -EPERM;
1254 }
1255
1256 if (ioc->diag_buffer_status[buffer_type] &
1257 MPT2_DIAG_BUFFER_IS_REGISTERED) {
1258 printk(MPT2SAS_ERR_FMT "%s: already has a registered "
1259 "buffer for buffer_type(0x%02x)\n", ioc->name, __func__,
1260 buffer_type);
1261 return -EINVAL;
1262 }
1263
1264 if (karg.requested_buffer_size % 4) {
1265 printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size "
1266 "is not 4 byte aligned\n", ioc->name, __func__);
1267 return -EINVAL;
1268 }
1269
1270 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
1271 return -EAGAIN;
1272 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
1273 return -ERESTARTSYS;
1274
1275 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
1276 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
1277 ioc->name, __func__);
1278 rc = -EAGAIN;
1279 goto out;
1280 }
1281
1282 smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1283 if (!smid) {
1284 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1285 ioc->name, __func__);
1286 rc = -EAGAIN;
1287 goto out;
1288 }
1289
1290 rc = 0;
1291 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
1292 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1293 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1294 ioc->ctl_cmds.smid = smid;
1295
1296 request_data = ioc->diag_buffer[buffer_type];
1297 request_data_sz = karg.requested_buffer_size;
1298 ioc->unique_id[buffer_type] = karg.unique_id;
1299 ioc->diag_buffer_status[buffer_type] = 0;
1300 memcpy(ioc->product_specific[buffer_type], karg.product_specific,
1301 MPT2_PRODUCT_SPECIFIC_DWORDS);
1302 ioc->diagnostic_flags[buffer_type] = karg.diagnostic_flags;
1303
1304 if (request_data) {
1305 request_data_dma = ioc->diag_buffer_dma[buffer_type];
1306 if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) {
1307 pci_free_consistent(ioc->pdev,
1308 ioc->diag_buffer_sz[buffer_type],
1309 request_data, request_data_dma);
1310 request_data = NULL;
1311 }
1312 }
1313
1314 if (request_data == NULL) {
1315 ioc->diag_buffer_sz[buffer_type] = 0;
1316 ioc->diag_buffer_dma[buffer_type] = 0;
1317 request_data = pci_alloc_consistent(
1318 ioc->pdev, request_data_sz, &request_data_dma);
1319 if (request_data == NULL) {
1320 printk(MPT2SAS_ERR_FMT "%s: failed allocating memory"
1321 " for diag buffers, requested size(%d)\n",
1322 ioc->name, __func__, request_data_sz);
1323 mpt2sas_base_free_smid(ioc, smid);
1324 return -ENOMEM;
1325 }
1326 ioc->diag_buffer[buffer_type] = request_data;
1327 ioc->diag_buffer_sz[buffer_type] = request_data_sz;
1328 ioc->diag_buffer_dma[buffer_type] = request_data_dma;
1329 }
1330
1331 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
1332 mpi_request->BufferType = karg.buffer_type;
1333 mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags);
1334 mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
1335 mpi_request->BufferLength = cpu_to_le32(request_data_sz);
1336
1337 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), "
1338 "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data,
1339 (unsigned long long)request_data_dma, mpi_request->BufferLength));
1340
1341 for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
1342 mpi_request->ProductSpecific[i] =
1343 cpu_to_le32(ioc->product_specific[buffer_type][i]);
1344
1345 mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
1346 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
1347 MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
1348
1349 if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
1350 printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
1351 __func__);
1352 _debug_dump_mf(mpi_request,
1353 sizeof(Mpi2DiagBufferPostRequest_t)/4);
1354 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
1355 issue_reset = 1;
1356 goto issue_host_reset;
1357 }
1358
1359 /* process the completed Reply Message Frame */
1360 if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
1361 printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
1362 ioc->name, __func__);
1363 rc = -EFAULT;
1364 goto out;
1365 }
1366
1367 mpi_reply = ioc->ctl_cmds.reply;
1368 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1369
1370 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1371 ioc->diag_buffer_status[buffer_type] |=
1372 MPT2_DIAG_BUFFER_IS_REGISTERED;
1373 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
1374 ioc->name, __func__));
1375 } else {
1376 printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
1377 "log_info(0x%08x)\n", ioc->name, __func__,
1378 ioc_status, mpi_reply->IOCLogInfo);
1379 rc = -EFAULT;
1380 }
1381
1382 issue_host_reset:
1383 if (issue_reset)
1384 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1385 FORCE_BIG_HAMMER);
1386
1387 out:
1388
1389 if (rc && request_data)
1390 pci_free_consistent(ioc->pdev, request_data_sz,
1391 request_data, request_data_dma);
1392
1393 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
1394 mutex_unlock(&ioc->ctl_cmds.mutex);
1395 return rc;
1396}
1397
1398/**
1399 * _ctl_diag_unregister - application unregister with driver
1400 * @arg - user space buffer containing ioctl content
1401 *
1402 * This will allow the driver to cleanup any memory allocated for diag
1403 * messages and to free up any resources.
1404 */
1405static long
1406_ctl_diag_unregister(void __user *arg)
1407{
1408 struct mpt2_diag_unregister karg;
1409 struct MPT2SAS_ADAPTER *ioc;
1410 void *request_data;
1411 dma_addr_t request_data_dma;
1412 u32 request_data_sz;
1413 u8 buffer_type;
1414
1415 if (copy_from_user(&karg, arg, sizeof(karg))) {
1416 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1417 __FILE__, __LINE__, __func__);
1418 return -EFAULT;
1419 }
1420 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1421 return -ENODEV;
1422
1423 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1424 __func__));
1425
1426 buffer_type = karg.unique_id & 0x000000ff;
1427 if (!_ctl_diag_capability(ioc, buffer_type)) {
1428 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1429 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1430 return -EPERM;
1431 }
1432
1433 if ((ioc->diag_buffer_status[buffer_type] &
1434 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
1435 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
1436 "registered\n", ioc->name, __func__, buffer_type);
1437 return -EINVAL;
1438 }
1439 if ((ioc->diag_buffer_status[buffer_type] &
1440 MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
1441 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) has not been "
1442 "released\n", ioc->name, __func__, buffer_type);
1443 return -EINVAL;
1444 }
1445
1446 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1447 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1448 "registered\n", ioc->name, __func__, karg.unique_id);
1449 return -EINVAL;
1450 }
1451
1452 request_data = ioc->diag_buffer[buffer_type];
1453 if (!request_data) {
1454 printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
1455 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1456 return -ENOMEM;
1457 }
1458
1459 request_data_sz = ioc->diag_buffer_sz[buffer_type];
1460 request_data_dma = ioc->diag_buffer_dma[buffer_type];
1461 pci_free_consistent(ioc->pdev, request_data_sz,
1462 request_data, request_data_dma);
1463 ioc->diag_buffer[buffer_type] = NULL;
1464 ioc->diag_buffer_status[buffer_type] = 0;
1465 return 0;
1466}
1467
1468/**
1469 * _ctl_diag_query - query relevant info associated with diag buffers
1470 * @arg - user space buffer containing ioctl content
1471 *
1472 * The application will send only buffer_type and unique_id. Driver will
1473 * inspect unique_id first, if valid, fill in all the info. If unique_id is
1474 * 0x00, the driver will return info specified by Buffer Type.
1475 */
1476static long
1477_ctl_diag_query(void __user *arg)
1478{
1479 struct mpt2_diag_query karg;
1480 struct MPT2SAS_ADAPTER *ioc;
1481 void *request_data;
1482 int i;
1483 u8 buffer_type;
1484
1485 if (copy_from_user(&karg, arg, sizeof(karg))) {
1486 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1487 __FILE__, __LINE__, __func__);
1488 return -EFAULT;
1489 }
1490 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1491 return -ENODEV;
1492
1493 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1494 __func__));
1495
1496 karg.application_flags = 0;
1497 buffer_type = karg.buffer_type;
1498
1499 if (!_ctl_diag_capability(ioc, buffer_type)) {
1500 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1501 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1502 return -EPERM;
1503 }
1504
1505 if ((ioc->diag_buffer_status[buffer_type] &
1506 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
1507 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
1508 "registered\n", ioc->name, __func__, buffer_type);
1509 return -EINVAL;
1510 }
1511
1512 if (karg.unique_id & 0xffffff00) {
1513 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1514 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1515 "registered\n", ioc->name, __func__,
1516 karg.unique_id);
1517 return -EINVAL;
1518 }
1519 }
1520
1521 request_data = ioc->diag_buffer[buffer_type];
1522 if (!request_data) {
1523 printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
1524 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1525 return -ENOMEM;
1526 }
1527
1528 if (ioc->diag_buffer_status[buffer_type] & MPT2_DIAG_BUFFER_IS_RELEASED)
1529 karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
1530 MPT2_APP_FLAGS_BUFFER_VALID);
1531 else
1532 karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
1533 MPT2_APP_FLAGS_BUFFER_VALID |
1534 MPT2_APP_FLAGS_FW_BUFFER_ACCESS);
1535
1536 for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
1537 karg.product_specific[i] =
1538 ioc->product_specific[buffer_type][i];
1539
1540 karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
1541 karg.driver_added_buffer_size = 0;
1542 karg.unique_id = ioc->unique_id[buffer_type];
1543 karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
1544
1545 if (copy_to_user(arg, &karg, sizeof(struct mpt2_diag_query))) {
1546 printk(MPT2SAS_ERR_FMT "%s: unable to write mpt2_diag_query "
1547 "data @ %p\n", ioc->name, __func__, arg);
1548 return -EFAULT;
1549 }
1550 return 0;
1551}
1552
1553/**
1554 * _ctl_diag_release - request to send Diag Release Message to firmware
1555 * @arg - user space buffer containing ioctl content
1556 * @state - NON_BLOCKING or BLOCKING
1557 *
1558 * This allows ownership of the specified buffer to returned to the driver,
1559 * allowing an application to read the buffer without fear that firmware is
1560 * overwritting information in the buffer.
1561 */
1562static long
1563_ctl_diag_release(void __user *arg, enum block_state state)
1564{
1565 struct mpt2_diag_release karg;
1566 struct MPT2SAS_ADAPTER *ioc;
1567 void *request_data;
1568 int rc;
1569 Mpi2DiagReleaseRequest_t *mpi_request;
1570 Mpi2DiagReleaseReply_t *mpi_reply;
1571 u8 buffer_type;
1572 unsigned long timeleft;
1573 u16 smid;
1574 u16 ioc_status;
1575 u8 issue_reset = 0;
1576
1577 if (copy_from_user(&karg, arg, sizeof(karg))) {
1578 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1579 __FILE__, __LINE__, __func__);
1580 return -EFAULT;
1581 }
1582 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1583 return -ENODEV;
1584
1585 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1586 __func__));
1587
1588 buffer_type = karg.unique_id & 0x000000ff;
1589 if (!_ctl_diag_capability(ioc, buffer_type)) {
1590 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1591 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1592 return -EPERM;
1593 }
1594
1595 if ((ioc->diag_buffer_status[buffer_type] &
1596 MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
1597 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
1598 "registered\n", ioc->name, __func__, buffer_type);
1599 return -EINVAL;
1600 }
1601
1602 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1603 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1604 "registered\n", ioc->name, __func__, karg.unique_id);
1605 return -EINVAL;
1606 }
1607
1608 if (ioc->diag_buffer_status[buffer_type] &
1609 MPT2_DIAG_BUFFER_IS_RELEASED) {
1610 printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
1611 "is already released\n", ioc->name, __func__,
1612 buffer_type);
1613 return 0;
1614 }
1615
1616 request_data = ioc->diag_buffer[buffer_type];
1617
1618 if (!request_data) {
1619 printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
1620 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1621 return -ENOMEM;
1622 }
1623
1624 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
1625 return -EAGAIN;
1626 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
1627 return -ERESTARTSYS;
1628
1629 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
1630 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
1631 ioc->name, __func__);
1632 rc = -EAGAIN;
1633 goto out;
1634 }
1635
1636 smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1637 if (!smid) {
1638 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1639 ioc->name, __func__);
1640 rc = -EAGAIN;
1641 goto out;
1642 }
1643
1644 rc = 0;
1645 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
1646 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1647 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1648 ioc->ctl_cmds.smid = smid;
1649
1650 mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
1651 mpi_request->BufferType = buffer_type;
1652
1653 mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
1654 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
1655 MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
1656
1657 if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
1658 printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
1659 __func__);
1660 _debug_dump_mf(mpi_request,
1661 sizeof(Mpi2DiagReleaseRequest_t)/4);
1662 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
1663 issue_reset = 1;
1664 goto issue_host_reset;
1665 }
1666
1667 /* process the completed Reply Message Frame */
1668 if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
1669 printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
1670 ioc->name, __func__);
1671 rc = -EFAULT;
1672 goto out;
1673 }
1674
1675 mpi_reply = ioc->ctl_cmds.reply;
1676 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1677
1678 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1679 ioc->diag_buffer_status[buffer_type] |=
1680 MPT2_DIAG_BUFFER_IS_RELEASED;
1681 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
1682 ioc->name, __func__));
1683 } else {
1684 printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
1685 "log_info(0x%08x)\n", ioc->name, __func__,
1686 ioc_status, mpi_reply->IOCLogInfo);
1687 rc = -EFAULT;
1688 }
1689
1690 issue_host_reset:
1691 if (issue_reset)
1692 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1693 FORCE_BIG_HAMMER);
1694
1695 out:
1696
1697 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
1698 mutex_unlock(&ioc->ctl_cmds.mutex);
1699 return rc;
1700}
1701
1702/**
1703 * _ctl_diag_read_buffer - request for copy of the diag buffer
1704 * @arg - user space buffer containing ioctl content
1705 * @state - NON_BLOCKING or BLOCKING
1706 */
1707static long
1708_ctl_diag_read_buffer(void __user *arg, enum block_state state)
1709{
1710 struct mpt2_diag_read_buffer karg;
1711 struct mpt2_diag_read_buffer __user *uarg = arg;
1712 struct MPT2SAS_ADAPTER *ioc;
1713 void *request_data, *diag_data;
1714 Mpi2DiagBufferPostRequest_t *mpi_request;
1715 Mpi2DiagBufferPostReply_t *mpi_reply;
1716 int rc, i;
1717 u8 buffer_type;
1718 unsigned long timeleft;
1719 u16 smid;
1720 u16 ioc_status;
1721 u8 issue_reset = 0;
1722
1723 if (copy_from_user(&karg, arg, sizeof(karg))) {
1724 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1725 __FILE__, __LINE__, __func__);
1726 return -EFAULT;
1727 }
1728 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
1729 return -ENODEV;
1730
1731 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
1732 __func__));
1733
1734 buffer_type = karg.unique_id & 0x000000ff;
1735 if (!_ctl_diag_capability(ioc, buffer_type)) {
1736 printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
1737 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1738 return -EPERM;
1739 }
1740
1741 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1742 printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
1743 "registered\n", ioc->name, __func__, karg.unique_id);
1744 return -EINVAL;
1745 }
1746
1747 request_data = ioc->diag_buffer[buffer_type];
1748 if (!request_data) {
1749 printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
1750 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
1751 return -ENOMEM;
1752 }
1753
1754 if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
1755 printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
1756 "or bytes_to_read are not 4 byte aligned\n", ioc->name,
1757 __func__);
1758 return -EINVAL;
1759 }
1760
1761 diag_data = (void *)(request_data + karg.starting_offset);
1762 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(%p), "
1763 "offset(%d), sz(%d)\n", ioc->name, __func__,
1764 diag_data, karg.starting_offset, karg.bytes_to_read));
1765
1766 if (copy_to_user((void __user *)uarg->diagnostic_data,
1767 diag_data, karg.bytes_to_read)) {
1768 printk(MPT2SAS_ERR_FMT "%s: Unable to write "
1769 "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
1770 __func__, diag_data);
1771 return -EFAULT;
1772 }
1773
1774 if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0)
1775 return 0;
1776
1777 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: Reregister "
1778 "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type));
1779 if ((ioc->diag_buffer_status[buffer_type] &
1780 MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
1781 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
1782 "buffer_type(0x%02x) is still registered\n", ioc->name,
1783 __func__, buffer_type));
1784 return 0;
1785 }
1786 /* Get a free request frame and save the message context.
1787 */
1788 if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
1789 return -EAGAIN;
1790 else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
1791 return -ERESTARTSYS;
1792
1793 if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
1794 printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
1795 ioc->name, __func__);
1796 rc = -EAGAIN;
1797 goto out;
1798 }
1799
1800 smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1801 if (!smid) {
1802 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1803 ioc->name, __func__);
1804 rc = -EAGAIN;
1805 goto out;
1806 }
1807
1808 rc = 0;
1809 ioc->ctl_cmds.status = MPT2_CMD_PENDING;
1810 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1811 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1812 ioc->ctl_cmds.smid = smid;
1813
1814 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
1815 mpi_request->BufferType = buffer_type;
1816 mpi_request->BufferLength =
1817 cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
1818 mpi_request->BufferAddress =
1819 cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
1820 for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
1821 mpi_request->ProductSpecific[i] =
1822 cpu_to_le32(ioc->product_specific[buffer_type][i]);
1823
1824 mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
1825 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
1826 MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
1827
1828 if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
1829 printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
1830 __func__);
1831 _debug_dump_mf(mpi_request,
1832 sizeof(Mpi2DiagBufferPostRequest_t)/4);
1833 if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
1834 issue_reset = 1;
1835 goto issue_host_reset;
1836 }
1837
1838 /* process the completed Reply Message Frame */
1839 if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
1840 printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
1841 ioc->name, __func__);
1842 rc = -EFAULT;
1843 goto out;
1844 }
1845
1846 mpi_reply = ioc->ctl_cmds.reply;
1847 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1848
1849 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1850 ioc->diag_buffer_status[buffer_type] |=
1851 MPT2_DIAG_BUFFER_IS_REGISTERED;
1852 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
1853 ioc->name, __func__));
1854 } else {
1855 printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
1856 "log_info(0x%08x)\n", ioc->name, __func__,
1857 ioc_status, mpi_reply->IOCLogInfo);
1858 rc = -EFAULT;
1859 }
1860
1861 issue_host_reset:
1862 if (issue_reset)
1863 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1864 FORCE_BIG_HAMMER);
1865
1866 out:
1867
1868 ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
1869 mutex_unlock(&ioc->ctl_cmds.mutex);
1870 return rc;
1871}
1872
1873/**
1874 * _ctl_ioctl_main - main ioctl entry point
1875 * @file - (struct file)
1876 * @cmd - ioctl opcode
1877 * @arg -
1878 */
1879static long
1880_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
1881{
1882 enum block_state state;
1883 long ret = -EINVAL;
1884 unsigned long flags;
1885
1886 state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING :
1887 BLOCKING;
1888
1889 switch (cmd) {
1890 case MPT2IOCINFO:
1891 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo))
1892 ret = _ctl_getiocinfo(arg);
1893 break;
1894 case MPT2COMMAND:
1895 {
1896 struct mpt2_ioctl_command karg;
1897 struct mpt2_ioctl_command __user *uarg;
1898 struct MPT2SAS_ADAPTER *ioc;
1899
1900 if (copy_from_user(&karg, arg, sizeof(karg))) {
1901 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1902 __FILE__, __LINE__, __func__);
1903 return -EFAULT;
1904 }
1905
1906 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
1907 !ioc)
1908 return -ENODEV;
1909
1910 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
1911 if (ioc->shost_recovery) {
1912 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
1913 flags);
1914 return -EAGAIN;
1915 }
1916 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
1917
1918 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
1919 uarg = arg;
1920 ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
1921 }
1922 break;
1923 }
1924 case MPT2EVENTQUERY:
1925 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery))
1926 ret = _ctl_eventquery(arg);
1927 break;
1928 case MPT2EVENTENABLE:
1929 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable))
1930 ret = _ctl_eventenable(arg);
1931 break;
1932 case MPT2EVENTREPORT:
1933 ret = _ctl_eventreport(arg);
1934 break;
1935 case MPT2HARDRESET:
1936 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset))
1937 ret = _ctl_do_reset(arg);
1938 break;
1939 case MPT2BTDHMAPPING:
1940 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping))
1941 ret = _ctl_btdh_mapping(arg);
1942 break;
1943 case MPT2DIAGREGISTER:
1944 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register))
1945 ret = _ctl_diag_register(arg, state);
1946 break;
1947 case MPT2DIAGUNREGISTER:
1948 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister))
1949 ret = _ctl_diag_unregister(arg);
1950 break;
1951 case MPT2DIAGQUERY:
1952 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query))
1953 ret = _ctl_diag_query(arg);
1954 break;
1955 case MPT2DIAGRELEASE:
1956 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release))
1957 ret = _ctl_diag_release(arg, state);
1958 break;
1959 case MPT2DIAGREADBUFFER:
1960 if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer))
1961 ret = _ctl_diag_read_buffer(arg, state);
1962 break;
1963 default:
1964 {
1965 struct mpt2_ioctl_command karg;
1966 struct MPT2SAS_ADAPTER *ioc;
1967
1968 if (copy_from_user(&karg, arg, sizeof(karg))) {
1969 printk(KERN_ERR "failure at %s:%d/%s()!\n",
1970 __FILE__, __LINE__, __func__);
1971 return -EFAULT;
1972 }
1973
1974 if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
1975 !ioc)
1976 return -ENODEV;
1977
1978 dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1979 "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
1980 break;
1981 }
1982 }
1983 return ret;
1984}
1985
1986/**
1987 * _ctl_ioctl - main ioctl entry point (unlocked)
1988 * @file - (struct file)
1989 * @cmd - ioctl opcode
1990 * @arg -
1991 */
1992static long
1993_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1994{
1995 long ret;
1996 lock_kernel();
1997 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
1998 unlock_kernel();
1999 return ret;
2000}
2001
2002#ifdef CONFIG_COMPAT
2003/**
2004 * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
2005 * @file - (struct file)
2006 * @cmd - ioctl opcode
2007 * @arg - (struct mpt2_ioctl_command32)
2008 *
2009 * MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
2010 */
2011static long
2012_ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
2013{
2014 struct mpt2_ioctl_command32 karg32;
2015 struct mpt2_ioctl_command32 __user *uarg;
2016 struct mpt2_ioctl_command karg;
2017 struct MPT2SAS_ADAPTER *ioc;
2018 enum block_state state;
2019 unsigned long flags;
2020
2021 if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
2022 return -EINVAL;
2023
2024 uarg = (struct mpt2_ioctl_command32 __user *) arg;
2025
2026 if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
2027 printk(KERN_ERR "failure at %s:%d/%s()!\n",
2028 __FILE__, __LINE__, __func__);
2029 return -EFAULT;
2030 }
2031 if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
2032 return -ENODEV;
2033
2034 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
2035 if (ioc->shost_recovery) {
2036 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
2037 flags);
2038 return -EAGAIN;
2039 }
2040 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
2041
2042 memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
2043 karg.hdr.ioc_number = karg32.hdr.ioc_number;
2044 karg.hdr.port_number = karg32.hdr.port_number;
2045 karg.hdr.max_data_size = karg32.hdr.max_data_size;
2046 karg.timeout = karg32.timeout;
2047 karg.max_reply_bytes = karg32.max_reply_bytes;
2048 karg.data_in_size = karg32.data_in_size;
2049 karg.data_out_size = karg32.data_out_size;
2050 karg.max_sense_bytes = karg32.max_sense_bytes;
2051 karg.data_sge_offset = karg32.data_sge_offset;
2052 memcpy(&karg.reply_frame_buf_ptr, &karg32.reply_frame_buf_ptr,
2053 sizeof(uint32_t));
2054 memcpy(&karg.data_in_buf_ptr, &karg32.data_in_buf_ptr,
2055 sizeof(uint32_t));
2056 memcpy(&karg.data_out_buf_ptr, &karg32.data_out_buf_ptr,
2057 sizeof(uint32_t));
2058 memcpy(&karg.sense_data_ptr, &karg32.sense_data_ptr,
2059 sizeof(uint32_t));
2060 state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
2061 return _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
2062}
2063
2064/**
2065 * _ctl_ioctl_compat - main ioctl entry point (compat)
2066 * @file -
2067 * @cmd -
2068 * @arg -
2069 *
2070 * This routine handles 32 bit applications in 64bit os.
2071 */
2072static long
2073_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
2074{
2075 long ret;
2076 lock_kernel();
2077 if (cmd == MPT2COMMAND32)
2078 ret = _ctl_compat_mpt_command(file, cmd, arg);
2079 else
2080 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
2081 unlock_kernel();
2082 return ret;
2083}
2084#endif
2085
2086/* scsi host attributes */
2087
2088/**
2089 * _ctl_version_fw_show - firmware version
2090 * @cdev - pointer to embedded class device
2091 * @buf - the buffer returned
2092 *
2093 * A sysfs 'read-only' shost attribute.
2094 */
2095static ssize_t
2096_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr,
2097 char *buf)
2098{
2099 struct Scsi_Host *shost = class_to_shost(cdev);
2100 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2101
2102 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2103 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
2104 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
2105 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
2106 ioc->facts.FWVersion.Word & 0x000000FF);
2107}
2108static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL);
2109
2110/**
2111 * _ctl_version_bios_show - bios version
2112 * @cdev - pointer to embedded class device
2113 * @buf - the buffer returned
2114 *
2115 * A sysfs 'read-only' shost attribute.
2116 */
2117static ssize_t
2118_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr,
2119 char *buf)
2120{
2121 struct Scsi_Host *shost = class_to_shost(cdev);
2122 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2123
2124 u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
2125
2126 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2127 (version & 0xFF000000) >> 24,
2128 (version & 0x00FF0000) >> 16,
2129 (version & 0x0000FF00) >> 8,
2130 version & 0x000000FF);
2131}
2132static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL);
2133
2134/**
2135 * _ctl_version_mpi_show - MPI (message passing interface) version
2136 * @cdev - pointer to embedded class device
2137 * @buf - the buffer returned
2138 *
2139 * A sysfs 'read-only' shost attribute.
2140 */
2141static ssize_t
2142_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr,
2143 char *buf)
2144{
2145 struct Scsi_Host *shost = class_to_shost(cdev);
2146 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2147
2148 return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
2149 ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
2150}
2151static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL);
2152
2153/**
2154 * _ctl_version_product_show - product name
2155 * @cdev - pointer to embedded class device
2156 * @buf - the buffer returned
2157 *
2158 * A sysfs 'read-only' shost attribute.
2159 */
2160static ssize_t
2161_ctl_version_product_show(struct device *cdev, struct device_attribute *attr,
2162 char *buf)
2163{
2164 struct Scsi_Host *shost = class_to_shost(cdev);
2165 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2166
2167 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
2168}
2169static DEVICE_ATTR(version_product, S_IRUGO,
2170 _ctl_version_product_show, NULL);
2171
2172/**
2173 * _ctl_version_nvdata_persistent_show - ndvata persistent version
2174 * @cdev - pointer to embedded class device
2175 * @buf - the buffer returned
2176 *
2177 * A sysfs 'read-only' shost attribute.
2178 */
2179static ssize_t
2180_ctl_version_nvdata_persistent_show(struct device *cdev,
2181 struct device_attribute *attr, char *buf)
2182{
2183 struct Scsi_Host *shost = class_to_shost(cdev);
2184 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2185
2186 return snprintf(buf, PAGE_SIZE, "%02xh\n",
2187 le16_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
2188}
2189static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
2190 _ctl_version_nvdata_persistent_show, NULL);
2191
2192/**
2193 * _ctl_version_nvdata_default_show - nvdata default version
2194 * @cdev - pointer to embedded class device
2195 * @buf - the buffer returned
2196 *
2197 * A sysfs 'read-only' shost attribute.
2198 */
2199static ssize_t
2200_ctl_version_nvdata_default_show(struct device *cdev,
2201 struct device_attribute *attr, char *buf)
2202{
2203 struct Scsi_Host *shost = class_to_shost(cdev);
2204 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2205
2206 return snprintf(buf, PAGE_SIZE, "%02xh\n",
2207 le16_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
2208}
2209static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
2210 _ctl_version_nvdata_default_show, NULL);
2211
2212/**
2213 * _ctl_board_name_show - board name
2214 * @cdev - pointer to embedded class device
2215 * @buf - the buffer returned
2216 *
2217 * A sysfs 'read-only' shost attribute.
2218 */
2219static ssize_t
2220_ctl_board_name_show(struct device *cdev, struct device_attribute *attr,
2221 char *buf)
2222{
2223 struct Scsi_Host *shost = class_to_shost(cdev);
2224 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2225
2226 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
2227}
2228static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL);
2229
2230/**
2231 * _ctl_board_assembly_show - board assembly name
2232 * @cdev - pointer to embedded class device
2233 * @buf - the buffer returned
2234 *
2235 * A sysfs 'read-only' shost attribute.
2236 */
2237static ssize_t
2238_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr,
2239 char *buf)
2240{
2241 struct Scsi_Host *shost = class_to_shost(cdev);
2242 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2243
2244 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
2245}
2246static DEVICE_ATTR(board_assembly, S_IRUGO,
2247 _ctl_board_assembly_show, NULL);
2248
2249/**
2250 * _ctl_board_tracer_show - board tracer number
2251 * @cdev - pointer to embedded class device
2252 * @buf - the buffer returned
2253 *
2254 * A sysfs 'read-only' shost attribute.
2255 */
2256static ssize_t
2257_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr,
2258 char *buf)
2259{
2260 struct Scsi_Host *shost = class_to_shost(cdev);
2261 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2262
2263 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
2264}
2265static DEVICE_ATTR(board_tracer, S_IRUGO,
2266 _ctl_board_tracer_show, NULL);
2267
2268/**
2269 * _ctl_io_delay_show - io missing delay
2270 * @cdev - pointer to embedded class device
2271 * @buf - the buffer returned
2272 *
2273 * This is for firmware implemention for deboucing device
2274 * removal events.
2275 *
2276 * A sysfs 'read-only' shost attribute.
2277 */
2278static ssize_t
2279_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr,
2280 char *buf)
2281{
2282 struct Scsi_Host *shost = class_to_shost(cdev);
2283 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2284
2285 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
2286}
2287static DEVICE_ATTR(io_delay, S_IRUGO,
2288 _ctl_io_delay_show, NULL);
2289
2290/**
2291 * _ctl_device_delay_show - device missing delay
2292 * @cdev - pointer to embedded class device
2293 * @buf - the buffer returned
2294 *
2295 * This is for firmware implemention for deboucing device
2296 * removal events.
2297 *
2298 * A sysfs 'read-only' shost attribute.
2299 */
2300static ssize_t
2301_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr,
2302 char *buf)
2303{
2304 struct Scsi_Host *shost = class_to_shost(cdev);
2305 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2306
2307 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
2308}
2309static DEVICE_ATTR(device_delay, S_IRUGO,
2310 _ctl_device_delay_show, NULL);
2311
2312/**
2313 * _ctl_fw_queue_depth_show - global credits
2314 * @cdev - pointer to embedded class device
2315 * @buf - the buffer returned
2316 *
2317 * This is firmware queue depth limit
2318 *
2319 * A sysfs 'read-only' shost attribute.
2320 */
2321static ssize_t
2322_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
2323 char *buf)
2324{
2325 struct Scsi_Host *shost = class_to_shost(cdev);
2326 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2327
2328 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
2329}
2330static DEVICE_ATTR(fw_queue_depth, S_IRUGO,
2331 _ctl_fw_queue_depth_show, NULL);
2332
2333/**
2334 * _ctl_sas_address_show - sas address
2335 * @cdev - pointer to embedded class device
2336 * @buf - the buffer returned
2337 *
2338 * This is the controller sas address
2339 *
2340 * A sysfs 'read-only' shost attribute.
2341 */
2342static ssize_t
2343_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr,
2344 char *buf)
2345{
2346 struct Scsi_Host *shost = class_to_shost(cdev);
2347 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2348
2349 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
2350 (unsigned long long)ioc->sas_hba.sas_address);
2351}
2352static DEVICE_ATTR(host_sas_address, S_IRUGO,
2353 _ctl_host_sas_address_show, NULL);
2354
2355/**
2356 * _ctl_logging_level_show - logging level
2357 * @cdev - pointer to embedded class device
2358 * @buf - the buffer returned
2359 *
2360 * A sysfs 'read/write' shost attribute.
2361 */
2362static ssize_t
2363_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr,
2364 char *buf)
2365{
2366 struct Scsi_Host *shost = class_to_shost(cdev);
2367 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2368
2369 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
2370}
2371static ssize_t
2372_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
2373 const char *buf, size_t count)
2374{
2375 struct Scsi_Host *shost = class_to_shost(cdev);
2376 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
2377 int val = 0;
2378
2379 if (sscanf(buf, "%x", &val) != 1)
2380 return -EINVAL;
2381
2382 ioc->logging_level = val;
2383 printk(MPT2SAS_INFO_FMT "logging_level=%08xh\n", ioc->name,
2384 ioc->logging_level);
2385 return strlen(buf);
2386}
2387static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
2388 _ctl_logging_level_show, _ctl_logging_level_store);
2389
2390struct device_attribute *mpt2sas_host_attrs[] = {
2391 &dev_attr_version_fw,
2392 &dev_attr_version_bios,
2393 &dev_attr_version_mpi,
2394 &dev_attr_version_product,
2395 &dev_attr_version_nvdata_persistent,
2396 &dev_attr_version_nvdata_default,
2397 &dev_attr_board_name,
2398 &dev_attr_board_assembly,
2399 &dev_attr_board_tracer,
2400 &dev_attr_io_delay,
2401 &dev_attr_device_delay,
2402 &dev_attr_logging_level,
2403 &dev_attr_fw_queue_depth,
2404 &dev_attr_host_sas_address,
2405 NULL,
2406};
2407
2408/* device attributes */
2409
2410/**
2411 * _ctl_device_sas_address_show - sas address
2412 * @cdev - pointer to embedded class device
2413 * @buf - the buffer returned
2414 *
2415 * This is the sas address for the target
2416 *
2417 * A sysfs 'read-only' shost attribute.
2418 */
2419static ssize_t
2420_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr,
2421 char *buf)
2422{
2423 struct scsi_device *sdev = to_scsi_device(dev);
2424 struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
2425
2426 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
2427 (unsigned long long)sas_device_priv_data->sas_target->sas_address);
2428}
2429static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL);
2430
2431/**
2432 * _ctl_device_handle_show - device handle
2433 * @cdev - pointer to embedded class device
2434 * @buf - the buffer returned
2435 *
2436 * This is the firmware assigned device handle
2437 *
2438 * A sysfs 'read-only' shost attribute.
2439 */
2440static ssize_t
2441_ctl_device_handle_show(struct device *dev, struct device_attribute *attr,
2442 char *buf)
2443{
2444 struct scsi_device *sdev = to_scsi_device(dev);
2445 struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
2446
2447 return snprintf(buf, PAGE_SIZE, "0x%04x\n",
2448 sas_device_priv_data->sas_target->handle);
2449}
2450static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL);
2451
2452struct device_attribute *mpt2sas_dev_attrs[] = {
2453 &dev_attr_sas_address,
2454 &dev_attr_sas_device_handle,
2455 NULL,
2456};
2457
2458static const struct file_operations ctl_fops = {
2459 .owner = THIS_MODULE,
2460 .unlocked_ioctl = _ctl_ioctl,
2461 .release = _ctl_release,
2462 .poll = _ctl_poll,
2463 .fasync = _ctl_fasync,
2464#ifdef CONFIG_COMPAT
2465 .compat_ioctl = _ctl_ioctl_compat,
2466#endif
2467};
2468
2469static struct miscdevice ctl_dev = {
2470 .minor = MPT2SAS_MINOR,
2471 .name = MPT2SAS_DEV_NAME,
2472 .fops = &ctl_fops,
2473};
2474
2475/**
2476 * mpt2sas_ctl_init - main entry point for ctl.
2477 *
2478 */
2479void
2480mpt2sas_ctl_init(void)
2481{
2482 async_queue = NULL;
2483 if (misc_register(&ctl_dev) < 0)
2484 printk(KERN_ERR "%s can't register misc device [minor=%d]\n",
2485 MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
2486
2487 init_waitqueue_head(&ctl_poll_wait);
2488}
2489
2490/**
2491 * mpt2sas_ctl_exit - exit point for ctl
2492 *
2493 */
2494void
2495mpt2sas_ctl_exit(void)
2496{
2497 struct MPT2SAS_ADAPTER *ioc;
2498 int i;
2499
2500 list_for_each_entry(ioc, &ioc_list, list) {
2501
2502 /* free memory associated to diag buffers */
2503 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
2504 if (!ioc->diag_buffer[i])
2505 continue;
2506 pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i],
2507 ioc->diag_buffer[i], ioc->diag_buffer_dma[i]);
2508 ioc->diag_buffer[i] = NULL;
2509 ioc->diag_buffer_status[i] = 0;
2510 }
2511
2512 kfree(ioc->event_log);
2513 }
2514 misc_deregister(&ctl_dev);
2515}
2516
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
new file mode 100644
index 000000000000..dbb6c0cf8889
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
@@ -0,0 +1,416 @@
1/*
2 * Management Module Support for MPT (Message Passing Technology) based
3 * controllers
4 *
5 * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h
6 * Copyright (C) 2007-2008 LSI Corporation
7 * (mailto:DL-MPTFusionLinux@lsi.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * NO WARRANTY
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
29
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
42 * USA.
43 */
44
45#ifndef MPT2SAS_CTL_H_INCLUDED
46#define MPT2SAS_CTL_H_INCLUDED
47
48#ifdef __KERNEL__
49#include <linux/miscdevice.h>
50#endif
51
52#define MPT2SAS_DEV_NAME "mpt2ctl"
53#define MPT2_MAGIC_NUMBER 'm'
54#define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
55
56/**
57 * IOCTL opcodes
58 */
59#define MPT2IOCINFO _IOWR(MPT2_MAGIC_NUMBER, 17, \
60 struct mpt2_ioctl_iocinfo)
61#define MPT2COMMAND _IOWR(MPT2_MAGIC_NUMBER, 20, \
62 struct mpt2_ioctl_command)
63#ifdef CONFIG_COMPAT
64#define MPT2COMMAND32 _IOWR(MPT2_MAGIC_NUMBER, 20, \
65 struct mpt2_ioctl_command32)
66#endif
67#define MPT2EVENTQUERY _IOWR(MPT2_MAGIC_NUMBER, 21, \
68 struct mpt2_ioctl_eventquery)
69#define MPT2EVENTENABLE _IOWR(MPT2_MAGIC_NUMBER, 22, \
70 struct mpt2_ioctl_eventenable)
71#define MPT2EVENTREPORT _IOWR(MPT2_MAGIC_NUMBER, 23, \
72 struct mpt2_ioctl_eventreport)
73#define MPT2HARDRESET _IOWR(MPT2_MAGIC_NUMBER, 24, \
74 struct mpt2_ioctl_diag_reset)
75#define MPT2BTDHMAPPING _IOWR(MPT2_MAGIC_NUMBER, 31, \
76 struct mpt2_ioctl_btdh_mapping)
77
78/* diag buffer support */
79#define MPT2DIAGREGISTER _IOWR(MPT2_MAGIC_NUMBER, 26, \
80 struct mpt2_diag_register)
81#define MPT2DIAGRELEASE _IOWR(MPT2_MAGIC_NUMBER, 27, \
82 struct mpt2_diag_release)
83#define MPT2DIAGUNREGISTER _IOWR(MPT2_MAGIC_NUMBER, 28, \
84 struct mpt2_diag_unregister)
85#define MPT2DIAGQUERY _IOWR(MPT2_MAGIC_NUMBER, 29, \
86 struct mpt2_diag_query)
87#define MPT2DIAGREADBUFFER _IOWR(MPT2_MAGIC_NUMBER, 30, \
88 struct mpt2_diag_read_buffer)
89
90/**
91 * struct mpt2_ioctl_header - main header structure
92 * @ioc_number - IOC unit number
93 * @port_number - IOC port number
94 * @max_data_size - maximum number bytes to transfer on read
95 */
96struct mpt2_ioctl_header {
97 uint32_t ioc_number;
98 uint32_t port_number;
99 uint32_t max_data_size;
100};
101
102/**
103 * struct mpt2_ioctl_diag_reset - diagnostic reset
104 * @hdr - generic header
105 */
106struct mpt2_ioctl_diag_reset {
107 struct mpt2_ioctl_header hdr;
108};
109
110
111/**
112 * struct mpt2_ioctl_pci_info - pci device info
113 * @device - pci device id
114 * @function - pci function id
115 * @bus - pci bus id
116 * @segment_id - pci segment id
117 */
118struct mpt2_ioctl_pci_info {
119 union {
120 struct {
121 uint32_t device:5;
122 uint32_t function:3;
123 uint32_t bus:24;
124 } bits;
125 uint32_t word;
126 } u;
127 uint32_t segment_id;
128};
129
130
131#define MPT2_IOCTL_INTERFACE_SCSI (0x00)
132#define MPT2_IOCTL_INTERFACE_FC (0x01)
133#define MPT2_IOCTL_INTERFACE_FC_IP (0x02)
134#define MPT2_IOCTL_INTERFACE_SAS (0x03)
135#define MPT2_IOCTL_INTERFACE_SAS2 (0x04)
136#define MPT2_IOCTL_VERSION_LENGTH (32)
137
138/**
139 * struct mpt2_ioctl_iocinfo - generic controller info
140 * @hdr - generic header
141 * @adapter_type - type of adapter (spi, fc, sas)
142 * @port_number - port number
143 * @pci_id - PCI Id
144 * @hw_rev - hardware revision
145 * @sub_system_device - PCI subsystem Device ID
146 * @sub_system_vendor - PCI subsystem Vendor ID
147 * @rsvd0 - reserved
148 * @firmware_version - firmware version
149 * @bios_version - BIOS version
150 * @driver_version - driver version - 32 ASCII characters
151 * @rsvd1 - reserved
152 * @scsi_id - scsi id of adapter 0
153 * @rsvd2 - reserved
154 * @pci_information - pci info (2nd revision)
155 */
156struct mpt2_ioctl_iocinfo {
157 struct mpt2_ioctl_header hdr;
158 uint32_t adapter_type;
159 uint32_t port_number;
160 uint32_t pci_id;
161 uint32_t hw_rev;
162 uint32_t subsystem_device;
163 uint32_t subsystem_vendor;
164 uint32_t rsvd0;
165 uint32_t firmware_version;
166 uint32_t bios_version;
167 uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH];
168 uint8_t rsvd1;
169 uint8_t scsi_id;
170 uint16_t rsvd2;
171 struct mpt2_ioctl_pci_info pci_information;
172};
173
174
175/* number of event log entries */
176#define MPT2SAS_CTL_EVENT_LOG_SIZE (50)
177
178/**
179 * struct mpt2_ioctl_eventquery - query event count and type
180 * @hdr - generic header
181 * @event_entries - number of events returned by get_event_report
182 * @rsvd - reserved
183 * @event_types - type of events currently being captured
184 */
185struct mpt2_ioctl_eventquery {
186 struct mpt2_ioctl_header hdr;
187 uint16_t event_entries;
188 uint16_t rsvd;
189 uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
190};
191
192/**
193 * struct mpt2_ioctl_eventenable - enable/disable event capturing
194 * @hdr - generic header
195 * @event_types - toggle off/on type of events to be captured
196 */
197struct mpt2_ioctl_eventenable {
198 struct mpt2_ioctl_header hdr;
199 uint32_t event_types[4];
200};
201
202#define MPT2_EVENT_DATA_SIZE (192)
203/**
204 * struct MPT2_IOCTL_EVENTS -
205 * @event - the event that was reported
206 * @context - unique value for each event assigned by driver
207 * @data - event data returned in fw reply message
208 */
209struct MPT2_IOCTL_EVENTS {
210 uint32_t event;
211 uint32_t context;
212 uint8_t data[MPT2_EVENT_DATA_SIZE];
213};
214
215/**
216 * struct mpt2_ioctl_eventreport - returing event log
217 * @hdr - generic header
218 * @event_data - (see struct MPT2_IOCTL_EVENTS)
219 */
220struct mpt2_ioctl_eventreport {
221 struct mpt2_ioctl_header hdr;
222 struct MPT2_IOCTL_EVENTS event_data[1];
223};
224
225/**
226 * struct mpt2_ioctl_command - generic mpt firmware passthru ioclt
227 * @hdr - generic header
228 * @timeout - command timeout in seconds. (if zero then use driver default
229 * value).
230 * @reply_frame_buf_ptr - reply location
231 * @data_in_buf_ptr - destination for read
232 * @data_out_buf_ptr - data source for write
233 * @sense_data_ptr - sense data location
234 * @max_reply_bytes - maximum number of reply bytes to be sent to app.
235 * @data_in_size - number bytes for data transfer in (read)
236 * @data_out_size - number bytes for data transfer out (write)
237 * @max_sense_bytes - maximum number of bytes for auto sense buffers
238 * @data_sge_offset - offset in words from the start of the request message to
239 * the first SGL
240 * @mf[1];
241 */
242struct mpt2_ioctl_command {
243 struct mpt2_ioctl_header hdr;
244 uint32_t timeout;
245 void __user *reply_frame_buf_ptr;
246 void __user *data_in_buf_ptr;
247 void __user *data_out_buf_ptr;
248 void __user *sense_data_ptr;
249 uint32_t max_reply_bytes;
250 uint32_t data_in_size;
251 uint32_t data_out_size;
252 uint32_t max_sense_bytes;
253 uint32_t data_sge_offset;
254 uint8_t mf[1];
255};
256
257#ifdef CONFIG_COMPAT
258struct mpt2_ioctl_command32 {
259 struct mpt2_ioctl_header hdr;
260 uint32_t timeout;
261 uint32_t reply_frame_buf_ptr;
262 uint32_t data_in_buf_ptr;
263 uint32_t data_out_buf_ptr;
264 uint32_t sense_data_ptr;
265 uint32_t max_reply_bytes;
266 uint32_t data_in_size;
267 uint32_t data_out_size;
268 uint32_t max_sense_bytes;
269 uint32_t data_sge_offset;
270 uint8_t mf[1];
271};
272#endif
273
274/**
275 * struct mpt2_ioctl_btdh_mapping - mapping info
276 * @hdr - generic header
277 * @id - target device identification number
278 * @bus - SCSI bus number that the target device exists on
279 * @handle - device handle for the target device
280 * @rsvd - reserved
281 *
282 * To obtain a bus/id the application sets
283 * handle to valid handle, and bus/id to 0xFFFF.
284 *
285 * To obtain the device handle the application sets
286 * bus/id valid value, and the handle to 0xFFFF.
287 */
288struct mpt2_ioctl_btdh_mapping {
289 struct mpt2_ioctl_header hdr;
290 uint32_t id;
291 uint32_t bus;
292 uint16_t handle;
293 uint16_t rsvd;
294};
295
296
297/* status bits for ioc->diag_buffer_status */
298#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
299#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
300
301/* application flags for mpt2_diag_register, mpt2_diag_query */
302#define MPT2_APP_FLAGS_APP_OWNED (0x0001)
303#define MPT2_APP_FLAGS_BUFFER_VALID (0x0002)
304#define MPT2_APP_FLAGS_FW_BUFFER_ACCESS (0x0004)
305
306/* flags for mpt2_diag_read_buffer */
307#define MPT2_FLAGS_REREGISTER (0x0001)
308
309#define MPT2_PRODUCT_SPECIFIC_DWORDS 23
310
311/**
312 * struct mpt2_diag_register - application register with driver
313 * @hdr - generic header
314 * @reserved -
315 * @buffer_type - specifies either TRACE or SNAPSHOT
316 * @application_flags - misc flags
317 * @diagnostic_flags - specifies flags affecting command processing
318 * @product_specific - product specific information
319 * @requested_buffer_size - buffers size in bytes
320 * @unique_id - tag specified by application that is used to signal ownership
321 * of the buffer.
322 *
323 * This will allow the driver to setup any required buffers that will be
324 * needed by firmware to communicate with the driver.
325 */
326struct mpt2_diag_register {
327 struct mpt2_ioctl_header hdr;
328 uint8_t reserved;
329 uint8_t buffer_type;
330 uint16_t application_flags;
331 uint32_t diagnostic_flags;
332 uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS];
333 uint32_t requested_buffer_size;
334 uint32_t unique_id;
335};
336
337/**
338 * struct mpt2_diag_unregister - application unregister with driver
339 * @hdr - generic header
340 * @unique_id - tag uniquely identifies the buffer to be unregistered
341 *
342 * This will allow the driver to cleanup any memory allocated for diag
343 * messages and to free up any resources.
344 */
345struct mpt2_diag_unregister {
346 struct mpt2_ioctl_header hdr;
347 uint32_t unique_id;
348};
349
350/**
351 * struct mpt2_diag_query - query relevant info associated with diag buffers
352 * @hdr - generic header
353 * @reserved -
354 * @buffer_type - specifies either TRACE or SNAPSHOT
355 * @application_flags - misc flags
356 * @diagnostic_flags - specifies flags affecting command processing
357 * @product_specific - product specific information
358 * @total_buffer_size - diag buffer size in bytes
359 * @driver_added_buffer_size - size of extra space appended to end of buffer
360 * @unique_id - unique id associated with this buffer.
361 *
362 * The application will send only buffer_type and unique_id. Driver will
363 * inspect unique_id first, if valid, fill in all the info. If unique_id is
364 * 0x00, the driver will return info specified by Buffer Type.
365 */
366struct mpt2_diag_query {
367 struct mpt2_ioctl_header hdr;
368 uint8_t reserved;
369 uint8_t buffer_type;
370 uint16_t application_flags;
371 uint32_t diagnostic_flags;
372 uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS];
373 uint32_t total_buffer_size;
374 uint32_t driver_added_buffer_size;
375 uint32_t unique_id;
376};
377
378/**
379 * struct mpt2_diag_release - request to send Diag Release Message to firmware
380 * @hdr - generic header
381 * @unique_id - tag uniquely identifies the buffer to be released
382 *
383 * This allows ownership of the specified buffer to returned to the driver,
384 * allowing an application to read the buffer without fear that firmware is
385 * overwritting information in the buffer.
386 */
387struct mpt2_diag_release {
388 struct mpt2_ioctl_header hdr;
389 uint32_t unique_id;
390};
391
392/**
393 * struct mpt2_diag_read_buffer - request for copy of the diag buffer
394 * @hdr - generic header
395 * @status -
396 * @reserved -
397 * @flags - misc flags
398 * @starting_offset - starting offset within drivers buffer where to start
399 * reading data at into the specified application buffer
400 * @bytes_to_read - number of bytes to copy from the drivers buffer into the
401 * application buffer starting at starting_offset.
402 * @unique_id - unique id associated with this buffer.
403 * @diagnostic_data - data payload
404 */
405struct mpt2_diag_read_buffer {
406 struct mpt2_ioctl_header hdr;
407 uint8_t status;
408 uint8_t reserved;
409 uint16_t flags;
410 uint32_t starting_offset;
411 uint32_t bytes_to_read;
412 uint32_t unique_id;
413 uint32_t diagnostic_data[1];
414};
415
416#endif /* MPT2SAS_CTL_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h
new file mode 100644
index 000000000000..ad325096e842
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h
@@ -0,0 +1,181 @@
1/*
2 * Logging Support for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c
5 * Copyright (C) 2007-2008 LSI Corporation
6 * (mailto:DL-MPTFusionLinux@lsi.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * NO WARRANTY
19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23 * solely responsible for determining the appropriateness of using and
24 * distributing the Program and assumes all risks associated with its
25 * exercise of rights under this Agreement, including but not limited to
26 * the risks and costs of program errors, damage to or loss of data,
27 * programs or equipment, and unavailability or interruption of operations.
28
29 * DISCLAIMER OF LIABILITY
30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
41 * USA.
42 */
43
44#ifndef MPT2SAS_DEBUG_H_INCLUDED
45#define MPT2SAS_DEBUG_H_INCLUDED
46
47#define MPT_DEBUG 0x00000001
48#define MPT_DEBUG_MSG_FRAME 0x00000002
49#define MPT_DEBUG_SG 0x00000004
50#define MPT_DEBUG_EVENTS 0x00000008
51#define MPT_DEBUG_EVENT_WORK_TASK 0x00000010
52#define MPT_DEBUG_INIT 0x00000020
53#define MPT_DEBUG_EXIT 0x00000040
54#define MPT_DEBUG_FAIL 0x00000080
55#define MPT_DEBUG_TM 0x00000100
56#define MPT_DEBUG_REPLY 0x00000200
57#define MPT_DEBUG_HANDSHAKE 0x00000400
58#define MPT_DEBUG_CONFIG 0x00000800
59#define MPT_DEBUG_DL 0x00001000
60#define MPT_DEBUG_RESET 0x00002000
61#define MPT_DEBUG_SCSI 0x00004000
62#define MPT_DEBUG_IOCTL 0x00008000
63#define MPT_DEBUG_CSMISAS 0x00010000
64#define MPT_DEBUG_SAS 0x00020000
65#define MPT_DEBUG_TRANSPORT 0x00040000
66#define MPT_DEBUG_TASK_SET_FULL 0x00080000
67
68#define MPT_DEBUG_TARGET_MODE 0x00100000
69
70
71/*
72 * CONFIG_SCSI_MPT2SAS_LOGGING - enabled in Kconfig
73 */
74
75#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
76#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \
77{ \
78 if (IOC->logging_level & BITS) \
79 CMD; \
80}
81#else
82#define MPT_CHECK_LOGGING(IOC, CMD, BITS)
83#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */
84
85
86/*
87 * debug macros
88 */
89
90#define dprintk(IOC, CMD) \
91 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG)
92
93#define dsgprintk(IOC, CMD) \
94 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG)
95
96#define devtprintk(IOC, CMD) \
97 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS)
98
99#define dewtprintk(IOC, CMD) \
100 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK)
101
102#define dinitprintk(IOC, CMD) \
103 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT)
104
105#define dexitprintk(IOC, CMD) \
106 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT)
107
108#define dfailprintk(IOC, CMD) \
109 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL)
110
111#define dtmprintk(IOC, CMD) \
112 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM)
113
114#define dreplyprintk(IOC, CMD) \
115 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY)
116
117#define dhsprintk(IOC, CMD) \
118 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE)
119
120#define dcprintk(IOC, CMD) \
121 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG)
122
123#define ddlprintk(IOC, CMD) \
124 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL)
125
126#define drsprintk(IOC, CMD) \
127 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET)
128
129#define dsprintk(IOC, CMD) \
130 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI)
131
132#define dctlprintk(IOC, CMD) \
133 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL)
134
135#define dcsmisasprintk(IOC, CMD) \
136 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CSMISAS)
137
138#define dsasprintk(IOC, CMD) \
139 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS)
140
141#define dsastransport(IOC, CMD) \
142 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
143
144#define dmfprintk(IOC, CMD) \
145 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME)
146
147#define dtsfprintk(IOC, CMD) \
148 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL)
149
150#define dtransportprintk(IOC, CMD) \
151 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT)
152
153#define dTMprintk(IOC, CMD) \
154 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TARGET_MODE)
155
156/* inline functions for dumping debug data*/
157#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
158/**
159 * _debug_dump_mf - print message frame contents
160 * @mpi_request: pointer to message frame
161 * @sz: number of dwords
162 */
163static inline void
164_debug_dump_mf(void *mpi_request, int sz)
165{
166 int i;
167 u32 *mfp = (u32 *)mpi_request;
168
169 printk(KERN_INFO "mf:\n\t");
170 for (i = 0; i < sz; i++) {
171 if (i && ((i % 8) == 0))
172 printk("\n\t");
173 printk("%08x ", le32_to_cpu(mfp[i]));
174 }
175 printk("\n");
176}
177#else
178#define _debug_dump_mf(mpi_request, sz)
179#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */
180
181#endif /* MPT2SAS_DEBUG_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
new file mode 100644
index 000000000000..50865a8e1a4f
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -0,0 +1,5687 @@
1/*
2 * Scsi Host Layer for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c
5 * Copyright (C) 2007-2008 LSI Corporation
6 * (mailto:DL-MPTFusionLinux@lsi.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * NO WARRANTY
19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23 * solely responsible for determining the appropriateness of using and
24 * distributing the Program and assumes all risks associated with its
25 * exercise of rights under this Agreement, including but not limited to
26 * the risks and costs of program errors, damage to or loss of data,
27 * programs or equipment, and unavailability or interruption of operations.
28
29 * DISCLAIMER OF LIABILITY
30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
41 * USA.
42 */
43
44#include <linux/version.h>
45#include <linux/module.h>
46#include <linux/kernel.h>
47#include <linux/init.h>
48#include <linux/errno.h>
49#include <linux/blkdev.h>
50#include <linux/sched.h>
51#include <linux/workqueue.h>
52#include <linux/delay.h>
53#include <linux/pci.h>
54#include <linux/interrupt.h>
55
56#include "mpt2sas_base.h"
57
58MODULE_AUTHOR(MPT2SAS_AUTHOR);
59MODULE_DESCRIPTION(MPT2SAS_DESCRIPTION);
60MODULE_LICENSE("GPL");
61MODULE_VERSION(MPT2SAS_DRIVER_VERSION);
62
63#define RAID_CHANNEL 1
64
65/* forward proto's */
66static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
67 struct _sas_node *sas_expander);
68static void _firmware_event_work(struct work_struct *work);
69
70/* global parameters */
71LIST_HEAD(ioc_list);
72
73/* local parameters */
74static u32 logging_level;
75static u8 scsi_io_cb_idx = -1;
76static u8 tm_cb_idx = -1;
77static u8 ctl_cb_idx = -1;
78static u8 base_cb_idx = -1;
79static u8 transport_cb_idx = -1;
80static u8 config_cb_idx = -1;
81static int mpt_ids;
82
83/* command line options */
84MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
85 "(default=0)");
86
87/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
88#define MPT2SAS_MAX_LUN (16895)
89static int max_lun = MPT2SAS_MAX_LUN;
90module_param(max_lun, int, 0);
91MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
92
93/**
94 * struct sense_info - common structure for obtaining sense keys
95 * @skey: sense key
96 * @asc: additional sense code
97 * @ascq: additional sense code qualifier
98 */
99struct sense_info {
100 u8 skey;
101 u8 asc;
102 u8 ascq;
103};
104
105
106#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
107/**
108 * struct fw_event_work - firmware event struct
109 * @list: link list framework
110 * @work: work object (ioc->fault_reset_work_q)
111 * @ioc: per adapter object
112 * @VF_ID: virtual function id
113 * @host_reset_handling: handling events during host reset
114 * @ignore: flag meaning this event has been marked to ignore
115 * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
116 * @event_data: reply event data payload follows
117 *
118 * This object stored on ioc->fw_event_list.
119 */
120struct fw_event_work {
121 struct list_head list;
122 struct delayed_work work;
123 struct MPT2SAS_ADAPTER *ioc;
124 u8 VF_ID;
125 u8 host_reset_handling;
126 u8 ignore;
127 u16 event;
128 void *event_data;
129};
130
131/**
132 * struct _scsi_io_transfer - scsi io transfer
133 * @handle: sas device handle (assigned by firmware)
134 * @is_raid: flag set for hidden raid components
135 * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
136 * @data_length: data transfer length
137 * @data_dma: dma pointer to data
138 * @sense: sense data
139 * @lun: lun number
140 * @cdb_length: cdb length
141 * @cdb: cdb contents
142 * @valid_reply: flag set for reply message
143 * @timeout: timeout for this command
144 * @sense_length: sense length
145 * @ioc_status: ioc status
146 * @scsi_state: scsi state
147 * @scsi_status: scsi staus
148 * @log_info: log information
149 * @transfer_length: data length transfer when there is a reply message
150 *
151 * Used for sending internal scsi commands to devices within this module.
152 * Refer to _scsi_send_scsi_io().
153 */
154struct _scsi_io_transfer {
155 u16 handle;
156 u8 is_raid;
157 enum dma_data_direction dir;
158 u32 data_length;
159 dma_addr_t data_dma;
160 u8 sense[SCSI_SENSE_BUFFERSIZE];
161 u32 lun;
162 u8 cdb_length;
163 u8 cdb[32];
164 u8 timeout;
165 u8 valid_reply;
166 /* the following bits are only valid when 'valid_reply = 1' */
167 u32 sense_length;
168 u16 ioc_status;
169 u8 scsi_state;
170 u8 scsi_status;
171 u32 log_info;
172 u32 transfer_length;
173};
174
175/*
176 * The pci device ids are defined in mpi/mpi2_cnfg.h.
177 */
178static struct pci_device_id scsih_pci_table[] = {
179 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
180 PCI_ANY_ID, PCI_ANY_ID },
181 /* Falcon ~ 2008*/
182 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
183 PCI_ANY_ID, PCI_ANY_ID },
184 /* Liberator ~ 2108 */
185 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
186 PCI_ANY_ID, PCI_ANY_ID },
187 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
188 PCI_ANY_ID, PCI_ANY_ID },
189 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
190 PCI_ANY_ID, PCI_ANY_ID },
191 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
192 PCI_ANY_ID, PCI_ANY_ID },
193 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
194 PCI_ANY_ID, PCI_ANY_ID },
195 {0} /* Terminating entry */
196};
197MODULE_DEVICE_TABLE(pci, scsih_pci_table);
198
199/**
200 * scsih_set_debug_level - global setting of ioc->logging_level.
201 *
202 * Note: The logging levels are defined in mpt2sas_debug.h.
203 */
204static int
205scsih_set_debug_level(const char *val, struct kernel_param *kp)
206{
207 int ret = param_set_int(val, kp);
208 struct MPT2SAS_ADAPTER *ioc;
209
210 if (ret)
211 return ret;
212
213 printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level);
214 list_for_each_entry(ioc, &ioc_list, list)
215 ioc->logging_level = logging_level;
216 return 0;
217}
218module_param_call(logging_level, scsih_set_debug_level, param_get_int,
219 &logging_level, 0644);
220
221/**
222 * _scsih_srch_boot_sas_address - search based on sas_address
223 * @sas_address: sas address
224 * @boot_device: boot device object from bios page 2
225 *
226 * Returns 1 when there's a match, 0 means no match.
227 */
228static inline int
229_scsih_srch_boot_sas_address(u64 sas_address,
230 Mpi2BootDeviceSasWwid_t *boot_device)
231{
232 return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0;
233}
234
235/**
236 * _scsih_srch_boot_device_name - search based on device name
237 * @device_name: device name specified in INDENTIFY fram
238 * @boot_device: boot device object from bios page 2
239 *
240 * Returns 1 when there's a match, 0 means no match.
241 */
242static inline int
243_scsih_srch_boot_device_name(u64 device_name,
244 Mpi2BootDeviceDeviceName_t *boot_device)
245{
246 return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
247}
248
249/**
250 * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
251 * @enclosure_logical_id: enclosure logical id
252 * @slot_number: slot number
253 * @boot_device: boot device object from bios page 2
254 *
255 * Returns 1 when there's a match, 0 means no match.
256 */
257static inline int
258_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
259 Mpi2BootDeviceEnclosureSlot_t *boot_device)
260{
261 return (enclosure_logical_id == le64_to_cpu(boot_device->
262 EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
263 SlotNumber)) ? 1 : 0;
264}
265
266/**
267 * _scsih_is_boot_device - search for matching boot device.
268 * @sas_address: sas address
269 * @device_name: device name specified in INDENTIFY fram
270 * @enclosure_logical_id: enclosure logical id
271 * @slot_number: slot number
272 * @form: specifies boot device form
273 * @boot_device: boot device object from bios page 2
274 *
275 * Returns 1 when there's a match, 0 means no match.
276 */
277static int
278_scsih_is_boot_device(u64 sas_address, u64 device_name,
279 u64 enclosure_logical_id, u16 slot, u8 form,
280 Mpi2BiosPage2BootDevice_t *boot_device)
281{
282 int rc = 0;
283
284 switch (form) {
285 case MPI2_BIOSPAGE2_FORM_SAS_WWID:
286 if (!sas_address)
287 break;
288 rc = _scsih_srch_boot_sas_address(
289 sas_address, &boot_device->SasWwid);
290 break;
291 case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
292 if (!enclosure_logical_id)
293 break;
294 rc = _scsih_srch_boot_encl_slot(
295 enclosure_logical_id,
296 slot, &boot_device->EnclosureSlot);
297 break;
298 case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
299 if (!device_name)
300 break;
301 rc = _scsih_srch_boot_device_name(
302 device_name, &boot_device->DeviceName);
303 break;
304 case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
305 break;
306 }
307
308 return rc;
309}
310
311/**
312 * _scsih_determine_boot_device - determine boot device.
313 * @ioc: per adapter object
314 * @device: either sas_device or raid_device object
315 * @is_raid: [flag] 1 = raid object, 0 = sas object
316 *
317 * Determines whether this device should be first reported device to
318 * to scsi-ml or sas transport, this purpose is for persistant boot device.
319 * There are primary, alternate, and current entries in bios page 2. The order
320 * priority is primary, alternate, then current. This routine saves
321 * the corresponding device object and is_raid flag in the ioc object.
322 * The saved data to be used later in _scsih_probe_boot_devices().
323 */
324static void
325_scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc,
326 void *device, u8 is_raid)
327{
328 struct _sas_device *sas_device;
329 struct _raid_device *raid_device;
330 u64 sas_address;
331 u64 device_name;
332 u64 enclosure_logical_id;
333 u16 slot;
334
335 /* only process this function when driver loads */
336 if (!ioc->wait_for_port_enable_to_complete)
337 return;
338
339 if (!is_raid) {
340 sas_device = device;
341 sas_address = sas_device->sas_address;
342 device_name = sas_device->device_name;
343 enclosure_logical_id = sas_device->enclosure_logical_id;
344 slot = sas_device->slot;
345 } else {
346 raid_device = device;
347 sas_address = raid_device->wwid;
348 device_name = 0;
349 enclosure_logical_id = 0;
350 slot = 0;
351 }
352
353 if (!ioc->req_boot_device.device) {
354 if (_scsih_is_boot_device(sas_address, device_name,
355 enclosure_logical_id, slot,
356 (ioc->bios_pg2.ReqBootDeviceForm &
357 MPI2_BIOSPAGE2_FORM_MASK),
358 &ioc->bios_pg2.RequestedBootDevice)) {
359 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT
360 "%s: req_boot_device(0x%016llx)\n",
361 ioc->name, __func__,
362 (unsigned long long)sas_address));
363 ioc->req_boot_device.device = device;
364 ioc->req_boot_device.is_raid = is_raid;
365 }
366 }
367
368 if (!ioc->req_alt_boot_device.device) {
369 if (_scsih_is_boot_device(sas_address, device_name,
370 enclosure_logical_id, slot,
371 (ioc->bios_pg2.ReqAltBootDeviceForm &
372 MPI2_BIOSPAGE2_FORM_MASK),
373 &ioc->bios_pg2.RequestedAltBootDevice)) {
374 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT
375 "%s: req_alt_boot_device(0x%016llx)\n",
376 ioc->name, __func__,
377 (unsigned long long)sas_address));
378 ioc->req_alt_boot_device.device = device;
379 ioc->req_alt_boot_device.is_raid = is_raid;
380 }
381 }
382
383 if (!ioc->current_boot_device.device) {
384 if (_scsih_is_boot_device(sas_address, device_name,
385 enclosure_logical_id, slot,
386 (ioc->bios_pg2.CurrentBootDeviceForm &
387 MPI2_BIOSPAGE2_FORM_MASK),
388 &ioc->bios_pg2.CurrentBootDevice)) {
389 dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT
390 "%s: current_boot_device(0x%016llx)\n",
391 ioc->name, __func__,
392 (unsigned long long)sas_address));
393 ioc->current_boot_device.device = device;
394 ioc->current_boot_device.is_raid = is_raid;
395 }
396 }
397}
398
399/**
400 * mpt2sas_scsih_sas_device_find_by_sas_address - sas device search
401 * @ioc: per adapter object
402 * @sas_address: sas address
403 * Context: Calling function should acquire ioc->sas_device_lock
404 *
405 * This searches for sas_device based on sas_address, then return sas_device
406 * object.
407 */
408struct _sas_device *
409mpt2sas_scsih_sas_device_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
410 u64 sas_address)
411{
412 struct _sas_device *sas_device, *r;
413
414 r = NULL;
415 /* check the sas_device_init_list */
416 list_for_each_entry(sas_device, &ioc->sas_device_init_list,
417 list) {
418 if (sas_device->sas_address != sas_address)
419 continue;
420 r = sas_device;
421 goto out;
422 }
423
424 /* then check the sas_device_list */
425 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
426 if (sas_device->sas_address != sas_address)
427 continue;
428 r = sas_device;
429 goto out;
430 }
431 out:
432 return r;
433}
434
435/**
436 * _scsih_sas_device_find_by_handle - sas device search
437 * @ioc: per adapter object
438 * @handle: sas device handle (assigned by firmware)
439 * Context: Calling function should acquire ioc->sas_device_lock
440 *
441 * This searches for sas_device based on sas_address, then return sas_device
442 * object.
443 */
444static struct _sas_device *
445_scsih_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
446{
447 struct _sas_device *sas_device, *r;
448
449 r = NULL;
450 if (ioc->wait_for_port_enable_to_complete) {
451 list_for_each_entry(sas_device, &ioc->sas_device_init_list,
452 list) {
453 if (sas_device->handle != handle)
454 continue;
455 r = sas_device;
456 goto out;
457 }
458 } else {
459 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
460 if (sas_device->handle != handle)
461 continue;
462 r = sas_device;
463 goto out;
464 }
465 }
466
467 out:
468 return r;
469}
470
471/**
472 * _scsih_sas_device_remove - remove sas_device from list.
473 * @ioc: per adapter object
474 * @sas_device: the sas_device object
475 * Context: This function will acquire ioc->sas_device_lock.
476 *
477 * Removing object and freeing associated memory from the ioc->sas_device_list.
478 */
479static void
480_scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc,
481 struct _sas_device *sas_device)
482{
483 unsigned long flags;
484
485 spin_lock_irqsave(&ioc->sas_device_lock, flags);
486 list_del(&sas_device->list);
487 memset(sas_device, 0, sizeof(struct _sas_device));
488 kfree(sas_device);
489 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
490}
491
492/**
493 * _scsih_sas_device_add - insert sas_device to the list.
494 * @ioc: per adapter object
495 * @sas_device: the sas_device object
496 * Context: This function will acquire ioc->sas_device_lock.
497 *
498 * Adding new object to the ioc->sas_device_list.
499 */
500static void
501_scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
502 struct _sas_device *sas_device)
503{
504 unsigned long flags;
505 u16 handle, parent_handle;
506 u64 sas_address;
507
508 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle"
509 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
510 sas_device->handle, (unsigned long long)sas_device->sas_address));
511
512 spin_lock_irqsave(&ioc->sas_device_lock, flags);
513 list_add_tail(&sas_device->list, &ioc->sas_device_list);
514 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
515
516 handle = sas_device->handle;
517 parent_handle = sas_device->parent_handle;
518 sas_address = sas_device->sas_address;
519 if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) {
520 _scsih_sas_device_remove(ioc, sas_device);
521 } else if (!sas_device->starget) {
522 mpt2sas_transport_port_remove(ioc, sas_address, parent_handle);
523 _scsih_sas_device_remove(ioc, sas_device);
524 }
525}
526
527/**
528 * _scsih_sas_device_init_add - insert sas_device to the list.
529 * @ioc: per adapter object
530 * @sas_device: the sas_device object
531 * Context: This function will acquire ioc->sas_device_lock.
532 *
533 * Adding new object at driver load time to the ioc->sas_device_init_list.
534 */
535static void
536_scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
537 struct _sas_device *sas_device)
538{
539 unsigned long flags;
540
541 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle"
542 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
543 sas_device->handle, (unsigned long long)sas_device->sas_address));
544
545 spin_lock_irqsave(&ioc->sas_device_lock, flags);
546 list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
547 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
548 _scsih_determine_boot_device(ioc, sas_device, 0);
549}
550
551/**
552 * mpt2sas_scsih_expander_find_by_handle - expander device search
553 * @ioc: per adapter object
554 * @handle: expander handle (assigned by firmware)
555 * Context: Calling function should acquire ioc->sas_device_lock
556 *
557 * This searches for expander device based on handle, then returns the
558 * sas_node object.
559 */
560struct _sas_node *
561mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
562{
563 struct _sas_node *sas_expander, *r;
564
565 r = NULL;
566 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
567 if (sas_expander->handle != handle)
568 continue;
569 r = sas_expander;
570 goto out;
571 }
572 out:
573 return r;
574}
575
576/**
577 * _scsih_raid_device_find_by_id - raid device search
578 * @ioc: per adapter object
579 * @id: sas device target id
580 * @channel: sas device channel
581 * Context: Calling function should acquire ioc->raid_device_lock
582 *
583 * This searches for raid_device based on target id, then return raid_device
584 * object.
585 */
586static struct _raid_device *
587_scsih_raid_device_find_by_id(struct MPT2SAS_ADAPTER *ioc, int id, int channel)
588{
589 struct _raid_device *raid_device, *r;
590
591 r = NULL;
592 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
593 if (raid_device->id == id && raid_device->channel == channel) {
594 r = raid_device;
595 goto out;
596 }
597 }
598
599 out:
600 return r;
601}
602
603/**
604 * _scsih_raid_device_find_by_handle - raid device search
605 * @ioc: per adapter object
606 * @handle: sas device handle (assigned by firmware)
607 * Context: Calling function should acquire ioc->raid_device_lock
608 *
609 * This searches for raid_device based on handle, then return raid_device
610 * object.
611 */
612static struct _raid_device *
613_scsih_raid_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
614{
615 struct _raid_device *raid_device, *r;
616
617 r = NULL;
618 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
619 if (raid_device->handle != handle)
620 continue;
621 r = raid_device;
622 goto out;
623 }
624
625 out:
626 return r;
627}
628
629/**
630 * _scsih_raid_device_find_by_wwid - raid device search
631 * @ioc: per adapter object
632 * @handle: sas device handle (assigned by firmware)
633 * Context: Calling function should acquire ioc->raid_device_lock
634 *
635 * This searches for raid_device based on wwid, then return raid_device
636 * object.
637 */
638static struct _raid_device *
639_scsih_raid_device_find_by_wwid(struct MPT2SAS_ADAPTER *ioc, u64 wwid)
640{
641 struct _raid_device *raid_device, *r;
642
643 r = NULL;
644 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
645 if (raid_device->wwid != wwid)
646 continue;
647 r = raid_device;
648 goto out;
649 }
650
651 out:
652 return r;
653}
654
655/**
656 * _scsih_raid_device_add - add raid_device object
657 * @ioc: per adapter object
658 * @raid_device: raid_device object
659 *
660 * This is added to the raid_device_list link list.
661 */
662static void
663_scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc,
664 struct _raid_device *raid_device)
665{
666 unsigned long flags;
667
668 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle"
669 "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
670 raid_device->handle, (unsigned long long)raid_device->wwid));
671
672 spin_lock_irqsave(&ioc->raid_device_lock, flags);
673 list_add_tail(&raid_device->list, &ioc->raid_device_list);
674 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
675}
676
677/**
678 * _scsih_raid_device_remove - delete raid_device object
679 * @ioc: per adapter object
680 * @raid_device: raid_device object
681 *
682 * This is removed from the raid_device_list link list.
683 */
684static void
685_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
686 struct _raid_device *raid_device)
687{
688 unsigned long flags;
689
690 spin_lock_irqsave(&ioc->raid_device_lock, flags);
691 list_del(&raid_device->list);
692 memset(raid_device, 0, sizeof(struct _raid_device));
693 kfree(raid_device);
694 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
695}
696
697/**
698 * mpt2sas_scsih_expander_find_by_sas_address - expander device search
699 * @ioc: per adapter object
700 * @sas_address: sas address
701 * Context: Calling function should acquire ioc->sas_node_lock.
702 *
703 * This searches for expander device based on sas_address, then returns the
704 * sas_node object.
705 */
706struct _sas_node *
707mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
708 u64 sas_address)
709{
710 struct _sas_node *sas_expander, *r;
711
712 r = NULL;
713 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
714 if (sas_expander->sas_address != sas_address)
715 continue;
716 r = sas_expander;
717 goto out;
718 }
719 out:
720 return r;
721}
722
723/**
724 * _scsih_expander_node_add - insert expander device to the list.
725 * @ioc: per adapter object
726 * @sas_expander: the sas_device object
727 * Context: This function will acquire ioc->sas_node_lock.
728 *
729 * Adding new object to the ioc->sas_expander_list.
730 *
731 * Return nothing.
732 */
733static void
734_scsih_expander_node_add(struct MPT2SAS_ADAPTER *ioc,
735 struct _sas_node *sas_expander)
736{
737 unsigned long flags;
738
739 spin_lock_irqsave(&ioc->sas_node_lock, flags);
740 list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
741 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
742}
743
744/**
745 * _scsih_is_end_device - determines if device is an end device
746 * @device_info: bitfield providing information about the device.
747 * Context: none
748 *
749 * Returns 1 if end device.
750 */
751static int
752_scsih_is_end_device(u32 device_info)
753{
754 if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
755 ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
756 (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
757 (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
758 return 1;
759 else
760 return 0;
761}
762
763/**
764 * _scsih_scsi_lookup_get - returns scmd entry
765 * @ioc: per adapter object
766 * @smid: system request message index
767 * Context: This function will acquire ioc->scsi_lookup_lock.
768 *
769 * Returns the smid stored scmd pointer.
770 */
771static struct scsi_cmnd *
772_scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
773{
774 unsigned long flags;
775 struct scsi_cmnd *scmd;
776
777 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
778 scmd = ioc->scsi_lookup[smid - 1].scmd;
779 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
780 return scmd;
781}
782
783/**
784 * mptscsih_getclear_scsi_lookup - returns scmd entry
785 * @ioc: per adapter object
786 * @smid: system request message index
787 * Context: This function will acquire ioc->scsi_lookup_lock.
788 *
789 * Returns the smid stored scmd pointer, as well as clearing the scmd pointer.
790 */
791static struct scsi_cmnd *
792_scsih_scsi_lookup_getclear(struct MPT2SAS_ADAPTER *ioc, u16 smid)
793{
794 unsigned long flags;
795 struct scsi_cmnd *scmd;
796
797 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
798 scmd = ioc->scsi_lookup[smid - 1].scmd;
799 ioc->scsi_lookup[smid - 1].scmd = NULL;
800 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
801 return scmd;
802}
803
804/**
805 * _scsih_scsi_lookup_set - updates scmd entry in lookup
806 * @ioc: per adapter object
807 * @smid: system request message index
808 * @scmd: pointer to scsi command object
809 * Context: This function will acquire ioc->scsi_lookup_lock.
810 *
811 * This will save scmd pointer in the scsi_lookup array.
812 *
813 * Return nothing.
814 */
815static void
816_scsih_scsi_lookup_set(struct MPT2SAS_ADAPTER *ioc, u16 smid,
817 struct scsi_cmnd *scmd)
818{
819 unsigned long flags;
820
821 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
822 ioc->scsi_lookup[smid - 1].scmd = scmd;
823 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
824}
825
826/**
827 * _scsih_scsi_lookup_find_by_scmd - scmd lookup
828 * @ioc: per adapter object
829 * @smid: system request message index
830 * @scmd: pointer to scsi command object
831 * Context: This function will acquire ioc->scsi_lookup_lock.
832 *
833 * This will search for a scmd pointer in the scsi_lookup array,
834 * returning the revelent smid. A returned value of zero means invalid.
835 */
836static u16
837_scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd
838 *scmd)
839{
840 u16 smid;
841 unsigned long flags;
842 int i;
843
844 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
845 smid = 0;
846 for (i = 0; i < ioc->request_depth; i++) {
847 if (ioc->scsi_lookup[i].scmd == scmd) {
848 smid = i + 1;
849 goto out;
850 }
851 }
852 out:
853 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
854 return smid;
855}
856
857/**
858 * _scsih_scsi_lookup_find_by_target - search for matching channel:id
859 * @ioc: per adapter object
860 * @id: target id
861 * @channel: channel
862 * Context: This function will acquire ioc->scsi_lookup_lock.
863 *
864 * This will search for a matching channel:id in the scsi_lookup array,
865 * returning 1 if found.
866 */
867static u8
868_scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id,
869 int channel)
870{
871 u8 found;
872 unsigned long flags;
873 int i;
874
875 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
876 found = 0;
877 for (i = 0 ; i < ioc->request_depth; i++) {
878 if (ioc->scsi_lookup[i].scmd &&
879 (ioc->scsi_lookup[i].scmd->device->id == id &&
880 ioc->scsi_lookup[i].scmd->device->channel == channel)) {
881 found = 1;
882 goto out;
883 }
884 }
885 out:
886 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
887 return found;
888}
889
890/**
891 * _scsih_get_chain_buffer_dma - obtain block of chains (dma address)
892 * @ioc: per adapter object
893 * @smid: system request message index
894 *
895 * Returns phys pointer to chain buffer.
896 */
897static dma_addr_t
898_scsih_get_chain_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
899{
900 return ioc->chain_dma + ((smid - 1) * (ioc->request_sz *
901 ioc->chains_needed_per_io));
902}
903
904/**
905 * _scsih_get_chain_buffer - obtain block of chains assigned to a mf request
906 * @ioc: per adapter object
907 * @smid: system request message index
908 *
909 * Returns virt pointer to chain buffer.
910 */
911static void *
912_scsih_get_chain_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
913{
914 return (void *)(ioc->chain + ((smid - 1) * (ioc->request_sz *
915 ioc->chains_needed_per_io)));
916}
917
918/**
919 * _scsih_build_scatter_gather - main sg creation routine
920 * @ioc: per adapter object
921 * @scmd: scsi command
922 * @smid: system request message index
923 * Context: none.
924 *
925 * The main routine that builds scatter gather table from a given
926 * scsi request sent via the .queuecommand main handler.
927 *
928 * Returns 0 success, anything else error
929 */
930static int
931_scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
932 struct scsi_cmnd *scmd, u16 smid)
933{
934 Mpi2SCSIIORequest_t *mpi_request;
935 dma_addr_t chain_dma;
936 struct scatterlist *sg_scmd;
937 void *sg_local, *chain;
938 u32 chain_offset;
939 u32 chain_length;
940 u32 chain_flags;
941 u32 sges_left;
942 u32 sges_in_segment;
943 u32 sgl_flags;
944 u32 sgl_flags_last_element;
945 u32 sgl_flags_end_buffer;
946
947 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
948
949 /* init scatter gather flags */
950 sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT;
951 if (scmd->sc_data_direction == DMA_TO_DEVICE)
952 sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC;
953 sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT)
954 << MPI2_SGE_FLAGS_SHIFT;
955 sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT |
956 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST)
957 << MPI2_SGE_FLAGS_SHIFT;
958 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
959
960 sg_scmd = scsi_sglist(scmd);
961 sges_left = scsi_dma_map(scmd);
962 if (!sges_left) {
963 sdev_printk(KERN_ERR, scmd->device, "pci_map_sg"
964 " failed: request for %d bytes!\n", scsi_bufflen(scmd));
965 return -ENOMEM;
966 }
967
968 sg_local = &mpi_request->SGL;
969 sges_in_segment = ioc->max_sges_in_main_message;
970 if (sges_left <= sges_in_segment)
971 goto fill_in_last_segment;
972
973 mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) +
974 (sges_in_segment * ioc->sge_size))/4;
975
976 /* fill in main message segment when there is a chain following */
977 while (sges_in_segment) {
978 if (sges_in_segment == 1)
979 ioc->base_add_sg_single(sg_local,
980 sgl_flags_last_element | sg_dma_len(sg_scmd),
981 sg_dma_address(sg_scmd));
982 else
983 ioc->base_add_sg_single(sg_local, sgl_flags |
984 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
985 sg_scmd = sg_next(sg_scmd);
986 sg_local += ioc->sge_size;
987 sges_left--;
988 sges_in_segment--;
989 }
990
991 /* initializing the chain flags and pointers */
992 chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
993 chain = _scsih_get_chain_buffer(ioc, smid);
994 chain_dma = _scsih_get_chain_buffer_dma(ioc, smid);
995 do {
996 sges_in_segment = (sges_left <=
997 ioc->max_sges_in_chain_message) ? sges_left :
998 ioc->max_sges_in_chain_message;
999 chain_offset = (sges_left == sges_in_segment) ?
1000 0 : (sges_in_segment * ioc->sge_size)/4;
1001 chain_length = sges_in_segment * ioc->sge_size;
1002 if (chain_offset) {
1003 chain_offset = chain_offset <<
1004 MPI2_SGE_CHAIN_OFFSET_SHIFT;
1005 chain_length += ioc->sge_size;
1006 }
1007 ioc->base_add_sg_single(sg_local, chain_flags | chain_offset |
1008 chain_length, chain_dma);
1009 sg_local = chain;
1010 if (!chain_offset)
1011 goto fill_in_last_segment;
1012
1013 /* fill in chain segments */
1014 while (sges_in_segment) {
1015 if (sges_in_segment == 1)
1016 ioc->base_add_sg_single(sg_local,
1017 sgl_flags_last_element |
1018 sg_dma_len(sg_scmd),
1019 sg_dma_address(sg_scmd));
1020 else
1021 ioc->base_add_sg_single(sg_local, sgl_flags |
1022 sg_dma_len(sg_scmd),
1023 sg_dma_address(sg_scmd));
1024 sg_scmd = sg_next(sg_scmd);
1025 sg_local += ioc->sge_size;
1026 sges_left--;
1027 sges_in_segment--;
1028 }
1029
1030 chain_dma += ioc->request_sz;
1031 chain += ioc->request_sz;
1032 } while (1);
1033
1034
1035 fill_in_last_segment:
1036
1037 /* fill the last segment */
1038 while (sges_left) {
1039 if (sges_left == 1)
1040 ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer |
1041 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1042 else
1043 ioc->base_add_sg_single(sg_local, sgl_flags |
1044 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1045 sg_scmd = sg_next(sg_scmd);
1046 sg_local += ioc->sge_size;
1047 sges_left--;
1048 }
1049
1050 return 0;
1051}
1052
1053/**
1054 * scsih_change_queue_depth - setting device queue depth
1055 * @sdev: scsi device struct
1056 * @qdepth: requested queue depth
1057 *
1058 * Returns queue depth.
1059 */
1060static int
1061scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
1062{
1063 struct Scsi_Host *shost = sdev->host;
1064 int max_depth;
1065 int tag_type;
1066
1067 max_depth = shost->can_queue;
1068 if (!sdev->tagged_supported)
1069 max_depth = 1;
1070 if (qdepth > max_depth)
1071 qdepth = max_depth;
1072 tag_type = (qdepth == 1) ? 0 : MSG_SIMPLE_TAG;
1073 scsi_adjust_queue_depth(sdev, tag_type, qdepth);
1074
1075 if (sdev->inquiry_len > 7)
1076 sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
1077 "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
1078 sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
1079 sdev->ordered_tags, sdev->scsi_level,
1080 (sdev->inquiry[7] & 2) >> 1);
1081
1082 return sdev->queue_depth;
1083}
1084
1085/**
1086 * scsih_change_queue_depth - changing device queue tag type
1087 * @sdev: scsi device struct
1088 * @tag_type: requested tag type
1089 *
1090 * Returns queue tag type.
1091 */
1092static int
1093scsih_change_queue_type(struct scsi_device *sdev, int tag_type)
1094{
1095 if (sdev->tagged_supported) {
1096 scsi_set_tag_type(sdev, tag_type);
1097 if (tag_type)
1098 scsi_activate_tcq(sdev, sdev->queue_depth);
1099 else
1100 scsi_deactivate_tcq(sdev, sdev->queue_depth);
1101 } else
1102 tag_type = 0;
1103
1104 return tag_type;
1105}
1106
1107/**
1108 * scsih_target_alloc - target add routine
1109 * @starget: scsi target struct
1110 *
1111 * Returns 0 if ok. Any other return is assumed to be an error and
1112 * the device is ignored.
1113 */
1114static int
1115scsih_target_alloc(struct scsi_target *starget)
1116{
1117 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1118 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1119 struct MPT2SAS_TARGET *sas_target_priv_data;
1120 struct _sas_device *sas_device;
1121 struct _raid_device *raid_device;
1122 unsigned long flags;
1123 struct sas_rphy *rphy;
1124
1125 sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
1126 if (!sas_target_priv_data)
1127 return -ENOMEM;
1128
1129 starget->hostdata = sas_target_priv_data;
1130 sas_target_priv_data->starget = starget;
1131 sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
1132
1133 /* RAID volumes */
1134 if (starget->channel == RAID_CHANNEL) {
1135 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1136 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1137 starget->channel);
1138 if (raid_device) {
1139 sas_target_priv_data->handle = raid_device->handle;
1140 sas_target_priv_data->sas_address = raid_device->wwid;
1141 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
1142 raid_device->starget = starget;
1143 }
1144 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1145 return 0;
1146 }
1147
1148 /* sas/sata devices */
1149 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1150 rphy = dev_to_rphy(starget->dev.parent);
1151 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1152 rphy->identify.sas_address);
1153
1154 if (sas_device) {
1155 sas_target_priv_data->handle = sas_device->handle;
1156 sas_target_priv_data->sas_address = sas_device->sas_address;
1157 sas_device->starget = starget;
1158 sas_device->id = starget->id;
1159 sas_device->channel = starget->channel;
1160 if (sas_device->hidden_raid_component)
1161 sas_target_priv_data->flags |=
1162 MPT_TARGET_FLAGS_RAID_COMPONENT;
1163 }
1164 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1165
1166 return 0;
1167}
1168
1169/**
1170 * scsih_target_destroy - target destroy routine
1171 * @starget: scsi target struct
1172 *
1173 * Returns nothing.
1174 */
1175static void
1176scsih_target_destroy(struct scsi_target *starget)
1177{
1178 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1179 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1180 struct MPT2SAS_TARGET *sas_target_priv_data;
1181 struct _sas_device *sas_device;
1182 struct _raid_device *raid_device;
1183 unsigned long flags;
1184 struct sas_rphy *rphy;
1185
1186 sas_target_priv_data = starget->hostdata;
1187 if (!sas_target_priv_data)
1188 return;
1189
1190 if (starget->channel == RAID_CHANNEL) {
1191 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1192 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1193 starget->channel);
1194 if (raid_device) {
1195 raid_device->starget = NULL;
1196 raid_device->sdev = NULL;
1197 }
1198 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1199 goto out;
1200 }
1201
1202 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1203 rphy = dev_to_rphy(starget->dev.parent);
1204 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1205 rphy->identify.sas_address);
1206 if (sas_device)
1207 sas_device->starget = NULL;
1208
1209 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1210
1211 out:
1212 kfree(sas_target_priv_data);
1213 starget->hostdata = NULL;
1214}
1215
1216/**
1217 * scsih_slave_alloc - device add routine
1218 * @sdev: scsi device struct
1219 *
1220 * Returns 0 if ok. Any other return is assumed to be an error and
1221 * the device is ignored.
1222 */
1223static int
1224scsih_slave_alloc(struct scsi_device *sdev)
1225{
1226 struct Scsi_Host *shost;
1227 struct MPT2SAS_ADAPTER *ioc;
1228 struct MPT2SAS_TARGET *sas_target_priv_data;
1229 struct MPT2SAS_DEVICE *sas_device_priv_data;
1230 struct scsi_target *starget;
1231 struct _raid_device *raid_device;
1232 struct _sas_device *sas_device;
1233 unsigned long flags;
1234
1235 sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
1236 if (!sas_device_priv_data)
1237 return -ENOMEM;
1238
1239 sas_device_priv_data->lun = sdev->lun;
1240 sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
1241
1242 starget = scsi_target(sdev);
1243 sas_target_priv_data = starget->hostdata;
1244 sas_target_priv_data->num_luns++;
1245 sas_device_priv_data->sas_target = sas_target_priv_data;
1246 sdev->hostdata = sas_device_priv_data;
1247 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
1248 sdev->no_uld_attach = 1;
1249
1250 shost = dev_to_shost(&starget->dev);
1251 ioc = shost_priv(shost);
1252 if (starget->channel == RAID_CHANNEL) {
1253 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1254 raid_device = _scsih_raid_device_find_by_id(ioc,
1255 starget->id, starget->channel);
1256 if (raid_device)
1257 raid_device->sdev = sdev; /* raid is single lun */
1258 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1259 } else {
1260 /* set TLR bit for SSP devices */
1261 if (!(ioc->facts.IOCCapabilities &
1262 MPI2_IOCFACTS_CAPABILITY_TLR))
1263 goto out;
1264 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1265 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1266 sas_device_priv_data->sas_target->sas_address);
1267 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1268 if (sas_device && sas_device->device_info &
1269 MPI2_SAS_DEVICE_INFO_SSP_TARGET)
1270 sas_device_priv_data->flags |= MPT_DEVICE_TLR_ON;
1271 }
1272
1273 out:
1274 return 0;
1275}
1276
1277/**
1278 * scsih_slave_destroy - device destroy routine
1279 * @sdev: scsi device struct
1280 *
1281 * Returns nothing.
1282 */
1283static void
1284scsih_slave_destroy(struct scsi_device *sdev)
1285{
1286 struct MPT2SAS_TARGET *sas_target_priv_data;
1287 struct scsi_target *starget;
1288
1289 if (!sdev->hostdata)
1290 return;
1291
1292 starget = scsi_target(sdev);
1293 sas_target_priv_data = starget->hostdata;
1294 sas_target_priv_data->num_luns--;
1295 kfree(sdev->hostdata);
1296 sdev->hostdata = NULL;
1297}
1298
1299/**
1300 * scsih_display_sata_capabilities - sata capabilities
1301 * @ioc: per adapter object
1302 * @sas_device: the sas_device object
1303 * @sdev: scsi device struct
1304 */
1305static void
1306scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
1307 struct _sas_device *sas_device, struct scsi_device *sdev)
1308{
1309 Mpi2ConfigReply_t mpi_reply;
1310 Mpi2SasDevicePage0_t sas_device_pg0;
1311 u32 ioc_status;
1312 u16 flags;
1313 u32 device_info;
1314
1315 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
1316 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, sas_device->handle))) {
1317 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1318 ioc->name, __FILE__, __LINE__, __func__);
1319 return;
1320 }
1321
1322 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1323 MPI2_IOCSTATUS_MASK;
1324 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1325 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1326 ioc->name, __FILE__, __LINE__, __func__);
1327 return;
1328 }
1329
1330 flags = le16_to_cpu(sas_device_pg0.Flags);
1331 device_info = le16_to_cpu(sas_device_pg0.DeviceInfo);
1332
1333 sdev_printk(KERN_INFO, sdev,
1334 "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
1335 "sw_preserve(%s)\n",
1336 (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
1337 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
1338 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
1339 "n",
1340 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
1341 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
1342 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
1343}
1344
1345/**
1346 * _scsih_get_volume_capabilities - volume capabilities
1347 * @ioc: per adapter object
1348 * @sas_device: the raid_device object
1349 */
1350static void
1351_scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
1352 struct _raid_device *raid_device)
1353{
1354 Mpi2RaidVolPage0_t *vol_pg0;
1355 Mpi2RaidPhysDiskPage0_t pd_pg0;
1356 Mpi2SasDevicePage0_t sas_device_pg0;
1357 Mpi2ConfigReply_t mpi_reply;
1358 u16 sz;
1359 u8 num_pds;
1360
1361 if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
1362 &num_pds)) || !num_pds) {
1363 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1364 ioc->name, __FILE__, __LINE__, __func__);
1365 return;
1366 }
1367
1368 raid_device->num_pds = num_pds;
1369 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1370 sizeof(Mpi2RaidVol0PhysDisk_t));
1371 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1372 if (!vol_pg0) {
1373 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1374 ioc->name, __FILE__, __LINE__, __func__);
1375 return;
1376 }
1377
1378 if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1379 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
1380 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1381 ioc->name, __FILE__, __LINE__, __func__);
1382 kfree(vol_pg0);
1383 return;
1384 }
1385
1386 raid_device->volume_type = vol_pg0->VolumeType;
1387
1388 /* figure out what the underlying devices are by
1389 * obtaining the device_info bits for the 1st device
1390 */
1391 if (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1392 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1393 vol_pg0->PhysDisk[0].PhysDiskNum))) {
1394 if (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
1395 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1396 le16_to_cpu(pd_pg0.DevHandle)))) {
1397 raid_device->device_info =
1398 le32_to_cpu(sas_device_pg0.DeviceInfo);
1399 }
1400 }
1401
1402 kfree(vol_pg0);
1403}
1404
1405/**
1406 * scsih_slave_configure - device configure routine.
1407 * @sdev: scsi device struct
1408 *
1409 * Returns 0 if ok. Any other return is assumed to be an error and
1410 * the device is ignored.
1411 */
1412static int
1413scsih_slave_configure(struct scsi_device *sdev)
1414{
1415 struct Scsi_Host *shost = sdev->host;
1416 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1417 struct MPT2SAS_DEVICE *sas_device_priv_data;
1418 struct MPT2SAS_TARGET *sas_target_priv_data;
1419 struct _sas_device *sas_device;
1420 struct _raid_device *raid_device;
1421 unsigned long flags;
1422 int qdepth;
1423 u8 ssp_target = 0;
1424 char *ds = "";
1425 char *r_level = "";
1426
1427 qdepth = 1;
1428 sas_device_priv_data = sdev->hostdata;
1429 sas_device_priv_data->configured_lun = 1;
1430 sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
1431 sas_target_priv_data = sas_device_priv_data->sas_target;
1432
1433 /* raid volume handling */
1434 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
1435
1436 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1437 raid_device = _scsih_raid_device_find_by_handle(ioc,
1438 sas_target_priv_data->handle);
1439 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1440 if (!raid_device) {
1441 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1442 ioc->name, __FILE__, __LINE__, __func__);
1443 return 0;
1444 }
1445
1446 _scsih_get_volume_capabilities(ioc, raid_device);
1447
1448 /* RAID Queue Depth Support
1449 * IS volume = underlying qdepth of drive type, either
1450 * MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH
1451 * IM/IME/R10 = 128 (MPT2SAS_RAID_QUEUE_DEPTH)
1452 */
1453 if (raid_device->device_info &
1454 MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1455 qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
1456 ds = "SSP";
1457 } else {
1458 qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
1459 if (raid_device->device_info &
1460 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1461 ds = "SATA";
1462 else
1463 ds = "STP";
1464 }
1465
1466 switch (raid_device->volume_type) {
1467 case MPI2_RAID_VOL_TYPE_RAID0:
1468 r_level = "RAID0";
1469 break;
1470 case MPI2_RAID_VOL_TYPE_RAID1E:
1471 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
1472 r_level = "RAID1E";
1473 break;
1474 case MPI2_RAID_VOL_TYPE_RAID1:
1475 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
1476 r_level = "RAID1";
1477 break;
1478 case MPI2_RAID_VOL_TYPE_RAID10:
1479 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
1480 r_level = "RAID10";
1481 break;
1482 case MPI2_RAID_VOL_TYPE_UNKNOWN:
1483 default:
1484 qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
1485 r_level = "RAIDX";
1486 break;
1487 }
1488
1489 sdev_printk(KERN_INFO, sdev, "%s: "
1490 "handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n",
1491 r_level, raid_device->handle,
1492 (unsigned long long)raid_device->wwid,
1493 raid_device->num_pds, ds);
1494 scsih_change_queue_depth(sdev, qdepth);
1495 return 0;
1496 }
1497
1498 /* non-raid handling */
1499 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1500 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1501 sas_device_priv_data->sas_target->sas_address);
1502 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1503 if (sas_device) {
1504 if (sas_target_priv_data->flags &
1505 MPT_TARGET_FLAGS_RAID_COMPONENT) {
1506 mpt2sas_config_get_volume_handle(ioc,
1507 sas_device->handle, &sas_device->volume_handle);
1508 mpt2sas_config_get_volume_wwid(ioc,
1509 sas_device->volume_handle,
1510 &sas_device->volume_wwid);
1511 }
1512 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1513 qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
1514 ssp_target = 1;
1515 ds = "SSP";
1516 } else {
1517 qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
1518 if (sas_device->device_info &
1519 MPI2_SAS_DEVICE_INFO_STP_TARGET)
1520 ds = "STP";
1521 else if (sas_device->device_info &
1522 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1523 ds = "SATA";
1524 }
1525
1526 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
1527 "sas_addr(0x%016llx), device_name(0x%016llx)\n",
1528 ds, sas_device->handle,
1529 (unsigned long long)sas_device->sas_address,
1530 (unsigned long long)sas_device->device_name);
1531 sdev_printk(KERN_INFO, sdev, "%s: "
1532 "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
1533 (unsigned long long) sas_device->enclosure_logical_id,
1534 sas_device->slot);
1535
1536 if (!ssp_target)
1537 scsih_display_sata_capabilities(ioc, sas_device, sdev);
1538 }
1539
1540 scsih_change_queue_depth(sdev, qdepth);
1541
1542 if (ssp_target)
1543 sas_read_port_mode_page(sdev);
1544 return 0;
1545}
1546
1547/**
1548 * scsih_bios_param - fetch head, sector, cylinder info for a disk
1549 * @sdev: scsi device struct
1550 * @bdev: pointer to block device context
1551 * @capacity: device size (in 512 byte sectors)
1552 * @params: three element array to place output:
1553 * params[0] number of heads (max 255)
1554 * params[1] number of sectors (max 63)
1555 * params[2] number of cylinders
1556 *
1557 * Return nothing.
1558 */
1559static int
1560scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
1561 sector_t capacity, int params[])
1562{
1563 int heads;
1564 int sectors;
1565 sector_t cylinders;
1566 ulong dummy;
1567
1568 heads = 64;
1569 sectors = 32;
1570
1571 dummy = heads * sectors;
1572 cylinders = capacity;
1573 sector_div(cylinders, dummy);
1574
1575 /*
1576 * Handle extended translation size for logical drives
1577 * > 1Gb
1578 */
1579 if ((ulong)capacity >= 0x200000) {
1580 heads = 255;
1581 sectors = 63;
1582 dummy = heads * sectors;
1583 cylinders = capacity;
1584 sector_div(cylinders, dummy);
1585 }
1586
1587 /* return result */
1588 params[0] = heads;
1589 params[1] = sectors;
1590 params[2] = cylinders;
1591
1592 return 0;
1593}
1594
1595/**
1596 * _scsih_response_code - translation of device response code
1597 * @ioc: per adapter object
1598 * @response_code: response code returned by the device
1599 *
1600 * Return nothing.
1601 */
1602static void
1603_scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code)
1604{
1605 char *desc;
1606
1607 switch (response_code) {
1608 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
1609 desc = "task management request completed";
1610 break;
1611 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
1612 desc = "invalid frame";
1613 break;
1614 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
1615 desc = "task management request not supported";
1616 break;
1617 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
1618 desc = "task management request failed";
1619 break;
1620 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
1621 desc = "task management request succeeded";
1622 break;
1623 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
1624 desc = "invalid lun";
1625 break;
1626 case 0xA:
1627 desc = "overlapped tag attempted";
1628 break;
1629 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
1630 desc = "task queued, however not sent to target";
1631 break;
1632 default:
1633 desc = "unknown";
1634 break;
1635 }
1636 printk(MPT2SAS_WARN_FMT "response_code(0x%01x): %s\n",
1637 ioc->name, response_code, desc);
1638}
1639
1640/**
1641 * scsih_tm_done - tm completion routine
1642 * @ioc: per adapter object
1643 * @smid: system request message index
1644 * @VF_ID: virtual function id
1645 * @reply: reply message frame(lower 32bit addr)
1646 * Context: none.
1647 *
1648 * The callback handler when using scsih_issue_tm.
1649 *
1650 * Return nothing.
1651 */
1652static void
1653scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
1654{
1655 MPI2DefaultReply_t *mpi_reply;
1656
1657 if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED)
1658 return;
1659 if (ioc->tm_cmds.smid != smid)
1660 return;
1661 ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
1662 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
1663 if (mpi_reply) {
1664 memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
1665 ioc->tm_cmds.status |= MPT2_CMD_REPLY_VALID;
1666 }
1667 ioc->tm_cmds.status &= ~MPT2_CMD_PENDING;
1668 complete(&ioc->tm_cmds.done);
1669}
1670
1671/**
1672 * mpt2sas_scsih_set_tm_flag - set per target tm_busy
1673 * @ioc: per adapter object
1674 * @handle: device handle
1675 *
1676 * During taskmangement request, we need to freeze the device queue.
1677 */
1678void
1679mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
1680{
1681 struct MPT2SAS_DEVICE *sas_device_priv_data;
1682 struct scsi_device *sdev;
1683 u8 skip = 0;
1684
1685 shost_for_each_device(sdev, ioc->shost) {
1686 if (skip)
1687 continue;
1688 sas_device_priv_data = sdev->hostdata;
1689 if (!sas_device_priv_data)
1690 continue;
1691 if (sas_device_priv_data->sas_target->handle == handle) {
1692 sas_device_priv_data->sas_target->tm_busy = 1;
1693 skip = 1;
1694 ioc->ignore_loginfos = 1;
1695 }
1696 }
1697}
1698
1699/**
1700 * mpt2sas_scsih_clear_tm_flag - clear per target tm_busy
1701 * @ioc: per adapter object
1702 * @handle: device handle
1703 *
1704 * During taskmangement request, we need to freeze the device queue.
1705 */
1706void
1707mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
1708{
1709 struct MPT2SAS_DEVICE *sas_device_priv_data;
1710 struct scsi_device *sdev;
1711 u8 skip = 0;
1712
1713 shost_for_each_device(sdev, ioc->shost) {
1714 if (skip)
1715 continue;
1716 sas_device_priv_data = sdev->hostdata;
1717 if (!sas_device_priv_data)
1718 continue;
1719 if (sas_device_priv_data->sas_target->handle == handle) {
1720 sas_device_priv_data->sas_target->tm_busy = 0;
1721 skip = 1;
1722 ioc->ignore_loginfos = 0;
1723 }
1724 }
1725}
1726
1727/**
1728 * mpt2sas_scsih_issue_tm - main routine for sending tm requests
1729 * @ioc: per adapter struct
1730 * @device_handle: device handle
1731 * @lun: lun number
1732 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
1733 * @smid_task: smid assigned to the task
1734 * @timeout: timeout in seconds
1735 * Context: The calling function needs to acquire the tm_cmds.mutex
1736 *
1737 * A generic API for sending task management requests to firmware.
1738 *
1739 * The ioc->tm_cmds.status flag should be MPT2_CMD_NOT_USED before calling
1740 * this API.
1741 *
1742 * The callback index is set inside `ioc->tm_cb_idx`.
1743 *
1744 * Return nothing.
1745 */
1746void
1747mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
1748 u8 type, u16 smid_task, ulong timeout)
1749{
1750 Mpi2SCSITaskManagementRequest_t *mpi_request;
1751 Mpi2SCSITaskManagementReply_t *mpi_reply;
1752 u16 smid = 0;
1753 u32 ioc_state;
1754 unsigned long timeleft;
1755 u8 VF_ID = 0;
1756 unsigned long flags;
1757
1758 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
1759 if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED ||
1760 ioc->shost_recovery) {
1761 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
1762 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1763 __func__, ioc->name);
1764 return;
1765 }
1766 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
1767
1768 ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
1769 if (ioc_state & MPI2_DOORBELL_USED) {
1770 dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell "
1771 "active!\n", ioc->name));
1772 goto issue_host_reset;
1773 }
1774
1775 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
1776 mpt2sas_base_fault_info(ioc, ioc_state &
1777 MPI2_DOORBELL_DATA_MASK);
1778 goto issue_host_reset;
1779 }
1780
1781 smid = mpt2sas_base_get_smid(ioc, ioc->tm_cb_idx);
1782 if (!smid) {
1783 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1784 ioc->name, __func__);
1785 return;
1786 }
1787
1788 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
1789 " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, smid));
1790 ioc->tm_cmds.status = MPT2_CMD_PENDING;
1791 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1792 ioc->tm_cmds.smid = smid;
1793 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
1794 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
1795 mpi_request->DevHandle = cpu_to_le16(handle);
1796 mpi_request->TaskType = type;
1797 mpi_request->TaskMID = cpu_to_le16(smid_task);
1798 int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
1799 mpt2sas_scsih_set_tm_flag(ioc, handle);
1800 mpt2sas_base_put_smid_hi_priority(ioc, smid, VF_ID);
1801 timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
1802 mpt2sas_scsih_clear_tm_flag(ioc, handle);
1803 if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) {
1804 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1805 ioc->name, __func__);
1806 _debug_dump_mf(mpi_request,
1807 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
1808 if (!(ioc->tm_cmds.status & MPT2_CMD_RESET))
1809 goto issue_host_reset;
1810 }
1811
1812 if (ioc->tm_cmds.status & MPT2_CMD_REPLY_VALID) {
1813 mpi_reply = ioc->tm_cmds.reply;
1814 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "complete tm: "
1815 "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
1816 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
1817 le32_to_cpu(mpi_reply->IOCLogInfo),
1818 le32_to_cpu(mpi_reply->TerminationCount)));
1819 if (ioc->logging_level & MPT_DEBUG_TM)
1820 _scsih_response_code(ioc, mpi_reply->ResponseCode);
1821 }
1822 return;
1823 issue_host_reset:
1824 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER);
1825}
1826
1827/**
1828 * scsih_abort - eh threads main abort routine
1829 * @sdev: scsi device struct
1830 *
1831 * Returns SUCCESS if command aborted else FAILED
1832 */
1833static int
1834scsih_abort(struct scsi_cmnd *scmd)
1835{
1836 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
1837 struct MPT2SAS_DEVICE *sas_device_priv_data;
1838 u16 smid;
1839 u16 handle;
1840 int r;
1841 struct scsi_cmnd *scmd_lookup;
1842
1843 printk(MPT2SAS_INFO_FMT "attempting task abort! scmd(%p)\n",
1844 ioc->name, scmd);
1845 scsi_print_command(scmd);
1846
1847 sas_device_priv_data = scmd->device->hostdata;
1848 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
1849 printk(MPT2SAS_INFO_FMT "device been deleted! scmd(%p)\n",
1850 ioc->name, scmd);
1851 scmd->result = DID_NO_CONNECT << 16;
1852 scmd->scsi_done(scmd);
1853 r = SUCCESS;
1854 goto out;
1855 }
1856
1857 /* search for the command */
1858 smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
1859 if (!smid) {
1860 scmd->result = DID_RESET << 16;
1861 r = SUCCESS;
1862 goto out;
1863 }
1864
1865 /* for hidden raid components and volumes this is not supported */
1866 if (sas_device_priv_data->sas_target->flags &
1867 MPT_TARGET_FLAGS_RAID_COMPONENT ||
1868 sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
1869 scmd->result = DID_RESET << 16;
1870 r = FAILED;
1871 goto out;
1872 }
1873
1874 mutex_lock(&ioc->tm_cmds.mutex);
1875 handle = sas_device_priv_data->sas_target->handle;
1876 mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun,
1877 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30);
1878
1879 /* sanity check - see whether command actually completed */
1880 scmd_lookup = _scsih_scsi_lookup_get(ioc, smid);
1881 if (scmd_lookup && (scmd_lookup->serial_number == scmd->serial_number))
1882 r = FAILED;
1883 else
1884 r = SUCCESS;
1885 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
1886 mutex_unlock(&ioc->tm_cmds.mutex);
1887
1888 out:
1889 printk(MPT2SAS_INFO_FMT "task abort: %s scmd(%p)\n",
1890 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
1891 return r;
1892}
1893
1894
1895/**
1896 * scsih_dev_reset - eh threads main device reset routine
1897 * @sdev: scsi device struct
1898 *
1899 * Returns SUCCESS if command aborted else FAILED
1900 */
1901static int
1902scsih_dev_reset(struct scsi_cmnd *scmd)
1903{
1904 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
1905 struct MPT2SAS_DEVICE *sas_device_priv_data;
1906 struct _sas_device *sas_device;
1907 unsigned long flags;
1908 u16 handle;
1909 int r;
1910
1911 printk(MPT2SAS_INFO_FMT "attempting target reset! scmd(%p)\n",
1912 ioc->name, scmd);
1913 scsi_print_command(scmd);
1914
1915 sas_device_priv_data = scmd->device->hostdata;
1916 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
1917 printk(MPT2SAS_INFO_FMT "device been deleted! scmd(%p)\n",
1918 ioc->name, scmd);
1919 scmd->result = DID_NO_CONNECT << 16;
1920 scmd->scsi_done(scmd);
1921 r = SUCCESS;
1922 goto out;
1923 }
1924
1925 /* for hidden raid components obtain the volume_handle */
1926 handle = 0;
1927 if (sas_device_priv_data->sas_target->flags &
1928 MPT_TARGET_FLAGS_RAID_COMPONENT) {
1929 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1930 sas_device = _scsih_sas_device_find_by_handle(ioc,
1931 sas_device_priv_data->sas_target->handle);
1932 if (sas_device)
1933 handle = sas_device->volume_handle;
1934 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1935 } else
1936 handle = sas_device_priv_data->sas_target->handle;
1937
1938 if (!handle) {
1939 scmd->result = DID_RESET << 16;
1940 r = FAILED;
1941 goto out;
1942 }
1943
1944 mutex_lock(&ioc->tm_cmds.mutex);
1945 mpt2sas_scsih_issue_tm(ioc, handle, 0,
1946 MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30);
1947
1948 /*
1949 * sanity check see whether all commands to this target been
1950 * completed
1951 */
1952 if (_scsih_scsi_lookup_find_by_target(ioc, scmd->device->id,
1953 scmd->device->channel))
1954 r = FAILED;
1955 else
1956 r = SUCCESS;
1957 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
1958 mutex_unlock(&ioc->tm_cmds.mutex);
1959
1960 out:
1961 printk(MPT2SAS_INFO_FMT "target reset: %s scmd(%p)\n",
1962 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
1963 return r;
1964}
1965
1966/**
1967 * scsih_abort - eh threads main host reset routine
1968 * @sdev: scsi device struct
1969 *
1970 * Returns SUCCESS if command aborted else FAILED
1971 */
1972static int
1973scsih_host_reset(struct scsi_cmnd *scmd)
1974{
1975 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
1976 int r, retval;
1977
1978 printk(MPT2SAS_INFO_FMT "attempting host reset! scmd(%p)\n",
1979 ioc->name, scmd);
1980 scsi_print_command(scmd);
1981
1982 retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1983 FORCE_BIG_HAMMER);
1984 r = (retval < 0) ? FAILED : SUCCESS;
1985 printk(MPT2SAS_INFO_FMT "host reset: %s scmd(%p)\n",
1986 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
1987
1988 return r;
1989}
1990
1991/**
1992 * _scsih_fw_event_add - insert and queue up fw_event
1993 * @ioc: per adapter object
1994 * @fw_event: object describing the event
1995 * Context: This function will acquire ioc->fw_event_lock.
1996 *
1997 * This adds the firmware event object into link list, then queues it up to
1998 * be processed from user context.
1999 *
2000 * Return nothing.
2001 */
2002static void
2003_scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
2004{
2005 unsigned long flags;
2006
2007 if (ioc->firmware_event_thread == NULL)
2008 return;
2009
2010 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2011 list_add_tail(&fw_event->list, &ioc->fw_event_list);
2012 INIT_DELAYED_WORK(&fw_event->work, _firmware_event_work);
2013 queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, 1);
2014 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2015}
2016
2017/**
2018 * _scsih_fw_event_free - delete fw_event
2019 * @ioc: per adapter object
2020 * @fw_event: object describing the event
2021 * Context: This function will acquire ioc->fw_event_lock.
2022 *
2023 * This removes firmware event object from link list, frees associated memory.
2024 *
2025 * Return nothing.
2026 */
2027static void
2028_scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
2029 *fw_event)
2030{
2031 unsigned long flags;
2032
2033 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2034 list_del(&fw_event->list);
2035 kfree(fw_event->event_data);
2036 kfree(fw_event);
2037 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2038}
2039
2040/**
2041 * _scsih_fw_event_add - requeue an event
2042 * @ioc: per adapter object
2043 * @fw_event: object describing the event
2044 * Context: This function will acquire ioc->fw_event_lock.
2045 *
2046 * Return nothing.
2047 */
2048static void
2049_scsih_fw_event_requeue(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
2050 *fw_event, unsigned long delay)
2051{
2052 unsigned long flags;
2053 if (ioc->firmware_event_thread == NULL)
2054 return;
2055
2056 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2057 queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, delay);
2058 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2059}
2060
2061/**
2062 * _scsih_fw_event_off - turn flag off preventing event handling
2063 * @ioc: per adapter object
2064 *
2065 * Used to prevent handling of firmware events during adapter reset
2066 * driver unload.
2067 *
2068 * Return nothing.
2069 */
2070static void
2071_scsih_fw_event_off(struct MPT2SAS_ADAPTER *ioc)
2072{
2073 unsigned long flags;
2074
2075 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2076 ioc->fw_events_off = 1;
2077 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2078
2079}
2080
2081/**
2082 * _scsih_fw_event_on - turn flag on allowing firmware event handling
2083 * @ioc: per adapter object
2084 *
2085 * Returns nothing.
2086 */
2087static void
2088_scsih_fw_event_on(struct MPT2SAS_ADAPTER *ioc)
2089{
2090 unsigned long flags;
2091
2092 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2093 ioc->fw_events_off = 0;
2094 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2095}
2096
2097/**
2098 * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
2099 * @ioc: per adapter object
2100 * @handle: device handle
2101 *
2102 * During device pull we need to appropiately set the sdev state.
2103 */
2104static void
2105_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2106{
2107 struct MPT2SAS_DEVICE *sas_device_priv_data;
2108 struct scsi_device *sdev;
2109
2110 shost_for_each_device(sdev, ioc->shost) {
2111 sas_device_priv_data = sdev->hostdata;
2112 if (!sas_device_priv_data)
2113 continue;
2114 if (!sas_device_priv_data->block)
2115 continue;
2116 if (sas_device_priv_data->sas_target->handle == handle) {
2117 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2118 MPT2SAS_INFO_FMT "SDEV_RUNNING: "
2119 "handle(0x%04x)\n", ioc->name, handle));
2120 sas_device_priv_data->block = 0;
2121 scsi_device_set_state(sdev, SDEV_RUNNING);
2122 }
2123 }
2124}
2125
2126/**
2127 * _scsih_block_io_device - set the device state to SDEV_BLOCK
2128 * @ioc: per adapter object
2129 * @handle: device handle
2130 *
2131 * During device pull we need to appropiately set the sdev state.
2132 */
2133static void
2134_scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2135{
2136 struct MPT2SAS_DEVICE *sas_device_priv_data;
2137 struct scsi_device *sdev;
2138
2139 shost_for_each_device(sdev, ioc->shost) {
2140 sas_device_priv_data = sdev->hostdata;
2141 if (!sas_device_priv_data)
2142 continue;
2143 if (sas_device_priv_data->block)
2144 continue;
2145 if (sas_device_priv_data->sas_target->handle == handle) {
2146 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2147 MPT2SAS_INFO_FMT "SDEV_BLOCK: "
2148 "handle(0x%04x)\n", ioc->name, handle));
2149 sas_device_priv_data->block = 1;
2150 scsi_device_set_state(sdev, SDEV_BLOCK);
2151 }
2152 }
2153}
2154
2155/**
2156 * _scsih_block_io_to_children_attached_to_ex
2157 * @ioc: per adapter object
2158 * @sas_expander: the sas_device object
2159 *
2160 * This routine set sdev state to SDEV_BLOCK for all devices
2161 * attached to this expander. This function called when expander is
2162 * pulled.
2163 */
2164static void
2165_scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
2166 struct _sas_node *sas_expander)
2167{
2168 struct _sas_port *mpt2sas_port;
2169 struct _sas_device *sas_device;
2170 struct _sas_node *expander_sibling;
2171 unsigned long flags;
2172
2173 if (!sas_expander)
2174 return;
2175
2176 list_for_each_entry(mpt2sas_port,
2177 &sas_expander->sas_port_list, port_list) {
2178 if (mpt2sas_port->remote_identify.device_type ==
2179 SAS_END_DEVICE) {
2180 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2181 sas_device =
2182 mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
2183 mpt2sas_port->remote_identify.sas_address);
2184 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2185 if (!sas_device)
2186 continue;
2187 _scsih_block_io_device(ioc, sas_device->handle);
2188 }
2189 }
2190
2191 list_for_each_entry(mpt2sas_port,
2192 &sas_expander->sas_port_list, port_list) {
2193
2194 if (mpt2sas_port->remote_identify.device_type ==
2195 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
2196 mpt2sas_port->remote_identify.device_type ==
2197 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
2198
2199 spin_lock_irqsave(&ioc->sas_node_lock, flags);
2200 expander_sibling =
2201 mpt2sas_scsih_expander_find_by_sas_address(
2202 ioc, mpt2sas_port->remote_identify.sas_address);
2203 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
2204 _scsih_block_io_to_children_attached_to_ex(ioc,
2205 expander_sibling);
2206 }
2207 }
2208}
2209
2210/**
2211 * _scsih_block_io_to_children_attached_directly
2212 * @ioc: per adapter object
2213 * @event_data: topology change event data
2214 *
2215 * This routine set sdev state to SDEV_BLOCK for all devices
2216 * direct attached during device pull.
2217 */
2218static void
2219_scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
2220 Mpi2EventDataSasTopologyChangeList_t *event_data)
2221{
2222 int i;
2223 u16 handle;
2224 u16 reason_code;
2225 u8 phy_number;
2226
2227 for (i = 0; i < event_data->NumEntries; i++) {
2228 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
2229 if (!handle)
2230 continue;
2231 phy_number = event_data->StartPhyNum + i;
2232 reason_code = event_data->PHY[i].PhyStatus &
2233 MPI2_EVENT_SAS_TOPO_RC_MASK;
2234 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
2235 _scsih_block_io_device(ioc, handle);
2236 }
2237}
2238
2239/**
2240 * _scsih_check_topo_delete_events - sanity check on topo events
2241 * @ioc: per adapter object
2242 * @event_data: the event data payload
2243 *
2244 * This routine added to better handle cable breaker.
2245 *
2246 * This handles the case where driver recieves multiple expander
2247 * add and delete events in a single shot. When there is a delete event
2248 * the routine will void any pending add events waiting in the event queue.
2249 *
2250 * Return nothing.
2251 */
2252static void
2253_scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
2254 Mpi2EventDataSasTopologyChangeList_t *event_data)
2255{
2256 struct fw_event_work *fw_event;
2257 Mpi2EventDataSasTopologyChangeList_t *local_event_data;
2258 u16 expander_handle;
2259 struct _sas_node *sas_expander;
2260 unsigned long flags;
2261
2262 expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
2263 if (expander_handle < ioc->sas_hba.num_phys) {
2264 _scsih_block_io_to_children_attached_directly(ioc, event_data);
2265 return;
2266 }
2267
2268 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING
2269 || event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) {
2270 spin_lock_irqsave(&ioc->sas_node_lock, flags);
2271 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
2272 expander_handle);
2273 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
2274 _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
2275 } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
2276 _scsih_block_io_to_children_attached_directly(ioc, event_data);
2277
2278 if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
2279 return;
2280
2281 /* mark ignore flag for pending events */
2282 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2283 list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
2284 if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
2285 fw_event->ignore)
2286 continue;
2287 local_event_data = fw_event->event_data;
2288 if (local_event_data->ExpStatus ==
2289 MPI2_EVENT_SAS_TOPO_ES_ADDED ||
2290 local_event_data->ExpStatus ==
2291 MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
2292 if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
2293 expander_handle) {
2294 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT
2295 "setting ignoring flag\n", ioc->name));
2296 fw_event->ignore = 1;
2297 }
2298 }
2299 }
2300 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2301}
2302
2303/**
2304 * _scsih_queue_rescan - queue a topology rescan from user context
2305 * @ioc: per adapter object
2306 *
2307 * Return nothing.
2308 */
2309static void
2310_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
2311{
2312 struct fw_event_work *fw_event;
2313
2314 if (ioc->wait_for_port_enable_to_complete)
2315 return;
2316 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2317 if (!fw_event)
2318 return;
2319 fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
2320 fw_event->ioc = ioc;
2321 _scsih_fw_event_add(ioc, fw_event);
2322}
2323
2324/**
2325 * _scsih_flush_running_cmds - completing outstanding commands.
2326 * @ioc: per adapter object
2327 *
2328 * The flushing out of all pending scmd commands following host reset,
2329 * where all IO is dropped to the floor.
2330 *
2331 * Return nothing.
2332 */
2333static void
2334_scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
2335{
2336 struct scsi_cmnd *scmd;
2337 u16 smid;
2338 u16 count = 0;
2339
2340 for (smid = 1; smid <= ioc->request_depth; smid++) {
2341 scmd = _scsih_scsi_lookup_getclear(ioc, smid);
2342 if (!scmd)
2343 continue;
2344 count++;
2345 mpt2sas_base_free_smid(ioc, smid);
2346 scsi_dma_unmap(scmd);
2347 scmd->result = DID_RESET << 16;
2348 scmd->scsi_done(scmd);
2349 }
2350 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n",
2351 ioc->name, count));
2352}
2353
2354/**
2355 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
2356 * @ioc: per adapter object
2357 * @reset_phase: phase
2358 *
2359 * The handler for doing any required cleanup or initialization.
2360 *
2361 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
2362 * MPT2_IOC_DONE_RESET
2363 *
2364 * Return nothing.
2365 */
2366void
2367mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
2368{
2369 switch (reset_phase) {
2370 case MPT2_IOC_PRE_RESET:
2371 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2372 "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
2373 _scsih_fw_event_off(ioc);
2374 break;
2375 case MPT2_IOC_AFTER_RESET:
2376 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2377 "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
2378 if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
2379 ioc->tm_cmds.status |= MPT2_CMD_RESET;
2380 mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
2381 complete(&ioc->tm_cmds.done);
2382 }
2383 _scsih_fw_event_on(ioc);
2384 _scsih_flush_running_cmds(ioc);
2385 break;
2386 case MPT2_IOC_DONE_RESET:
2387 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2388 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
2389 _scsih_queue_rescan(ioc);
2390 break;
2391 }
2392}
2393
2394/**
2395 * scsih_qcmd - main scsi request entry point
2396 * @scmd: pointer to scsi command object
2397 * @done: function pointer to be invoked on completion
2398 *
2399 * The callback index is set inside `ioc->scsi_io_cb_idx`.
2400 *
2401 * Returns 0 on success. If there's a failure, return either:
2402 * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
2403 * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
2404 */
2405static int
2406scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
2407{
2408 struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2409 struct MPT2SAS_DEVICE *sas_device_priv_data;
2410 struct MPT2SAS_TARGET *sas_target_priv_data;
2411 Mpi2SCSIIORequest_t *mpi_request;
2412 u32 mpi_control;
2413 u16 smid;
2414 unsigned long flags;
2415
2416 scmd->scsi_done = done;
2417 sas_device_priv_data = scmd->device->hostdata;
2418 if (!sas_device_priv_data) {
2419 scmd->result = DID_NO_CONNECT << 16;
2420 scmd->scsi_done(scmd);
2421 return 0;
2422 }
2423
2424 sas_target_priv_data = sas_device_priv_data->sas_target;
2425 if (!sas_target_priv_data || sas_target_priv_data->handle ==
2426 MPT2SAS_INVALID_DEVICE_HANDLE || sas_target_priv_data->deleted) {
2427 scmd->result = DID_NO_CONNECT << 16;
2428 scmd->scsi_done(scmd);
2429 return 0;
2430 }
2431
2432 /* see if we are busy with task managment stuff */
2433 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
2434 if (sas_target_priv_data->tm_busy ||
2435 ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
2436 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
2437 return SCSI_MLQUEUE_HOST_BUSY;
2438 }
2439 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
2440
2441 if (scmd->sc_data_direction == DMA_FROM_DEVICE)
2442 mpi_control = MPI2_SCSIIO_CONTROL_READ;
2443 else if (scmd->sc_data_direction == DMA_TO_DEVICE)
2444 mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
2445 else
2446 mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
2447
2448 /* set tags */
2449 if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) {
2450 if (scmd->device->tagged_supported) {
2451 if (scmd->device->ordered_tags)
2452 mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
2453 else
2454 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
2455 } else
2456/* MPI Revision I (UNIT = 0xA) - removed MPI2_SCSIIO_CONTROL_UNTAGGED */
2457/* mpi_control |= MPI2_SCSIIO_CONTROL_UNTAGGED;
2458 */
2459 mpi_control |= (0x500);
2460
2461 } else
2462 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
2463
2464 if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON))
2465 mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
2466
2467 smid = mpt2sas_base_get_smid(ioc, ioc->scsi_io_cb_idx);
2468 if (!smid) {
2469 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
2470 ioc->name, __func__);
2471 goto out;
2472 }
2473 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2474 memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
2475 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
2476 if (sas_device_priv_data->sas_target->flags &
2477 MPT_TARGET_FLAGS_RAID_COMPONENT)
2478 mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
2479 else
2480 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
2481 mpi_request->DevHandle =
2482 cpu_to_le16(sas_device_priv_data->sas_target->handle);
2483 mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
2484 mpi_request->Control = cpu_to_le32(mpi_control);
2485 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
2486 mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
2487 mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
2488 mpi_request->SenseBufferLowAddress =
2489 (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid);
2490 mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
2491 mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI +
2492 MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR);
2493
2494 int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
2495 mpi_request->LUN);
2496 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
2497
2498 if (!mpi_request->DataLength) {
2499 mpt2sas_base_build_zero_len_sge(ioc, &mpi_request->SGL);
2500 } else {
2501 if (_scsih_build_scatter_gather(ioc, scmd, smid)) {
2502 mpt2sas_base_free_smid(ioc, smid);
2503 goto out;
2504 }
2505 }
2506
2507 _scsih_scsi_lookup_set(ioc, smid, scmd);
2508 mpt2sas_base_put_smid_scsi_io(ioc, smid, 0,
2509 sas_device_priv_data->sas_target->handle);
2510 return 0;
2511
2512 out:
2513 return SCSI_MLQUEUE_HOST_BUSY;
2514}
2515
2516/**
2517 * _scsih_normalize_sense - normalize descriptor and fixed format sense data
2518 * @sense_buffer: sense data returned by target
2519 * @data: normalized skey/asc/ascq
2520 *
2521 * Return nothing.
2522 */
2523static void
2524_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
2525{
2526 if ((sense_buffer[0] & 0x7F) >= 0x72) {
2527 /* descriptor format */
2528 data->skey = sense_buffer[1] & 0x0F;
2529 data->asc = sense_buffer[2];
2530 data->ascq = sense_buffer[3];
2531 } else {
2532 /* fixed format */
2533 data->skey = sense_buffer[2] & 0x0F;
2534 data->asc = sense_buffer[12];
2535 data->ascq = sense_buffer[13];
2536 }
2537}
2538
2539#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
2540/**
2541 * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
2542 * @ioc: per adapter object
2543 * @scmd: pointer to scsi command object
2544 * @mpi_reply: reply mf payload returned from firmware
2545 *
2546 * scsi_status - SCSI Status code returned from target device
2547 * scsi_state - state info associated with SCSI_IO determined by ioc
2548 * ioc_status - ioc supplied status info
2549 *
2550 * Return nothing.
2551 */
2552static void
2553_scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
2554 Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
2555{
2556 u32 response_info;
2557 u8 *response_bytes;
2558 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
2559 MPI2_IOCSTATUS_MASK;
2560 u8 scsi_state = mpi_reply->SCSIState;
2561 u8 scsi_status = mpi_reply->SCSIStatus;
2562 char *desc_ioc_state = NULL;
2563 char *desc_scsi_status = NULL;
2564 char *desc_scsi_state = ioc->tmp_string;
2565
2566 switch (ioc_status) {
2567 case MPI2_IOCSTATUS_SUCCESS:
2568 desc_ioc_state = "success";
2569 break;
2570 case MPI2_IOCSTATUS_INVALID_FUNCTION:
2571 desc_ioc_state = "invalid function";
2572 break;
2573 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
2574 desc_ioc_state = "scsi recovered error";
2575 break;
2576 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
2577 desc_ioc_state = "scsi invalid dev handle";
2578 break;
2579 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
2580 desc_ioc_state = "scsi device not there";
2581 break;
2582 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
2583 desc_ioc_state = "scsi data overrun";
2584 break;
2585 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
2586 desc_ioc_state = "scsi data underrun";
2587 break;
2588 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
2589 desc_ioc_state = "scsi io data error";
2590 break;
2591 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
2592 desc_ioc_state = "scsi protocol error";
2593 break;
2594 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
2595 desc_ioc_state = "scsi task terminated";
2596 break;
2597 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
2598 desc_ioc_state = "scsi residual mismatch";
2599 break;
2600 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
2601 desc_ioc_state = "scsi task mgmt failed";
2602 break;
2603 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
2604 desc_ioc_state = "scsi ioc terminated";
2605 break;
2606 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
2607 desc_ioc_state = "scsi ext terminated";
2608 break;
2609 default:
2610 desc_ioc_state = "unknown";
2611 break;
2612 }
2613
2614 switch (scsi_status) {
2615 case MPI2_SCSI_STATUS_GOOD:
2616 desc_scsi_status = "good";
2617 break;
2618 case MPI2_SCSI_STATUS_CHECK_CONDITION:
2619 desc_scsi_status = "check condition";
2620 break;
2621 case MPI2_SCSI_STATUS_CONDITION_MET:
2622 desc_scsi_status = "condition met";
2623 break;
2624 case MPI2_SCSI_STATUS_BUSY:
2625 desc_scsi_status = "busy";
2626 break;
2627 case MPI2_SCSI_STATUS_INTERMEDIATE:
2628 desc_scsi_status = "intermediate";
2629 break;
2630 case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
2631 desc_scsi_status = "intermediate condmet";
2632 break;
2633 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
2634 desc_scsi_status = "reservation conflict";
2635 break;
2636 case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
2637 desc_scsi_status = "command terminated";
2638 break;
2639 case MPI2_SCSI_STATUS_TASK_SET_FULL:
2640 desc_scsi_status = "task set full";
2641 break;
2642 case MPI2_SCSI_STATUS_ACA_ACTIVE:
2643 desc_scsi_status = "aca active";
2644 break;
2645 case MPI2_SCSI_STATUS_TASK_ABORTED:
2646 desc_scsi_status = "task aborted";
2647 break;
2648 default:
2649 desc_scsi_status = "unknown";
2650 break;
2651 }
2652
2653 desc_scsi_state[0] = '\0';
2654 if (!scsi_state)
2655 desc_scsi_state = " ";
2656 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
2657 strcat(desc_scsi_state, "response info ");
2658 if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
2659 strcat(desc_scsi_state, "state terminated ");
2660 if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
2661 strcat(desc_scsi_state, "no status ");
2662 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
2663 strcat(desc_scsi_state, "autosense failed ");
2664 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
2665 strcat(desc_scsi_state, "autosense valid ");
2666
2667 scsi_print_command(scmd);
2668 printk(MPT2SAS_WARN_FMT "\tdev handle(0x%04x), "
2669 "ioc_status(%s)(0x%04x), smid(%d)\n", ioc->name,
2670 le16_to_cpu(mpi_reply->DevHandle), desc_ioc_state,
2671 ioc_status, smid);
2672 printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), "
2673 "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow,
2674 scsi_get_resid(scmd));
2675 printk(MPT2SAS_WARN_FMT "\ttag(%d), transfer_count(%d), "
2676 "sc->result(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->TaskTag),
2677 le32_to_cpu(mpi_reply->TransferCount), scmd->result);
2678 printk(MPT2SAS_WARN_FMT "\tscsi_status(%s)(0x%02x), "
2679 "scsi_state(%s)(0x%02x)\n", ioc->name, desc_scsi_status,
2680 scsi_status, desc_scsi_state, scsi_state);
2681
2682 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
2683 struct sense_info data;
2684 _scsih_normalize_sense(scmd->sense_buffer, &data);
2685 printk(MPT2SAS_WARN_FMT "\t[sense_key,asc,ascq]: "
2686 "[0x%02x,0x%02x,0x%02x]\n", ioc->name, data.skey,
2687 data.asc, data.ascq);
2688 }
2689
2690 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
2691 response_info = le32_to_cpu(mpi_reply->ResponseInfo);
2692 response_bytes = (u8 *)&response_info;
2693 _scsih_response_code(ioc, response_bytes[3]);
2694 }
2695}
2696#endif
2697
2698/**
2699 * _scsih_smart_predicted_fault - illuminate Fault LED
2700 * @ioc: per adapter object
2701 * @handle: device handle
2702 *
2703 * Return nothing.
2704 */
2705static void
2706_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2707{
2708 Mpi2SepReply_t mpi_reply;
2709 Mpi2SepRequest_t mpi_request;
2710 struct scsi_target *starget;
2711 struct MPT2SAS_TARGET *sas_target_priv_data;
2712 Mpi2EventNotificationReply_t *event_reply;
2713 Mpi2EventDataSasDeviceStatusChange_t *event_data;
2714 struct _sas_device *sas_device;
2715 ssize_t sz;
2716 unsigned long flags;
2717
2718 /* only handle non-raid devices */
2719 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2720 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
2721 if (!sas_device) {
2722 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2723 return;
2724 }
2725 starget = sas_device->starget;
2726 sas_target_priv_data = starget->hostdata;
2727
2728 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
2729 ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) {
2730 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2731 return;
2732 }
2733 starget_printk(KERN_WARNING, starget, "predicted fault\n");
2734 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2735
2736 if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) {
2737 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
2738 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
2739 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
2740 mpi_request.SlotStatus =
2741 MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
2742 mpi_request.DevHandle = cpu_to_le16(handle);
2743 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
2744 if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
2745 &mpi_request)) != 0) {
2746 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
2747 ioc->name, __FILE__, __LINE__, __func__);
2748 return;
2749 }
2750
2751 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
2752 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
2753 "enclosure_processor: ioc_status (0x%04x), "
2754 "loginfo(0x%08x)\n", ioc->name,
2755 le16_to_cpu(mpi_reply.IOCStatus),
2756 le32_to_cpu(mpi_reply.IOCLogInfo)));
2757 return;
2758 }
2759 }
2760
2761 /* insert into event log */
2762 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
2763 sizeof(Mpi2EventDataSasDeviceStatusChange_t);
2764 event_reply = kzalloc(sz, GFP_KERNEL);
2765 if (!event_reply) {
2766 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
2767 ioc->name, __FILE__, __LINE__, __func__);
2768 return;
2769 }
2770
2771 event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
2772 event_reply->Event =
2773 cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
2774 event_reply->MsgLength = sz/4;
2775 event_reply->EventDataLength =
2776 cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
2777 event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
2778 event_reply->EventData;
2779 event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
2780 event_data->ASC = 0x5D;
2781 event_data->DevHandle = cpu_to_le16(handle);
2782 event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
2783 mpt2sas_ctl_add_to_event_log(ioc, event_reply);
2784 kfree(event_reply);
2785}
2786
2787/**
2788 * scsih_io_done - scsi request callback
2789 * @ioc: per adapter object
2790 * @smid: system request message index
2791 * @VF_ID: virtual function id
2792 * @reply: reply message frame(lower 32bit addr)
2793 *
2794 * Callback handler when using scsih_qcmd.
2795 *
2796 * Return nothing.
2797 */
2798static void
2799scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
2800{
2801 Mpi2SCSIIORequest_t *mpi_request;
2802 Mpi2SCSIIOReply_t *mpi_reply;
2803 struct scsi_cmnd *scmd;
2804 u16 ioc_status;
2805 u32 xfer_cnt;
2806 u8 scsi_state;
2807 u8 scsi_status;
2808 u32 log_info;
2809 struct MPT2SAS_DEVICE *sas_device_priv_data;
2810 u32 response_code;
2811
2812 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
2813 scmd = _scsih_scsi_lookup_getclear(ioc, smid);
2814 if (scmd == NULL)
2815 return;
2816
2817 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
2818
2819 if (mpi_reply == NULL) {
2820 scmd->result = DID_OK << 16;
2821 goto out;
2822 }
2823
2824 sas_device_priv_data = scmd->device->hostdata;
2825 if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
2826 sas_device_priv_data->sas_target->deleted) {
2827 scmd->result = DID_NO_CONNECT << 16;
2828 goto out;
2829 }
2830
2831 /* turning off TLR */
2832 if (!sas_device_priv_data->tlr_snoop_check) {
2833 sas_device_priv_data->tlr_snoop_check++;
2834 if (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) {
2835 response_code = (le32_to_cpu(mpi_reply->ResponseInfo)
2836 >> 24);
2837 if (response_code ==
2838 MPI2_SCSITASKMGMT_RSP_INVALID_FRAME)
2839 sas_device_priv_data->flags &=
2840 ~MPT_DEVICE_TLR_ON;
2841 }
2842 }
2843
2844 xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
2845 scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
2846 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
2847 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
2848 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
2849 else
2850 log_info = 0;
2851 ioc_status &= MPI2_IOCSTATUS_MASK;
2852 scsi_state = mpi_reply->SCSIState;
2853 scsi_status = mpi_reply->SCSIStatus;
2854
2855 if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
2856 (scsi_status == MPI2_SCSI_STATUS_BUSY ||
2857 scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
2858 scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
2859 ioc_status = MPI2_IOCSTATUS_SUCCESS;
2860 }
2861
2862 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
2863 struct sense_info data;
2864 const void *sense_data = mpt2sas_base_get_sense_buffer(ioc,
2865 smid);
2866 memcpy(scmd->sense_buffer, sense_data,
2867 le32_to_cpu(mpi_reply->SenseCount));
2868 _scsih_normalize_sense(scmd->sense_buffer, &data);
2869 /* failure prediction threshold exceeded */
2870 if (data.asc == 0x5D)
2871 _scsih_smart_predicted_fault(ioc,
2872 le16_to_cpu(mpi_reply->DevHandle));
2873 }
2874
2875 switch (ioc_status) {
2876 case MPI2_IOCSTATUS_BUSY:
2877 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
2878 scmd->result = SAM_STAT_BUSY;
2879 break;
2880
2881 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
2882 scmd->result = DID_NO_CONNECT << 16;
2883 break;
2884
2885 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
2886 if (sas_device_priv_data->block) {
2887 scmd->result = (DID_BUS_BUSY << 16);
2888 break;
2889 }
2890
2891 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
2892 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
2893 scmd->result = DID_RESET << 16;
2894 break;
2895
2896 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
2897 if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
2898 scmd->result = DID_SOFT_ERROR << 16;
2899 else
2900 scmd->result = (DID_OK << 16) | scsi_status;
2901 break;
2902
2903 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
2904 scmd->result = (DID_OK << 16) | scsi_status;
2905
2906 if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
2907 break;
2908
2909 if (xfer_cnt < scmd->underflow) {
2910 if (scsi_status == SAM_STAT_BUSY)
2911 scmd->result = SAM_STAT_BUSY;
2912 else
2913 scmd->result = DID_SOFT_ERROR << 16;
2914 } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
2915 MPI2_SCSI_STATE_NO_SCSI_STATUS))
2916 scmd->result = DID_SOFT_ERROR << 16;
2917 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
2918 scmd->result = DID_RESET << 16;
2919 else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
2920 mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
2921 mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
2922 scmd->result = (DRIVER_SENSE << 24) |
2923 SAM_STAT_CHECK_CONDITION;
2924 scmd->sense_buffer[0] = 0x70;
2925 scmd->sense_buffer[2] = ILLEGAL_REQUEST;
2926 scmd->sense_buffer[12] = 0x20;
2927 scmd->sense_buffer[13] = 0;
2928 }
2929 break;
2930
2931 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
2932 scsi_set_resid(scmd, 0);
2933 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
2934 case MPI2_IOCSTATUS_SUCCESS:
2935 scmd->result = (DID_OK << 16) | scsi_status;
2936 if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
2937 MPI2_SCSI_STATE_NO_SCSI_STATUS))
2938 scmd->result = DID_SOFT_ERROR << 16;
2939 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
2940 scmd->result = DID_RESET << 16;
2941 break;
2942
2943 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
2944 case MPI2_IOCSTATUS_INVALID_FUNCTION:
2945 case MPI2_IOCSTATUS_INVALID_SGL:
2946 case MPI2_IOCSTATUS_INTERNAL_ERROR:
2947 case MPI2_IOCSTATUS_INVALID_FIELD:
2948 case MPI2_IOCSTATUS_INVALID_STATE:
2949 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
2950 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
2951 default:
2952 scmd->result = DID_SOFT_ERROR << 16;
2953 break;
2954
2955 }
2956
2957#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
2958 if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
2959 _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
2960#endif
2961
2962 out:
2963 scsi_dma_unmap(scmd);
2964 scmd->scsi_done(scmd);
2965}
2966
2967/**
2968 * _scsih_link_change - process phy link changes
2969 * @ioc: per adapter object
2970 * @handle: phy handle
2971 * @attached_handle: valid for devices attached to link
2972 * @phy_number: phy number
2973 * @link_rate: new link rate
2974 * Context: user.
2975 *
2976 * Return nothing.
2977 */
2978static void
2979_scsih_link_change(struct MPT2SAS_ADAPTER *ioc, u16 handle, u16 attached_handle,
2980 u8 phy_number, u8 link_rate)
2981{
2982 mpt2sas_transport_update_phy_link_change(ioc, handle, attached_handle,
2983 phy_number, link_rate);
2984}
2985
2986/**
2987 * _scsih_sas_host_refresh - refreshing sas host object contents
2988 * @ioc: per adapter object
2989 * @update: update link information
2990 * Context: user
2991 *
2992 * During port enable, fw will send topology events for every device. Its
2993 * possible that the handles may change from the previous setting, so this
2994 * code keeping handles updating if changed.
2995 *
2996 * Return nothing.
2997 */
2998static void
2999_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update)
3000{
3001 u16 sz;
3002 u16 ioc_status;
3003 int i;
3004 Mpi2ConfigReply_t mpi_reply;
3005 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
3006
3007 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
3008 "updating handles for sas_host(0x%016llx)\n",
3009 ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
3010
3011 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
3012 * sizeof(Mpi2SasIOUnit0PhyData_t));
3013 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
3014 if (!sas_iounit_pg0) {
3015 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3016 ioc->name, __FILE__, __LINE__, __func__);
3017 return;
3018 }
3019 if (!(mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
3020 sas_iounit_pg0, sz))) {
3021 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
3022 MPI2_IOCSTATUS_MASK;
3023 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
3024 goto out;
3025 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
3026 ioc->sas_hba.phy[i].handle =
3027 le16_to_cpu(sas_iounit_pg0->PhyData[i].
3028 ControllerDevHandle);
3029 if (update)
3030 _scsih_link_change(ioc,
3031 ioc->sas_hba.phy[i].handle,
3032 le16_to_cpu(sas_iounit_pg0->PhyData[i].
3033 AttachedDevHandle), i,
3034 sas_iounit_pg0->PhyData[i].
3035 NegotiatedLinkRate >> 4);
3036 }
3037 }
3038
3039 out:
3040 kfree(sas_iounit_pg0);
3041}
3042
3043/**
3044 * _scsih_sas_host_add - create sas host object
3045 * @ioc: per adapter object
3046 *
3047 * Creating host side data object, stored in ioc->sas_hba
3048 *
3049 * Return nothing.
3050 */
3051static void
3052_scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc)
3053{
3054 int i;
3055 Mpi2ConfigReply_t mpi_reply;
3056 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
3057 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
3058 Mpi2SasPhyPage0_t phy_pg0;
3059 Mpi2SasDevicePage0_t sas_device_pg0;
3060 Mpi2SasEnclosurePage0_t enclosure_pg0;
3061 u16 ioc_status;
3062 u16 sz;
3063 u16 device_missing_delay;
3064
3065 mpt2sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
3066 if (!ioc->sas_hba.num_phys) {
3067 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3068 ioc->name, __FILE__, __LINE__, __func__);
3069 return;
3070 }
3071
3072 /* sas_iounit page 0 */
3073 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
3074 sizeof(Mpi2SasIOUnit0PhyData_t));
3075 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
3076 if (!sas_iounit_pg0) {
3077 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3078 ioc->name, __FILE__, __LINE__, __func__);
3079 return;
3080 }
3081 if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
3082 sas_iounit_pg0, sz))) {
3083 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3084 ioc->name, __FILE__, __LINE__, __func__);
3085 goto out;
3086 }
3087 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
3088 MPI2_IOCSTATUS_MASK;
3089 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
3090 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3091 ioc->name, __FILE__, __LINE__, __func__);
3092 goto out;
3093 }
3094
3095 /* sas_iounit page 1 */
3096 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
3097 sizeof(Mpi2SasIOUnit1PhyData_t));
3098 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
3099 if (!sas_iounit_pg1) {
3100 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3101 ioc->name, __FILE__, __LINE__, __func__);
3102 goto out;
3103 }
3104 if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
3105 sas_iounit_pg1, sz))) {
3106 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3107 ioc->name, __FILE__, __LINE__, __func__);
3108 goto out;
3109 }
3110 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
3111 MPI2_IOCSTATUS_MASK;
3112 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
3113 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3114 ioc->name, __FILE__, __LINE__, __func__);
3115 goto out;
3116 }
3117
3118 ioc->io_missing_delay =
3119 le16_to_cpu(sas_iounit_pg1->IODeviceMissingDelay);
3120 device_missing_delay =
3121 le16_to_cpu(sas_iounit_pg1->ReportDeviceMissingDelay);
3122 if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
3123 ioc->device_missing_delay = (device_missing_delay &
3124 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
3125 else
3126 ioc->device_missing_delay = device_missing_delay &
3127 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
3128
3129 ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
3130 ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
3131 sizeof(struct _sas_phy), GFP_KERNEL);
3132 if (!ioc->sas_hba.phy) {
3133 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3134 ioc->name, __FILE__, __LINE__, __func__);
3135 goto out;
3136 }
3137 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
3138 if ((mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
3139 i))) {
3140 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3141 ioc->name, __FILE__, __LINE__, __func__);
3142 goto out;
3143 }
3144 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
3145 MPI2_IOCSTATUS_MASK;
3146 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
3147 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3148 ioc->name, __FILE__, __LINE__, __func__);
3149 goto out;
3150 }
3151 ioc->sas_hba.phy[i].handle =
3152 le16_to_cpu(sas_iounit_pg0->PhyData[i].ControllerDevHandle);
3153 ioc->sas_hba.phy[i].phy_id = i;
3154 mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
3155 phy_pg0, ioc->sas_hba.parent_dev);
3156 }
3157 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
3158 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.phy[0].handle))) {
3159 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3160 ioc->name, __FILE__, __LINE__, __func__);
3161 goto out;
3162 }
3163 ioc->sas_hba.handle = le16_to_cpu(sas_device_pg0.DevHandle);
3164 ioc->sas_hba.enclosure_handle =
3165 le16_to_cpu(sas_device_pg0.EnclosureHandle);
3166 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
3167 printk(MPT2SAS_INFO_FMT "host_add: handle(0x%04x), "
3168 "sas_addr(0x%016llx), phys(%d)\n", ioc->name, ioc->sas_hba.handle,
3169 (unsigned long long) ioc->sas_hba.sas_address,
3170 ioc->sas_hba.num_phys) ;
3171
3172 if (ioc->sas_hba.enclosure_handle) {
3173 if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
3174 &enclosure_pg0,
3175 MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
3176 ioc->sas_hba.enclosure_handle))) {
3177 ioc->sas_hba.enclosure_logical_id =
3178 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
3179 }
3180 }
3181
3182 out:
3183 kfree(sas_iounit_pg1);
3184 kfree(sas_iounit_pg0);
3185}
3186
3187/**
3188 * _scsih_expander_add - creating expander object
3189 * @ioc: per adapter object
3190 * @handle: expander handle
3191 *
3192 * Creating expander object, stored in ioc->sas_expander_list.
3193 *
3194 * Return 0 for success, else error.
3195 */
3196static int
3197_scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3198{
3199 struct _sas_node *sas_expander;
3200 Mpi2ConfigReply_t mpi_reply;
3201 Mpi2ExpanderPage0_t expander_pg0;
3202 Mpi2ExpanderPage1_t expander_pg1;
3203 Mpi2SasEnclosurePage0_t enclosure_pg0;
3204 u32 ioc_status;
3205 u16 parent_handle;
3206 __le64 sas_address;
3207 int i;
3208 unsigned long flags;
3209 struct _sas_port *mpt2sas_port;
3210 int rc = 0;
3211
3212 if (!handle)
3213 return -1;
3214
3215 if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
3216 MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
3217 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3218 ioc->name, __FILE__, __LINE__, __func__);
3219 return -1;
3220 }
3221
3222 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
3223 MPI2_IOCSTATUS_MASK;
3224 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
3225 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3226 ioc->name, __FILE__, __LINE__, __func__);
3227 return -1;
3228 }
3229
3230 /* handle out of order topology events */
3231 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
3232 if (parent_handle >= ioc->sas_hba.num_phys) {
3233 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3234 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
3235 parent_handle);
3236 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3237 if (!sas_expander) {
3238 rc = _scsih_expander_add(ioc, parent_handle);
3239 if (rc != 0)
3240 return rc;
3241 }
3242 }
3243
3244 sas_address = le64_to_cpu(expander_pg0.SASAddress);
3245
3246 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3247 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
3248 sas_address);
3249 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3250
3251 if (sas_expander)
3252 return 0;
3253
3254 sas_expander = kzalloc(sizeof(struct _sas_node),
3255 GFP_KERNEL);
3256 if (!sas_expander) {
3257 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3258 ioc->name, __FILE__, __LINE__, __func__);
3259 return -1;
3260 }
3261
3262 sas_expander->handle = handle;
3263 sas_expander->num_phys = expander_pg0.NumPhys;
3264 sas_expander->parent_handle = parent_handle;
3265 sas_expander->enclosure_handle =
3266 le16_to_cpu(expander_pg0.EnclosureHandle);
3267 sas_expander->sas_address = sas_address;
3268
3269 printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x),"
3270 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
3271 handle, sas_expander->parent_handle, (unsigned long long)
3272 sas_expander->sas_address, sas_expander->num_phys);
3273
3274 if (!sas_expander->num_phys)
3275 goto out_fail;
3276 sas_expander->phy = kcalloc(sas_expander->num_phys,
3277 sizeof(struct _sas_phy), GFP_KERNEL);
3278 if (!sas_expander->phy) {
3279 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3280 ioc->name, __FILE__, __LINE__, __func__);
3281 rc = -1;
3282 goto out_fail;
3283 }
3284
3285 INIT_LIST_HEAD(&sas_expander->sas_port_list);
3286 mpt2sas_port = mpt2sas_transport_port_add(ioc, handle,
3287 sas_expander->parent_handle);
3288 if (!mpt2sas_port) {
3289 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3290 ioc->name, __FILE__, __LINE__, __func__);
3291 rc = -1;
3292 goto out_fail;
3293 }
3294 sas_expander->parent_dev = &mpt2sas_port->rphy->dev;
3295
3296 for (i = 0 ; i < sas_expander->num_phys ; i++) {
3297 if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
3298 &expander_pg1, i, handle))) {
3299 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3300 ioc->name, __FILE__, __LINE__, __func__);
3301 continue;
3302 }
3303 sas_expander->phy[i].handle = handle;
3304 sas_expander->phy[i].phy_id = i;
3305 mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i],
3306 expander_pg1, sas_expander->parent_dev);
3307 }
3308
3309 if (sas_expander->enclosure_handle) {
3310 if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
3311 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
3312 sas_expander->enclosure_handle))) {
3313 sas_expander->enclosure_logical_id =
3314 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
3315 }
3316 }
3317
3318 _scsih_expander_node_add(ioc, sas_expander);
3319 return 0;
3320
3321 out_fail:
3322
3323 if (sas_expander)
3324 kfree(sas_expander->phy);
3325 kfree(sas_expander);
3326 return rc;
3327}
3328
3329/**
3330 * _scsih_expander_remove - removing expander object
3331 * @ioc: per adapter object
3332 * @handle: expander handle
3333 *
3334 * Return nothing.
3335 */
3336static void
3337_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3338{
3339 struct _sas_node *sas_expander;
3340 unsigned long flags;
3341
3342 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3343 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle);
3344 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3345 _scsih_expander_node_remove(ioc, sas_expander);
3346}
3347
3348/**
3349 * _scsih_add_device - creating sas device object
3350 * @ioc: per adapter object
3351 * @handle: sas device handle
3352 * @phy_num: phy number end device attached to
3353 * @is_pd: is this hidden raid component
3354 *
3355 * Creating end device object, stored in ioc->sas_device_list.
3356 *
3357 * Returns 0 for success, non-zero for failure.
3358 */
3359static int
3360_scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
3361{
3362 Mpi2ConfigReply_t mpi_reply;
3363 Mpi2SasDevicePage0_t sas_device_pg0;
3364 Mpi2SasEnclosurePage0_t enclosure_pg0;
3365 struct _sas_device *sas_device;
3366 u32 ioc_status;
3367 __le64 sas_address;
3368 u32 device_info;
3369 unsigned long flags;
3370
3371 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
3372 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
3373 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3374 ioc->name, __FILE__, __LINE__, __func__);
3375 return -1;
3376 }
3377
3378 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
3379 MPI2_IOCSTATUS_MASK;
3380 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
3381 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3382 ioc->name, __FILE__, __LINE__, __func__);
3383 return -1;
3384 }
3385
3386 /* check if device is present */
3387 if (!(le16_to_cpu(sas_device_pg0.Flags) &
3388 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
3389 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3390 ioc->name, __FILE__, __LINE__, __func__);
3391 printk(MPT2SAS_ERR_FMT "Flags = 0x%04x\n",
3392 ioc->name, le16_to_cpu(sas_device_pg0.Flags));
3393 return -1;
3394 }
3395
3396 /* check if there were any issus with discovery */
3397 if (sas_device_pg0.AccessStatus ==
3398 MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED) {
3399 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3400 ioc->name, __FILE__, __LINE__, __func__);
3401 printk(MPT2SAS_ERR_FMT "AccessStatus = 0x%02x\n",
3402 ioc->name, sas_device_pg0.AccessStatus);
3403 return -1;
3404 }
3405
3406 /* check if this is end device */
3407 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
3408 if (!(_scsih_is_end_device(device_info))) {
3409 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3410 ioc->name, __FILE__, __LINE__, __func__);
3411 return -1;
3412 }
3413
3414 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
3415
3416 spin_lock_irqsave(&ioc->sas_device_lock, flags);
3417 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
3418 sas_address);
3419 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3420
3421 if (sas_device) {
3422 _scsih_ublock_io_device(ioc, handle);
3423 return 0;
3424 }
3425
3426 sas_device = kzalloc(sizeof(struct _sas_device),
3427 GFP_KERNEL);
3428 if (!sas_device) {
3429 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3430 ioc->name, __FILE__, __LINE__, __func__);
3431 return -1;
3432 }
3433
3434 sas_device->handle = handle;
3435 sas_device->parent_handle =
3436 le16_to_cpu(sas_device_pg0.ParentDevHandle);
3437 sas_device->enclosure_handle =
3438 le16_to_cpu(sas_device_pg0.EnclosureHandle);
3439 sas_device->slot =
3440 le16_to_cpu(sas_device_pg0.Slot);
3441 sas_device->device_info = device_info;
3442 sas_device->sas_address = sas_address;
3443 sas_device->hidden_raid_component = is_pd;
3444
3445 /* get enclosure_logical_id */
3446 if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0,
3447 MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
3448 sas_device->enclosure_handle))) {
3449 sas_device->enclosure_logical_id =
3450 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
3451 }
3452
3453 /* get device name */
3454 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
3455
3456 if (ioc->wait_for_port_enable_to_complete)
3457 _scsih_sas_device_init_add(ioc, sas_device);
3458 else
3459 _scsih_sas_device_add(ioc, sas_device);
3460
3461 return 0;
3462}
3463
3464/**
3465 * _scsih_remove_device - removing sas device object
3466 * @ioc: per adapter object
3467 * @handle: sas device handle
3468 *
3469 * Return nothing.
3470 */
3471static void
3472_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3473{
3474 struct MPT2SAS_TARGET *sas_target_priv_data;
3475 struct _sas_device *sas_device;
3476 unsigned long flags;
3477 Mpi2SasIoUnitControlReply_t mpi_reply;
3478 Mpi2SasIoUnitControlRequest_t mpi_request;
3479 u16 device_handle;
3480
3481 /* lookup sas_device */
3482 spin_lock_irqsave(&ioc->sas_device_lock, flags);
3483 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
3484 if (!sas_device) {
3485 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3486 return;
3487 }
3488
3489 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle"
3490 "(0x%04x)\n", ioc->name, __func__, handle));
3491
3492 if (sas_device->starget && sas_device->starget->hostdata) {
3493 sas_target_priv_data = sas_device->starget->hostdata;
3494 sas_target_priv_data->deleted = 1;
3495 }
3496 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3497
3498 if (ioc->remove_host)
3499 goto out;
3500
3501 /* Target Reset to flush out all the outstanding IO */
3502 device_handle = (sas_device->hidden_raid_component) ?
3503 sas_device->volume_handle : handle;
3504 if (device_handle) {
3505 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset: "
3506 "handle(0x%04x)\n", ioc->name, device_handle));
3507 mutex_lock(&ioc->tm_cmds.mutex);
3508 mpt2sas_scsih_issue_tm(ioc, device_handle, 0,
3509 MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10);
3510 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
3511 mutex_unlock(&ioc->tm_cmds.mutex);
3512 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset "
3513 "done: handle(0x%04x)\n", ioc->name, device_handle));
3514 }
3515
3516 /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */
3517 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle"
3518 "(0x%04x)\n", ioc->name, handle));
3519 memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
3520 mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
3521 mpi_request.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
3522 mpi_request.DevHandle = handle;
3523 mpi_request.VF_ID = 0;
3524 if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply,
3525 &mpi_request)) != 0) {
3526 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3527 ioc->name, __FILE__, __LINE__, __func__);
3528 }
3529
3530 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: ioc_status"
3531 "(0x%04x), loginfo(0x%08x)\n", ioc->name,
3532 le16_to_cpu(mpi_reply.IOCStatus),
3533 le32_to_cpu(mpi_reply.IOCLogInfo)));
3534
3535 out:
3536 mpt2sas_transport_port_remove(ioc, sas_device->sas_address,
3537 sas_device->parent_handle);
3538
3539 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
3540 "(0x%016llx)\n", ioc->name, sas_device->handle,
3541 (unsigned long long) sas_device->sas_address);
3542 _scsih_sas_device_remove(ioc, sas_device);
3543
3544 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: handle"
3545 "(0x%04x)\n", ioc->name, __func__, handle));
3546}
3547
3548#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
3549/**
3550 * _scsih_sas_topology_change_event_debug - debug for topology event
3551 * @ioc: per adapter object
3552 * @event_data: event data payload
3553 * Context: user.
3554 */
3555static void
3556_scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
3557 Mpi2EventDataSasTopologyChangeList_t *event_data)
3558{
3559 int i;
3560 u16 handle;
3561 u16 reason_code;
3562 u8 phy_number;
3563 char *status_str = NULL;
3564 char link_rate[25];
3565
3566 switch (event_data->ExpStatus) {
3567 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
3568 status_str = "add";
3569 break;
3570 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
3571 status_str = "remove";
3572 break;
3573 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
3574 status_str = "responding";
3575 break;
3576 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
3577 status_str = "remove delay";
3578 break;
3579 default:
3580 status_str = "unknown status";
3581 break;
3582 }
3583 printk(MPT2SAS_DEBUG_FMT "sas topology change: (%s)\n",
3584 ioc->name, status_str);
3585 printk(KERN_DEBUG "\thandle(0x%04x), enclosure_handle(0x%04x) "
3586 "start_phy(%02d), count(%d)\n",
3587 le16_to_cpu(event_data->ExpanderDevHandle),
3588 le16_to_cpu(event_data->EnclosureHandle),
3589 event_data->StartPhyNum, event_data->NumEntries);
3590 for (i = 0; i < event_data->NumEntries; i++) {
3591 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3592 if (!handle)
3593 continue;
3594 phy_number = event_data->StartPhyNum + i;
3595 reason_code = event_data->PHY[i].PhyStatus &
3596 MPI2_EVENT_SAS_TOPO_RC_MASK;
3597 switch (reason_code) {
3598 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
3599 snprintf(link_rate, 25, ": add, link(0x%02x)",
3600 (event_data->PHY[i].LinkRate >> 4));
3601 status_str = link_rate;
3602 break;
3603 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
3604 status_str = ": remove";
3605 break;
3606 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
3607 status_str = ": remove_delay";
3608 break;
3609 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
3610 snprintf(link_rate, 25, ": link(0x%02x)",
3611 (event_data->PHY[i].LinkRate >> 4));
3612 status_str = link_rate;
3613 break;
3614 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
3615 status_str = ": responding";
3616 break;
3617 default:
3618 status_str = ": unknown";
3619 break;
3620 }
3621 printk(KERN_DEBUG "\tphy(%02d), attached_handle(0x%04x)%s\n",
3622 phy_number, handle, status_str);
3623 }
3624}
3625#endif
3626
3627/**
3628 * _scsih_sas_topology_change_event - handle topology changes
3629 * @ioc: per adapter object
3630 * @VF_ID:
3631 * @event_data: event data payload
3632 * fw_event:
3633 * Context: user.
3634 *
3635 */
3636static void
3637_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
3638 Mpi2EventDataSasTopologyChangeList_t *event_data,
3639 struct fw_event_work *fw_event)
3640{
3641 int i;
3642 u16 parent_handle, handle;
3643 u16 reason_code;
3644 u8 phy_number;
3645 struct _sas_node *sas_expander;
3646 unsigned long flags;
3647 u8 link_rate_;
3648
3649#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
3650 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
3651 _scsih_sas_topology_change_event_debug(ioc, event_data);
3652#endif
3653
3654 if (!ioc->sas_hba.num_phys)
3655 _scsih_sas_host_add(ioc);
3656 else
3657 _scsih_sas_host_refresh(ioc, 0);
3658
3659 if (fw_event->ignore) {
3660 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander "
3661 "event\n", ioc->name));
3662 return;
3663 }
3664
3665 parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
3666
3667 /* handle expander add */
3668 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
3669 if (_scsih_expander_add(ioc, parent_handle) != 0)
3670 return;
3671
3672 /* handle siblings events */
3673 for (i = 0; i < event_data->NumEntries; i++) {
3674 if (fw_event->ignore) {
3675 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring "
3676 "expander event\n", ioc->name));
3677 return;
3678 }
3679 if (event_data->PHY[i].PhyStatus &
3680 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
3681 continue;
3682 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3683 if (!handle)
3684 continue;
3685 phy_number = event_data->StartPhyNum + i;
3686 reason_code = event_data->PHY[i].PhyStatus &
3687 MPI2_EVENT_SAS_TOPO_RC_MASK;
3688 link_rate_ = event_data->PHY[i].LinkRate >> 4;
3689 switch (reason_code) {
3690 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
3691 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
3692 if (!parent_handle) {
3693 if (phy_number < ioc->sas_hba.num_phys)
3694 _scsih_link_change(ioc,
3695 ioc->sas_hba.phy[phy_number].handle,
3696 handle, phy_number, link_rate_);
3697 } else {
3698 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3699 sas_expander =
3700 mpt2sas_scsih_expander_find_by_handle(ioc,
3701 parent_handle);
3702 spin_unlock_irqrestore(&ioc->sas_node_lock,
3703 flags);
3704 if (sas_expander) {
3705 if (phy_number < sas_expander->num_phys)
3706 _scsih_link_change(ioc,
3707 sas_expander->
3708 phy[phy_number].handle,
3709 handle, phy_number,
3710 link_rate_);
3711 }
3712 }
3713 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) {
3714 if (link_rate_ >= MPI2_SAS_NEG_LINK_RATE_1_5)
3715 _scsih_ublock_io_device(ioc, handle);
3716 }
3717 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) {
3718 if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5)
3719 break;
3720 _scsih_add_device(ioc, handle, phy_number, 0);
3721 }
3722 break;
3723 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
3724 _scsih_remove_device(ioc, handle);
3725 break;
3726 }
3727 }
3728
3729 /* handle expander removal */
3730 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
3731 _scsih_expander_remove(ioc, parent_handle);
3732
3733}
3734
3735#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
3736/**
3737 * _scsih_sas_device_status_change_event_debug - debug for device event
3738 * @event_data: event data payload
3739 * Context: user.
3740 *
3741 * Return nothing.
3742 */
3743static void
3744_scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
3745 Mpi2EventDataSasDeviceStatusChange_t *event_data)
3746{
3747 char *reason_str = NULL;
3748
3749 switch (event_data->ReasonCode) {
3750 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
3751 reason_str = "smart data";
3752 break;
3753 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
3754 reason_str = "unsupported device discovered";
3755 break;
3756 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
3757 reason_str = "internal device reset";
3758 break;
3759 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
3760 reason_str = "internal task abort";
3761 break;
3762 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
3763 reason_str = "internal task abort set";
3764 break;
3765 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
3766 reason_str = "internal clear task set";
3767 break;
3768 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
3769 reason_str = "internal query task";
3770 break;
3771 case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
3772 reason_str = "sata init failure";
3773 break;
3774 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
3775 reason_str = "internal device reset complete";
3776 break;
3777 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
3778 reason_str = "internal task abort complete";
3779 break;
3780 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
3781 reason_str = "internal async notification";
3782 break;
3783 default:
3784 reason_str = "unknown reason";
3785 break;
3786 }
3787 printk(MPT2SAS_DEBUG_FMT "device status change: (%s)\n"
3788 "\thandle(0x%04x), sas address(0x%016llx)", ioc->name,
3789 reason_str, le16_to_cpu(event_data->DevHandle),
3790 (unsigned long long)le64_to_cpu(event_data->SASAddress));
3791 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
3792 printk(MPT2SAS_DEBUG_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
3793 event_data->ASC, event_data->ASCQ);
3794 printk(KERN_INFO "\n");
3795}
3796#endif
3797
3798/**
3799 * _scsih_sas_device_status_change_event - handle device status change
3800 * @ioc: per adapter object
3801 * @VF_ID:
3802 * @event_data: event data payload
3803 * Context: user.
3804 *
3805 * Return nothing.
3806 */
3807static void
3808_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
3809 Mpi2EventDataSasDeviceStatusChange_t *event_data)
3810{
3811#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
3812 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
3813 _scsih_sas_device_status_change_event_debug(ioc, event_data);
3814#endif
3815}
3816
3817#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
3818/**
3819 * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure event
3820 * @ioc: per adapter object
3821 * @event_data: event data payload
3822 * Context: user.
3823 *
3824 * Return nothing.
3825 */
3826static void
3827_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
3828 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
3829{
3830 char *reason_str = NULL;
3831
3832 switch (event_data->ReasonCode) {
3833 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
3834 reason_str = "enclosure add";
3835 break;
3836 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
3837 reason_str = "enclosure remove";
3838 break;
3839 default:
3840 reason_str = "unknown reason";
3841 break;
3842 }
3843
3844 printk(MPT2SAS_DEBUG_FMT "enclosure status change: (%s)\n"
3845 "\thandle(0x%04x), enclosure logical id(0x%016llx)"
3846 " number slots(%d)\n", ioc->name, reason_str,
3847 le16_to_cpu(event_data->EnclosureHandle),
3848 (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
3849 le16_to_cpu(event_data->StartSlot));
3850}
3851#endif
3852
3853/**
3854 * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
3855 * @ioc: per adapter object
3856 * @VF_ID:
3857 * @event_data: event data payload
3858 * Context: user.
3859 *
3860 * Return nothing.
3861 */
3862static void
3863_scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
3864 u8 VF_ID, Mpi2EventDataSasEnclDevStatusChange_t *event_data)
3865{
3866#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
3867 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
3868 _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
3869 event_data);
3870#endif
3871}
3872
3873/**
3874 * _scsih_sas_broadcast_primative_event - handle broadcast events
3875 * @ioc: per adapter object
3876 * @event_data: event data payload
3877 * Context: user.
3878 *
3879 * Return nothing.
3880 */
3881static void
3882_scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
3883 Mpi2EventDataSasBroadcastPrimitive_t *event_data)
3884{
3885 struct scsi_cmnd *scmd;
3886 u16 smid, handle;
3887 u32 lun;
3888 struct MPT2SAS_DEVICE *sas_device_priv_data;
3889 u32 termination_count;
3890 u32 query_count;
3891 Mpi2SCSITaskManagementReply_t *mpi_reply;
3892
3893 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: "
3894 "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
3895 event_data->PortWidth));
3896
3897 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
3898 __func__));
3899
3900 mutex_lock(&ioc->tm_cmds.mutex);
3901 termination_count = 0;
3902 query_count = 0;
3903 mpi_reply = ioc->tm_cmds.reply;
3904 for (smid = 1; smid <= ioc->request_depth; smid++) {
3905 scmd = _scsih_scsi_lookup_get(ioc, smid);
3906 if (!scmd)
3907 continue;
3908 sas_device_priv_data = scmd->device->hostdata;
3909 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
3910 continue;
3911 /* skip hidden raid components */
3912 if (sas_device_priv_data->sas_target->flags &
3913 MPT_TARGET_FLAGS_RAID_COMPONENT)
3914 continue;
3915 /* skip volumes */
3916 if (sas_device_priv_data->sas_target->flags &
3917 MPT_TARGET_FLAGS_VOLUME)
3918 continue;
3919
3920 handle = sas_device_priv_data->sas_target->handle;
3921 lun = sas_device_priv_data->lun;
3922 query_count++;
3923
3924 mpt2sas_scsih_issue_tm(ioc, handle, lun,
3925 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30);
3926 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
3927
3928 if ((mpi_reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) &&
3929 (mpi_reply->ResponseCode ==
3930 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
3931 mpi_reply->ResponseCode ==
3932 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
3933 continue;
3934
3935 mpt2sas_scsih_issue_tm(ioc, handle, lun,
3936 MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, smid, 30);
3937 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
3938 }
3939 ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
3940 ioc->broadcast_aen_busy = 0;
3941 mutex_unlock(&ioc->tm_cmds.mutex);
3942
3943 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT
3944 "%s - exit, query_count = %d termination_count = %d\n",
3945 ioc->name, __func__, query_count, termination_count));
3946}
3947
3948/**
3949 * _scsih_sas_discovery_event - handle discovery events
3950 * @ioc: per adapter object
3951 * @event_data: event data payload
3952 * Context: user.
3953 *
3954 * Return nothing.
3955 */
3956static void
3957_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
3958 Mpi2EventDataSasDiscovery_t *event_data)
3959{
3960#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
3961 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
3962 printk(MPT2SAS_DEBUG_FMT "discovery event: (%s)", ioc->name,
3963 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
3964 "start" : "stop");
3965 if (event_data->DiscoveryStatus)
3966 printk(MPT2SAS_DEBUG_FMT ", discovery_status(0x%08x)",
3967 ioc->name, le32_to_cpu(event_data->DiscoveryStatus));
3968 printk("\n");
3969 }
3970#endif
3971
3972 if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
3973 !ioc->sas_hba.num_phys)
3974 _scsih_sas_host_add(ioc);
3975}
3976
3977/**
3978 * _scsih_reprobe_lun - reprobing lun
3979 * @sdev: scsi device struct
3980 * @no_uld_attach: sdev->no_uld_attach flag setting
3981 *
3982 **/
3983static void
3984_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
3985{
3986 int rc;
3987
3988 sdev->no_uld_attach = no_uld_attach ? 1 : 0;
3989 sdev_printk(KERN_INFO, sdev, "%s raid component\n",
3990 sdev->no_uld_attach ? "hidding" : "exposing");
3991 rc = scsi_device_reprobe(sdev);
3992}
3993
3994/**
3995 * _scsih_reprobe_target - reprobing target
3996 * @starget: scsi target struct
3997 * @no_uld_attach: sdev->no_uld_attach flag setting
3998 *
3999 * Note: no_uld_attach flag determines whether the disk device is attached
4000 * to block layer. A value of `1` means to not attach.
4001 **/
4002static void
4003_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
4004{
4005 struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata;
4006
4007 if (no_uld_attach)
4008 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
4009 else
4010 sas_target_priv_data->flags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
4011
4012 starget_for_each_device(starget, no_uld_attach ? (void *)1 : NULL,
4013 _scsih_reprobe_lun);
4014}
4015/**
4016 * _scsih_sas_volume_add - add new volume
4017 * @ioc: per adapter object
4018 * @element: IR config element data
4019 * Context: user.
4020 *
4021 * Return nothing.
4022 */
4023static void
4024_scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
4025 Mpi2EventIrConfigElement_t *element)
4026{
4027 struct _raid_device *raid_device;
4028 unsigned long flags;
4029 u64 wwid;
4030 u16 handle = le16_to_cpu(element->VolDevHandle);
4031 int rc;
4032
4033#if 0 /* RAID_HACKS */
4034 if (le32_to_cpu(event_data->Flags) &
4035 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
4036 return;
4037#endif
4038
4039 mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
4040 if (!wwid) {
4041 printk(MPT2SAS_ERR_FMT
4042 "failure at %s:%d/%s()!\n", ioc->name,
4043 __FILE__, __LINE__, __func__);
4044 return;
4045 }
4046
4047 spin_lock_irqsave(&ioc->raid_device_lock, flags);
4048 raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
4049 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
4050
4051 if (raid_device)
4052 return;
4053
4054 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
4055 if (!raid_device) {
4056 printk(MPT2SAS_ERR_FMT
4057 "failure at %s:%d/%s()!\n", ioc->name,
4058 __FILE__, __LINE__, __func__);
4059 return;
4060 }
4061
4062 raid_device->id = ioc->sas_id++;
4063 raid_device->channel = RAID_CHANNEL;
4064 raid_device->handle = handle;
4065 raid_device->wwid = wwid;
4066 _scsih_raid_device_add(ioc, raid_device);
4067 if (!ioc->wait_for_port_enable_to_complete) {
4068 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
4069 raid_device->id, 0);
4070 if (rc)
4071 _scsih_raid_device_remove(ioc, raid_device);
4072 } else
4073 _scsih_determine_boot_device(ioc, raid_device, 1);
4074}
4075
4076/**
4077 * _scsih_sas_volume_delete - delete volume
4078 * @ioc: per adapter object
4079 * @element: IR config element data
4080 * Context: user.
4081 *
4082 * Return nothing.
4083 */
4084static void
4085_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc,
4086 Mpi2EventIrConfigElement_t *element)
4087{
4088 struct _raid_device *raid_device;
4089 u16 handle = le16_to_cpu(element->VolDevHandle);
4090 unsigned long flags;
4091 struct MPT2SAS_TARGET *sas_target_priv_data;
4092
4093#if 0 /* RAID_HACKS */
4094 if (le32_to_cpu(event_data->Flags) &
4095 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
4096 return;
4097#endif
4098
4099 spin_lock_irqsave(&ioc->raid_device_lock, flags);
4100 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
4101 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
4102 if (!raid_device)
4103 return;
4104 if (raid_device->starget) {
4105 sas_target_priv_data = raid_device->starget->hostdata;
4106 sas_target_priv_data->deleted = 1;
4107 scsi_remove_target(&raid_device->starget->dev);
4108 }
4109 _scsih_raid_device_remove(ioc, raid_device);
4110}
4111
4112/**
4113 * _scsih_sas_pd_expose - expose pd component to /dev/sdX
4114 * @ioc: per adapter object
4115 * @element: IR config element data
4116 * Context: user.
4117 *
4118 * Return nothing.
4119 */
4120static void
4121_scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc,
4122 Mpi2EventIrConfigElement_t *element)
4123{
4124 struct _sas_device *sas_device;
4125 unsigned long flags;
4126 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
4127
4128 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4129 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
4130 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4131 if (!sas_device)
4132 return;
4133
4134 /* exposing raid component */
4135 sas_device->volume_handle = 0;
4136 sas_device->volume_wwid = 0;
4137 sas_device->hidden_raid_component = 0;
4138 _scsih_reprobe_target(sas_device->starget, 0);
4139}
4140
4141/**
4142 * _scsih_sas_pd_hide - hide pd component from /dev/sdX
4143 * @ioc: per adapter object
4144 * @element: IR config element data
4145 * Context: user.
4146 *
4147 * Return nothing.
4148 */
4149static void
4150_scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
4151 Mpi2EventIrConfigElement_t *element)
4152{
4153 struct _sas_device *sas_device;
4154 unsigned long flags;
4155 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
4156
4157 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4158 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
4159 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4160 if (!sas_device)
4161 return;
4162
4163 /* hiding raid component */
4164 mpt2sas_config_get_volume_handle(ioc, handle,
4165 &sas_device->volume_handle);
4166 mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle,
4167 &sas_device->volume_wwid);
4168 sas_device->hidden_raid_component = 1;
4169 _scsih_reprobe_target(sas_device->starget, 1);
4170}
4171
4172/**
4173 * _scsih_sas_pd_delete - delete pd component
4174 * @ioc: per adapter object
4175 * @element: IR config element data
4176 * Context: user.
4177 *
4178 * Return nothing.
4179 */
4180static void
4181_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
4182 Mpi2EventIrConfigElement_t *element)
4183{
4184 struct _sas_device *sas_device;
4185 unsigned long flags;
4186 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
4187
4188 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4189 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
4190 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4191 if (!sas_device)
4192 return;
4193 _scsih_remove_device(ioc, handle);
4194}
4195
4196/**
4197 * _scsih_sas_pd_add - remove pd component
4198 * @ioc: per adapter object
4199 * @element: IR config element data
4200 * Context: user.
4201 *
4202 * Return nothing.
4203 */
4204static void
4205_scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
4206 Mpi2EventIrConfigElement_t *element)
4207{
4208 struct _sas_device *sas_device;
4209 unsigned long flags;
4210 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
4211
4212 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4213 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
4214 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4215 if (sas_device)
4216 sas_device->hidden_raid_component = 1;
4217 else
4218 _scsih_add_device(ioc, handle, 0, 1);
4219}
4220
4221#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4222/**
4223 * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
4224 * @ioc: per adapter object
4225 * @event_data: event data payload
4226 * Context: user.
4227 *
4228 * Return nothing.
4229 */
4230static void
4231_scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
4232 Mpi2EventDataIrConfigChangeList_t *event_data)
4233{
4234 Mpi2EventIrConfigElement_t *element;
4235 u8 element_type;
4236 int i;
4237 char *reason_str = NULL, *element_str = NULL;
4238
4239 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
4240
4241 printk(MPT2SAS_DEBUG_FMT "raid config change: (%s), elements(%d)\n",
4242 ioc->name, (le32_to_cpu(event_data->Flags) &
4243 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
4244 "foreign" : "native", event_data->NumElements);
4245 for (i = 0; i < event_data->NumElements; i++, element++) {
4246 switch (element->ReasonCode) {
4247 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
4248 reason_str = "add";
4249 break;
4250 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
4251 reason_str = "remove";
4252 break;
4253 case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
4254 reason_str = "no change";
4255 break;
4256 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
4257 reason_str = "hide";
4258 break;
4259 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
4260 reason_str = "unhide";
4261 break;
4262 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
4263 reason_str = "volume_created";
4264 break;
4265 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
4266 reason_str = "volume_deleted";
4267 break;
4268 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
4269 reason_str = "pd_created";
4270 break;
4271 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
4272 reason_str = "pd_deleted";
4273 break;
4274 default:
4275 reason_str = "unknown reason";
4276 break;
4277 }
4278 element_type = le16_to_cpu(element->ElementFlags) &
4279 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
4280 switch (element_type) {
4281 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
4282 element_str = "volume";
4283 break;
4284 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
4285 element_str = "phys disk";
4286 break;
4287 case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
4288 element_str = "hot spare";
4289 break;
4290 default:
4291 element_str = "unknown element";
4292 break;
4293 }
4294 printk(KERN_DEBUG "\t(%s:%s), vol handle(0x%04x), "
4295 "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
4296 reason_str, le16_to_cpu(element->VolDevHandle),
4297 le16_to_cpu(element->PhysDiskDevHandle),
4298 element->PhysDiskNum);
4299 }
4300}
4301#endif
4302
4303/**
4304 * _scsih_sas_ir_config_change_event - handle ir configuration change events
4305 * @ioc: per adapter object
4306 * @VF_ID:
4307 * @event_data: event data payload
4308 * Context: user.
4309 *
4310 * Return nothing.
4311 */
4312static void
4313_scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
4314 Mpi2EventDataIrConfigChangeList_t *event_data)
4315{
4316 Mpi2EventIrConfigElement_t *element;
4317 int i;
4318
4319#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4320 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
4321 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
4322
4323#endif
4324
4325 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
4326 for (i = 0; i < event_data->NumElements; i++, element++) {
4327
4328 switch (element->ReasonCode) {
4329 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
4330 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
4331 _scsih_sas_volume_add(ioc, element);
4332 break;
4333 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
4334 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
4335 _scsih_sas_volume_delete(ioc, element);
4336 break;
4337 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
4338 _scsih_sas_pd_hide(ioc, element);
4339 break;
4340 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
4341 _scsih_sas_pd_expose(ioc, element);
4342 break;
4343 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
4344 _scsih_sas_pd_add(ioc, element);
4345 break;
4346 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
4347 _scsih_sas_pd_delete(ioc, element);
4348 break;
4349 }
4350 }
4351}
4352
4353/**
4354 * _scsih_sas_ir_volume_event - IR volume event
4355 * @ioc: per adapter object
4356 * @event_data: event data payload
4357 * Context: user.
4358 *
4359 * Return nothing.
4360 */
4361static void
4362_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
4363 Mpi2EventDataIrVolume_t *event_data)
4364{
4365 u64 wwid;
4366 unsigned long flags;
4367 struct _raid_device *raid_device;
4368 u16 handle;
4369 u32 state;
4370 int rc;
4371 struct MPT2SAS_TARGET *sas_target_priv_data;
4372
4373 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
4374 return;
4375
4376 handle = le16_to_cpu(event_data->VolDevHandle);
4377 state = le32_to_cpu(event_data->NewValue);
4378 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle(0x%04x), "
4379 "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
4380 le32_to_cpu(event_data->PreviousValue), state));
4381
4382 spin_lock_irqsave(&ioc->raid_device_lock, flags);
4383 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
4384 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
4385
4386 switch (state) {
4387 case MPI2_RAID_VOL_STATE_MISSING:
4388 case MPI2_RAID_VOL_STATE_FAILED:
4389 if (!raid_device)
4390 break;
4391 if (raid_device->starget) {
4392 sas_target_priv_data = raid_device->starget->hostdata;
4393 sas_target_priv_data->deleted = 1;
4394 scsi_remove_target(&raid_device->starget->dev);
4395 }
4396 _scsih_raid_device_remove(ioc, raid_device);
4397 break;
4398
4399 case MPI2_RAID_VOL_STATE_ONLINE:
4400 case MPI2_RAID_VOL_STATE_DEGRADED:
4401 case MPI2_RAID_VOL_STATE_OPTIMAL:
4402 if (raid_device)
4403 break;
4404
4405 mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
4406 if (!wwid) {
4407 printk(MPT2SAS_ERR_FMT
4408 "failure at %s:%d/%s()!\n", ioc->name,
4409 __FILE__, __LINE__, __func__);
4410 break;
4411 }
4412
4413 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
4414 if (!raid_device) {
4415 printk(MPT2SAS_ERR_FMT
4416 "failure at %s:%d/%s()!\n", ioc->name,
4417 __FILE__, __LINE__, __func__);
4418 break;
4419 }
4420
4421 raid_device->id = ioc->sas_id++;
4422 raid_device->channel = RAID_CHANNEL;
4423 raid_device->handle = handle;
4424 raid_device->wwid = wwid;
4425 _scsih_raid_device_add(ioc, raid_device);
4426 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
4427 raid_device->id, 0);
4428 if (rc)
4429 _scsih_raid_device_remove(ioc, raid_device);
4430 break;
4431
4432 case MPI2_RAID_VOL_STATE_INITIALIZING:
4433 default:
4434 break;
4435 }
4436}
4437
4438/**
4439 * _scsih_sas_ir_physical_disk_event - PD event
4440 * @ioc: per adapter object
4441 * @event_data: event data payload
4442 * Context: user.
4443 *
4444 * Return nothing.
4445 */
4446static void
4447_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
4448 Mpi2EventDataIrPhysicalDisk_t *event_data)
4449{
4450 u16 handle;
4451 u32 state;
4452 struct _sas_device *sas_device;
4453 unsigned long flags;
4454
4455 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
4456 return;
4457
4458 handle = le16_to_cpu(event_data->PhysDiskDevHandle);
4459 state = le32_to_cpu(event_data->NewValue);
4460
4461 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle(0x%04x), "
4462 "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
4463 le32_to_cpu(event_data->PreviousValue), state));
4464
4465 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4466 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
4467 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4468
4469 switch (state) {
4470#if 0
4471 case MPI2_RAID_PD_STATE_OFFLINE:
4472 if (sas_device)
4473 _scsih_remove_device(ioc, handle);
4474 break;
4475#endif
4476 case MPI2_RAID_PD_STATE_ONLINE:
4477 case MPI2_RAID_PD_STATE_DEGRADED:
4478 case MPI2_RAID_PD_STATE_REBUILDING:
4479 case MPI2_RAID_PD_STATE_OPTIMAL:
4480 if (sas_device)
4481 sas_device->hidden_raid_component = 1;
4482 else
4483 _scsih_add_device(ioc, handle, 0, 1);
4484 break;
4485
4486 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
4487 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
4488 case MPI2_RAID_PD_STATE_HOT_SPARE:
4489 default:
4490 break;
4491 }
4492}
4493
4494#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4495/**
4496 * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
4497 * @ioc: per adapter object
4498 * @event_data: event data payload
4499 * Context: user.
4500 *
4501 * Return nothing.
4502 */
4503static void
4504_scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc,
4505 Mpi2EventDataIrOperationStatus_t *event_data)
4506{
4507 char *reason_str = NULL;
4508
4509 switch (event_data->RAIDOperation) {
4510 case MPI2_EVENT_IR_RAIDOP_RESYNC:
4511 reason_str = "resync";
4512 break;
4513 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
4514 reason_str = "online capacity expansion";
4515 break;
4516 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
4517 reason_str = "consistency check";
4518 break;
4519 default:
4520 reason_str = "unknown reason";
4521 break;
4522 }
4523
4524 printk(MPT2SAS_INFO_FMT "raid operational status: (%s)"
4525 "\thandle(0x%04x), percent complete(%d)\n",
4526 ioc->name, reason_str,
4527 le16_to_cpu(event_data->VolDevHandle),
4528 event_data->PercentComplete);
4529}
4530#endif
4531
4532/**
4533 * _scsih_sas_ir_operation_status_event - handle RAID operation events
4534 * @ioc: per adapter object
4535 * @VF_ID:
4536 * @event_data: event data payload
4537 * Context: user.
4538 *
4539 * Return nothing.
4540 */
4541static void
4542_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
4543 Mpi2EventDataIrOperationStatus_t *event_data)
4544{
4545#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
4546 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
4547 _scsih_sas_ir_operation_status_event_debug(ioc, event_data);
4548#endif
4549}
4550
4551/**
4552 * _scsih_task_set_full - handle task set full
4553 * @ioc: per adapter object
4554 * @event_data: event data payload
4555 * Context: user.
4556 *
4557 * Throttle back qdepth.
4558 */
4559static void
4560_scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
4561 Mpi2EventDataTaskSetFull_t *event_data)
4562{
4563 unsigned long flags;
4564 struct _sas_device *sas_device;
4565 static struct _raid_device *raid_device;
4566 struct scsi_device *sdev;
4567 int depth;
4568 u16 current_depth;
4569 u16 handle;
4570 int id, channel;
4571 u64 sas_address;
4572
4573 current_depth = le16_to_cpu(event_data->CurrentDepth);
4574 handle = le16_to_cpu(event_data->DevHandle);
4575 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4576 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
4577 if (!sas_device) {
4578 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4579 return;
4580 }
4581 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4582 id = sas_device->id;
4583 channel = sas_device->channel;
4584 sas_address = sas_device->sas_address;
4585
4586 /* if hidden raid component, then change to volume characteristics */
4587 if (sas_device->hidden_raid_component && sas_device->volume_handle) {
4588 spin_lock_irqsave(&ioc->raid_device_lock, flags);
4589 raid_device = _scsih_raid_device_find_by_handle(
4590 ioc, sas_device->volume_handle);
4591 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
4592 if (raid_device) {
4593 id = raid_device->id;
4594 channel = raid_device->channel;
4595 handle = raid_device->handle;
4596 sas_address = raid_device->wwid;
4597 }
4598 }
4599
4600 if (ioc->logging_level & MPT_DEBUG_TASK_SET_FULL)
4601 starget_printk(KERN_DEBUG, sas_device->starget, "task set "
4602 "full: handle(0x%04x), sas_addr(0x%016llx), depth(%d)\n",
4603 handle, (unsigned long long)sas_address, current_depth);
4604
4605 shost_for_each_device(sdev, ioc->shost) {
4606 if (sdev->id == id && sdev->channel == channel) {
4607 if (current_depth > sdev->queue_depth) {
4608 if (ioc->logging_level &
4609 MPT_DEBUG_TASK_SET_FULL)
4610 sdev_printk(KERN_INFO, sdev, "strange "
4611 "observation, the queue depth is"
4612 " (%d) meanwhile fw queue depth "
4613 "is (%d)\n", sdev->queue_depth,
4614 current_depth);
4615 continue;
4616 }
4617 depth = scsi_track_queue_full(sdev,
4618 current_depth - 1);
4619 if (depth > 0)
4620 sdev_printk(KERN_INFO, sdev, "Queue depth "
4621 "reduced to (%d)\n", depth);
4622 else if (depth < 0)
4623 sdev_printk(KERN_INFO, sdev, "Tagged Command "
4624 "Queueing is being disabled\n");
4625 else if (depth == 0)
4626 if (ioc->logging_level &
4627 MPT_DEBUG_TASK_SET_FULL)
4628 sdev_printk(KERN_INFO, sdev,
4629 "Queue depth not changed yet\n");
4630 }
4631 }
4632}
4633
4634/**
4635 * _scsih_mark_responding_sas_device - mark a sas_devices as responding
4636 * @ioc: per adapter object
4637 * @sas_address: sas address
4638 * @slot: enclosure slot id
4639 * @handle: device handle
4640 *
4641 * After host reset, find out whether devices are still responding.
4642 * Used in _scsi_remove_unresponsive_sas_devices.
4643 *
4644 * Return nothing.
4645 */
4646static void
4647_scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
4648 u16 slot, u16 handle)
4649{
4650 struct MPT2SAS_TARGET *sas_target_priv_data;
4651 struct scsi_target *starget;
4652 struct _sas_device *sas_device;
4653 unsigned long flags;
4654
4655 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4656 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
4657 if (sas_device->sas_address == sas_address &&
4658 sas_device->slot == slot && sas_device->starget) {
4659 sas_device->responding = 1;
4660 starget_printk(KERN_INFO, sas_device->starget,
4661 "handle(0x%04x), sas_addr(0x%016llx), enclosure "
4662 "logical id(0x%016llx), slot(%d)\n", handle,
4663 (unsigned long long)sas_device->sas_address,
4664 (unsigned long long)
4665 sas_device->enclosure_logical_id,
4666 sas_device->slot);
4667 if (sas_device->handle == handle)
4668 goto out;
4669 printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
4670 sas_device->handle);
4671 sas_device->handle = handle;
4672 starget = sas_device->starget;
4673 sas_target_priv_data = starget->hostdata;
4674 sas_target_priv_data->handle = handle;
4675 goto out;
4676 }
4677 }
4678 out:
4679 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4680}
4681
4682/**
4683 * _scsih_search_responding_sas_devices -
4684 * @ioc: per adapter object
4685 *
4686 * After host reset, find out whether devices are still responding.
4687 * If not remove.
4688 *
4689 * Return nothing.
4690 */
4691static void
4692_scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
4693{
4694 Mpi2SasDevicePage0_t sas_device_pg0;
4695 Mpi2ConfigReply_t mpi_reply;
4696 u16 ioc_status;
4697 __le64 sas_address;
4698 u16 handle;
4699 u32 device_info;
4700 u16 slot;
4701
4702 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
4703
4704 if (list_empty(&ioc->sas_device_list))
4705 return;
4706
4707 handle = 0xFFFF;
4708 while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
4709 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
4710 handle))) {
4711 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4712 MPI2_IOCSTATUS_MASK;
4713 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
4714 break;
4715 handle = le16_to_cpu(sas_device_pg0.DevHandle);
4716 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
4717 if (!(_scsih_is_end_device(device_info)))
4718 continue;
4719 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
4720 slot = le16_to_cpu(sas_device_pg0.Slot);
4721 _scsih_mark_responding_sas_device(ioc, sas_address, slot,
4722 handle);
4723 }
4724}
4725
4726/**
4727 * _scsih_mark_responding_raid_device - mark a raid_device as responding
4728 * @ioc: per adapter object
4729 * @wwid: world wide identifier for raid volume
4730 * @handle: device handle
4731 *
4732 * After host reset, find out whether devices are still responding.
4733 * Used in _scsi_remove_unresponsive_raid_devices.
4734 *
4735 * Return nothing.
4736 */
4737static void
4738_scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
4739 u16 handle)
4740{
4741 struct MPT2SAS_TARGET *sas_target_priv_data;
4742 struct scsi_target *starget;
4743 struct _raid_device *raid_device;
4744 unsigned long flags;
4745
4746 spin_lock_irqsave(&ioc->raid_device_lock, flags);
4747 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
4748 if (raid_device->wwid == wwid && raid_device->starget) {
4749 raid_device->responding = 1;
4750 starget_printk(KERN_INFO, raid_device->starget,
4751 "handle(0x%04x), wwid(0x%016llx)\n", handle,
4752 (unsigned long long)raid_device->wwid);
4753 if (raid_device->handle == handle)
4754 goto out;
4755 printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
4756 raid_device->handle);
4757 raid_device->handle = handle;
4758 starget = raid_device->starget;
4759 sas_target_priv_data = starget->hostdata;
4760 sas_target_priv_data->handle = handle;
4761 goto out;
4762 }
4763 }
4764 out:
4765 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
4766}
4767
4768/**
4769 * _scsih_search_responding_raid_devices -
4770 * @ioc: per adapter object
4771 *
4772 * After host reset, find out whether devices are still responding.
4773 * If not remove.
4774 *
4775 * Return nothing.
4776 */
4777static void
4778_scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
4779{
4780 Mpi2RaidVolPage1_t volume_pg1;
4781 Mpi2ConfigReply_t mpi_reply;
4782 u16 ioc_status;
4783 u16 handle;
4784
4785 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
4786
4787 if (list_empty(&ioc->raid_device_list))
4788 return;
4789
4790 handle = 0xFFFF;
4791 while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
4792 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
4793 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4794 MPI2_IOCSTATUS_MASK;
4795 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
4796 break;
4797 handle = le16_to_cpu(volume_pg1.DevHandle);
4798 _scsih_mark_responding_raid_device(ioc,
4799 le64_to_cpu(volume_pg1.WWID), handle);
4800 }
4801}
4802
4803/**
4804 * _scsih_mark_responding_expander - mark a expander as responding
4805 * @ioc: per adapter object
4806 * @sas_address: sas address
4807 * @handle:
4808 *
4809 * After host reset, find out whether devices are still responding.
4810 * Used in _scsi_remove_unresponsive_expanders.
4811 *
4812 * Return nothing.
4813 */
4814static void
4815_scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
4816 u16 handle)
4817{
4818 struct _sas_node *sas_expander;
4819 unsigned long flags;
4820
4821 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4822 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
4823 if (sas_expander->sas_address == sas_address) {
4824 sas_expander->responding = 1;
4825 if (sas_expander->handle != handle) {
4826 printk(KERN_INFO "old handle(0x%04x)\n",
4827 sas_expander->handle);
4828 sas_expander->handle = handle;
4829 }
4830 goto out;
4831 }
4832 }
4833 out:
4834 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4835}
4836
4837/**
4838 * _scsih_search_responding_expanders -
4839 * @ioc: per adapter object
4840 *
4841 * After host reset, find out whether devices are still responding.
4842 * If not remove.
4843 *
4844 * Return nothing.
4845 */
4846static void
4847_scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
4848{
4849 Mpi2ExpanderPage0_t expander_pg0;
4850 Mpi2ConfigReply_t mpi_reply;
4851 u16 ioc_status;
4852 __le64 sas_address;
4853 u16 handle;
4854
4855 printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
4856
4857 if (list_empty(&ioc->sas_expander_list))
4858 return;
4859
4860 handle = 0xFFFF;
4861 while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
4862 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
4863
4864 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4865 MPI2_IOCSTATUS_MASK;
4866 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
4867 break;
4868
4869 handle = le16_to_cpu(expander_pg0.DevHandle);
4870 sas_address = le64_to_cpu(expander_pg0.SASAddress);
4871 printk(KERN_INFO "\texpander present: handle(0x%04x), "
4872 "sas_addr(0x%016llx)\n", handle,
4873 (unsigned long long)sas_address);
4874 _scsih_mark_responding_expander(ioc, sas_address, handle);
4875 }
4876
4877}
4878
4879/**
4880 * _scsih_remove_unresponding_devices - removing unresponding devices
4881 * @ioc: per adapter object
4882 *
4883 * Return nothing.
4884 */
4885static void
4886_scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
4887{
4888 struct _sas_device *sas_device, *sas_device_next;
4889 struct _sas_node *sas_expander, *sas_expander_next;
4890 struct _raid_device *raid_device, *raid_device_next;
4891 unsigned long flags;
4892
4893 _scsih_search_responding_sas_devices(ioc);
4894 _scsih_search_responding_raid_devices(ioc);
4895 _scsih_search_responding_expanders(ioc);
4896
4897 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
4898 ioc->shost_recovery = 0;
4899 if (ioc->shost->shost_state == SHOST_RECOVERY) {
4900 printk(MPT2SAS_INFO_FMT "putting controller into "
4901 "SHOST_RUNNING\n", ioc->name);
4902 scsi_host_set_state(ioc->shost, SHOST_RUNNING);
4903 }
4904 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
4905
4906 list_for_each_entry_safe(sas_device, sas_device_next,
4907 &ioc->sas_device_list, list) {
4908 if (sas_device->responding) {
4909 sas_device->responding = 0;
4910 continue;
4911 }
4912 if (sas_device->starget)
4913 starget_printk(KERN_INFO, sas_device->starget,
4914 "removing: handle(0x%04x), sas_addr(0x%016llx), "
4915 "enclosure logical id(0x%016llx), slot(%d)\n",
4916 sas_device->handle,
4917 (unsigned long long)sas_device->sas_address,
4918 (unsigned long long)
4919 sas_device->enclosure_logical_id,
4920 sas_device->slot);
4921 _scsih_remove_device(ioc, sas_device->handle);
4922 }
4923
4924 list_for_each_entry_safe(raid_device, raid_device_next,
4925 &ioc->raid_device_list, list) {
4926 if (raid_device->responding) {
4927 raid_device->responding = 0;
4928 continue;
4929 }
4930 if (raid_device->starget) {
4931 starget_printk(KERN_INFO, raid_device->starget,
4932 "removing: handle(0x%04x), wwid(0x%016llx)\n",
4933 raid_device->handle,
4934 (unsigned long long)raid_device->wwid);
4935 scsi_remove_target(&raid_device->starget->dev);
4936 }
4937 _scsih_raid_device_remove(ioc, raid_device);
4938 }
4939
4940 list_for_each_entry_safe(sas_expander, sas_expander_next,
4941 &ioc->sas_expander_list, list) {
4942 if (sas_expander->responding) {
4943 sas_expander->responding = 0;
4944 continue;
4945 }
4946 printk("\tremoving expander: handle(0x%04x), "
4947 " sas_addr(0x%016llx)\n", sas_expander->handle,
4948 (unsigned long long)sas_expander->sas_address);
4949 _scsih_expander_remove(ioc, sas_expander->handle);
4950 }
4951}
4952
4953/**
4954 * _firmware_event_work - delayed task for processing firmware events
4955 * @ioc: per adapter object
4956 * @work: equal to the fw_event_work object
4957 * Context: user.
4958 *
4959 * Return nothing.
4960 */
4961static void
4962_firmware_event_work(struct work_struct *work)
4963{
4964 struct fw_event_work *fw_event = container_of(work,
4965 struct fw_event_work, work.work);
4966 unsigned long flags;
4967 struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
4968
4969 /* This is invoked by calling _scsih_queue_rescan(). */
4970 if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
4971 _scsih_fw_event_free(ioc, fw_event);
4972 _scsih_sas_host_refresh(ioc, 1);
4973 _scsih_remove_unresponding_devices(ioc);
4974 return;
4975 }
4976
4977 /* the queue is being flushed so ignore this event */
4978 spin_lock_irqsave(&ioc->fw_event_lock, flags);
4979 if (ioc->fw_events_off || ioc->remove_host) {
4980 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
4981 _scsih_fw_event_free(ioc, fw_event);
4982 return;
4983 }
4984 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
4985
4986 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
4987 if (ioc->shost_recovery) {
4988 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
4989 _scsih_fw_event_requeue(ioc, fw_event, 1000);
4990 return;
4991 }
4992 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
4993
4994 switch (fw_event->event) {
4995 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
4996 _scsih_sas_topology_change_event(ioc, fw_event->VF_ID,
4997 fw_event->event_data, fw_event);
4998 break;
4999 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
5000 _scsih_sas_device_status_change_event(ioc, fw_event->VF_ID,
5001 fw_event->event_data);
5002 break;
5003 case MPI2_EVENT_SAS_DISCOVERY:
5004 _scsih_sas_discovery_event(ioc, fw_event->VF_ID,
5005 fw_event->event_data);
5006 break;
5007 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
5008 _scsih_sas_broadcast_primative_event(ioc, fw_event->VF_ID,
5009 fw_event->event_data);
5010 break;
5011 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
5012 _scsih_sas_enclosure_dev_status_change_event(ioc,
5013 fw_event->VF_ID, fw_event->event_data);
5014 break;
5015 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
5016 _scsih_sas_ir_config_change_event(ioc, fw_event->VF_ID,
5017 fw_event->event_data);
5018 break;
5019 case MPI2_EVENT_IR_VOLUME:
5020 _scsih_sas_ir_volume_event(ioc, fw_event->VF_ID,
5021 fw_event->event_data);
5022 break;
5023 case MPI2_EVENT_IR_PHYSICAL_DISK:
5024 _scsih_sas_ir_physical_disk_event(ioc, fw_event->VF_ID,
5025 fw_event->event_data);
5026 break;
5027 case MPI2_EVENT_IR_OPERATION_STATUS:
5028 _scsih_sas_ir_operation_status_event(ioc, fw_event->VF_ID,
5029 fw_event->event_data);
5030 break;
5031 case MPI2_EVENT_TASK_SET_FULL:
5032 _scsih_task_set_full(ioc, fw_event->VF_ID,
5033 fw_event->event_data);
5034 break;
5035 }
5036 _scsih_fw_event_free(ioc, fw_event);
5037}
5038
5039/**
5040 * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time)
5041 * @ioc: per adapter object
5042 * @VF_ID: virtual function id
5043 * @reply: reply message frame(lower 32bit addr)
5044 * Context: interrupt.
5045 *
5046 * This function merely adds a new work task into ioc->firmware_event_thread.
5047 * The tasks are worked from _firmware_event_work in user context.
5048 *
5049 * Return nothing.
5050 */
5051void
5052mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
5053{
5054 struct fw_event_work *fw_event;
5055 Mpi2EventNotificationReply_t *mpi_reply;
5056 unsigned long flags;
5057 u16 event;
5058
5059 /* events turned off due to host reset or driver unloading */
5060 spin_lock_irqsave(&ioc->fw_event_lock, flags);
5061 if (ioc->fw_events_off || ioc->remove_host) {
5062 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
5063 return;
5064 }
5065 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
5066
5067 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
5068 event = le16_to_cpu(mpi_reply->Event);
5069
5070 switch (event) {
5071 /* handle these */
5072 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
5073 {
5074 Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
5075 (Mpi2EventDataSasBroadcastPrimitive_t *)
5076 mpi_reply->EventData;
5077
5078 if (baen_data->Primitive !=
5079 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT ||
5080 ioc->broadcast_aen_busy)
5081 return;
5082 ioc->broadcast_aen_busy = 1;
5083 break;
5084 }
5085
5086 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
5087 _scsih_check_topo_delete_events(ioc,
5088 (Mpi2EventDataSasTopologyChangeList_t *)
5089 mpi_reply->EventData);
5090 break;
5091
5092 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
5093 case MPI2_EVENT_IR_OPERATION_STATUS:
5094 case MPI2_EVENT_SAS_DISCOVERY:
5095 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
5096 case MPI2_EVENT_IR_VOLUME:
5097 case MPI2_EVENT_IR_PHYSICAL_DISK:
5098 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
5099 case MPI2_EVENT_TASK_SET_FULL:
5100 break;
5101
5102 default: /* ignore the rest */
5103 return;
5104 }
5105
5106 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
5107 if (!fw_event) {
5108 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5109 ioc->name, __FILE__, __LINE__, __func__);
5110 return;
5111 }
5112 fw_event->event_data =
5113 kzalloc(mpi_reply->EventDataLength*4, GFP_ATOMIC);
5114 if (!fw_event->event_data) {
5115 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5116 ioc->name, __FILE__, __LINE__, __func__);
5117 kfree(fw_event);
5118 return;
5119 }
5120
5121 memcpy(fw_event->event_data, mpi_reply->EventData,
5122 mpi_reply->EventDataLength*4);
5123 fw_event->ioc = ioc;
5124 fw_event->VF_ID = VF_ID;
5125 fw_event->event = event;
5126 _scsih_fw_event_add(ioc, fw_event);
5127}
5128
5129/* shost template */
5130static struct scsi_host_template scsih_driver_template = {
5131 .module = THIS_MODULE,
5132 .name = "Fusion MPT SAS Host",
5133 .proc_name = MPT2SAS_DRIVER_NAME,
5134 .queuecommand = scsih_qcmd,
5135 .target_alloc = scsih_target_alloc,
5136 .slave_alloc = scsih_slave_alloc,
5137 .slave_configure = scsih_slave_configure,
5138 .target_destroy = scsih_target_destroy,
5139 .slave_destroy = scsih_slave_destroy,
5140 .change_queue_depth = scsih_change_queue_depth,
5141 .change_queue_type = scsih_change_queue_type,
5142 .eh_abort_handler = scsih_abort,
5143 .eh_device_reset_handler = scsih_dev_reset,
5144 .eh_host_reset_handler = scsih_host_reset,
5145 .bios_param = scsih_bios_param,
5146 .can_queue = 1,
5147 .this_id = -1,
5148 .sg_tablesize = MPT2SAS_SG_DEPTH,
5149 .max_sectors = 8192,
5150 .cmd_per_lun = 7,
5151 .use_clustering = ENABLE_CLUSTERING,
5152 .shost_attrs = mpt2sas_host_attrs,
5153 .sdev_attrs = mpt2sas_dev_attrs,
5154};
5155
5156/**
5157 * _scsih_expander_node_remove - removing expander device from list.
5158 * @ioc: per adapter object
5159 * @sas_expander: the sas_device object
5160 * Context: Calling function should acquire ioc->sas_node_lock.
5161 *
5162 * Removing object and freeing associated memory from the
5163 * ioc->sas_expander_list.
5164 *
5165 * Return nothing.
5166 */
5167static void
5168_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
5169 struct _sas_node *sas_expander)
5170{
5171 struct _sas_port *mpt2sas_port;
5172 struct _sas_device *sas_device;
5173 struct _sas_node *expander_sibling;
5174 unsigned long flags;
5175
5176 if (!sas_expander)
5177 return;
5178
5179 /* remove sibling ports attached to this expander */
5180 retry_device_search:
5181 list_for_each_entry(mpt2sas_port,
5182 &sas_expander->sas_port_list, port_list) {
5183 if (mpt2sas_port->remote_identify.device_type ==
5184 SAS_END_DEVICE) {
5185 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5186 sas_device =
5187 mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5188 mpt2sas_port->remote_identify.sas_address);
5189 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5190 if (!sas_device)
5191 continue;
5192 _scsih_remove_device(ioc, sas_device->handle);
5193 goto retry_device_search;
5194 }
5195 }
5196
5197 retry_expander_search:
5198 list_for_each_entry(mpt2sas_port,
5199 &sas_expander->sas_port_list, port_list) {
5200
5201 if (mpt2sas_port->remote_identify.device_type ==
5202 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
5203 mpt2sas_port->remote_identify.device_type ==
5204 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
5205
5206 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5207 expander_sibling =
5208 mpt2sas_scsih_expander_find_by_sas_address(
5209 ioc, mpt2sas_port->remote_identify.sas_address);
5210 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5211 if (!expander_sibling)
5212 continue;
5213 _scsih_expander_remove(ioc, expander_sibling->handle);
5214 goto retry_expander_search;
5215 }
5216 }
5217
5218 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
5219 sas_expander->parent_handle);
5220
5221 printk(MPT2SAS_INFO_FMT "expander_remove: handle"
5222 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
5223 sas_expander->handle, (unsigned long long)
5224 sas_expander->sas_address);
5225
5226 list_del(&sas_expander->list);
5227 kfree(sas_expander->phy);
5228 kfree(sas_expander);
5229}
5230
5231/**
5232 * scsih_remove - detach and remove add host
5233 * @pdev: PCI device struct
5234 *
5235 * Return nothing.
5236 */
5237static void __devexit
5238scsih_remove(struct pci_dev *pdev)
5239{
5240 struct Scsi_Host *shost = pci_get_drvdata(pdev);
5241 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
5242 struct _sas_port *mpt2sas_port;
5243 struct _sas_device *sas_device;
5244 struct _sas_node *expander_sibling;
5245 struct workqueue_struct *wq;
5246 unsigned long flags;
5247
5248 ioc->remove_host = 1;
5249 _scsih_fw_event_off(ioc);
5250
5251 spin_lock_irqsave(&ioc->fw_event_lock, flags);
5252 wq = ioc->firmware_event_thread;
5253 ioc->firmware_event_thread = NULL;
5254 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
5255 if (wq)
5256 destroy_workqueue(wq);
5257
5258 /* free ports attached to the sas_host */
5259 retry_again:
5260 list_for_each_entry(mpt2sas_port,
5261 &ioc->sas_hba.sas_port_list, port_list) {
5262 if (mpt2sas_port->remote_identify.device_type ==
5263 SAS_END_DEVICE) {
5264 sas_device =
5265 mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5266 mpt2sas_port->remote_identify.sas_address);
5267 if (sas_device) {
5268 _scsih_remove_device(ioc, sas_device->handle);
5269 goto retry_again;
5270 }
5271 } else {
5272 expander_sibling =
5273 mpt2sas_scsih_expander_find_by_sas_address(ioc,
5274 mpt2sas_port->remote_identify.sas_address);
5275 if (expander_sibling) {
5276 _scsih_expander_remove(ioc,
5277 expander_sibling->handle);
5278 goto retry_again;
5279 }
5280 }
5281 }
5282
5283 /* free phys attached to the sas_host */
5284 if (ioc->sas_hba.num_phys) {
5285 kfree(ioc->sas_hba.phy);
5286 ioc->sas_hba.phy = NULL;
5287 ioc->sas_hba.num_phys = 0;
5288 }
5289
5290 sas_remove_host(shost);
5291 mpt2sas_base_detach(ioc);
5292 list_del(&ioc->list);
5293 scsi_remove_host(shost);
5294 scsi_host_put(shost);
5295}
5296
5297/**
5298 * _scsih_probe_boot_devices - reports 1st device
5299 * @ioc: per adapter object
5300 *
5301 * If specified in bios page 2, this routine reports the 1st
5302 * device scsi-ml or sas transport for persistent boot device
5303 * purposes. Please refer to function _scsih_determine_boot_device()
5304 */
5305static void
5306_scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
5307{
5308 u8 is_raid;
5309 void *device;
5310 struct _sas_device *sas_device;
5311 struct _raid_device *raid_device;
5312 u16 handle, parent_handle;
5313 u64 sas_address;
5314 unsigned long flags;
5315 int rc;
5316
5317 device = NULL;
5318 if (ioc->req_boot_device.device) {
5319 device = ioc->req_boot_device.device;
5320 is_raid = ioc->req_boot_device.is_raid;
5321 } else if (ioc->req_alt_boot_device.device) {
5322 device = ioc->req_alt_boot_device.device;
5323 is_raid = ioc->req_alt_boot_device.is_raid;
5324 } else if (ioc->current_boot_device.device) {
5325 device = ioc->current_boot_device.device;
5326 is_raid = ioc->current_boot_device.is_raid;
5327 }
5328
5329 if (!device)
5330 return;
5331
5332 if (is_raid) {
5333 raid_device = device;
5334 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
5335 raid_device->id, 0);
5336 if (rc)
5337 _scsih_raid_device_remove(ioc, raid_device);
5338 } else {
5339 sas_device = device;
5340 handle = sas_device->handle;
5341 parent_handle = sas_device->parent_handle;
5342 sas_address = sas_device->sas_address;
5343 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5344 list_move_tail(&sas_device->list, &ioc->sas_device_list);
5345 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5346 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
5347 sas_device->parent_handle)) {
5348 _scsih_sas_device_remove(ioc, sas_device);
5349 } else if (!sas_device->starget) {
5350 mpt2sas_transport_port_remove(ioc, sas_address,
5351 parent_handle);
5352 _scsih_sas_device_remove(ioc, sas_device);
5353 }
5354 }
5355}
5356
5357/**
5358 * _scsih_probe_raid - reporting raid volumes to scsi-ml
5359 * @ioc: per adapter object
5360 *
5361 * Called during initial loading of the driver.
5362 */
5363static void
5364_scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc)
5365{
5366 struct _raid_device *raid_device, *raid_next;
5367 int rc;
5368
5369 list_for_each_entry_safe(raid_device, raid_next,
5370 &ioc->raid_device_list, list) {
5371 if (raid_device->starget)
5372 continue;
5373 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
5374 raid_device->id, 0);
5375 if (rc)
5376 _scsih_raid_device_remove(ioc, raid_device);
5377 }
5378}
5379
5380/**
5381 * _scsih_probe_sas - reporting raid volumes to sas transport
5382 * @ioc: per adapter object
5383 *
5384 * Called during initial loading of the driver.
5385 */
5386static void
5387_scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
5388{
5389 struct _sas_device *sas_device, *next;
5390 unsigned long flags;
5391 u16 handle, parent_handle;
5392 u64 sas_address;
5393
5394 /* SAS Device List */
5395 list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
5396 list) {
5397 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5398 list_move_tail(&sas_device->list, &ioc->sas_device_list);
5399 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5400
5401 handle = sas_device->handle;
5402 parent_handle = sas_device->parent_handle;
5403 sas_address = sas_device->sas_address;
5404 if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) {
5405 _scsih_sas_device_remove(ioc, sas_device);
5406 } else if (!sas_device->starget) {
5407 mpt2sas_transport_port_remove(ioc, sas_address,
5408 parent_handle);
5409 _scsih_sas_device_remove(ioc, sas_device);
5410 }
5411 }
5412}
5413
5414/**
5415 * _scsih_probe_devices - probing for devices
5416 * @ioc: per adapter object
5417 *
5418 * Called during initial loading of the driver.
5419 */
5420static void
5421_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
5422{
5423 u16 volume_mapping_flags =
5424 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
5425 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
5426
5427 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
5428 return; /* return when IOC doesn't support initiator mode */
5429
5430 _scsih_probe_boot_devices(ioc);
5431
5432 if (ioc->ir_firmware) {
5433 if ((volume_mapping_flags &
5434 MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) {
5435 _scsih_probe_sas(ioc);
5436 _scsih_probe_raid(ioc);
5437 } else {
5438 _scsih_probe_raid(ioc);
5439 _scsih_probe_sas(ioc);
5440 }
5441 } else
5442 _scsih_probe_sas(ioc);
5443}
5444
5445/**
5446 * scsih_probe - attach and add scsi host
5447 * @pdev: PCI device struct
5448 * @id: pci device id
5449 *
5450 * Returns 0 success, anything else error.
5451 */
5452static int
5453scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
5454{
5455 struct MPT2SAS_ADAPTER *ioc;
5456 struct Scsi_Host *shost;
5457
5458 shost = scsi_host_alloc(&scsih_driver_template,
5459 sizeof(struct MPT2SAS_ADAPTER));
5460 if (!shost)
5461 return -ENODEV;
5462
5463 /* init local params */
5464 ioc = shost_priv(shost);
5465 memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER));
5466 INIT_LIST_HEAD(&ioc->list);
5467 list_add_tail(&ioc->list, &ioc_list);
5468 ioc->shost = shost;
5469 ioc->id = mpt_ids++;
5470 sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id);
5471 ioc->pdev = pdev;
5472 ioc->scsi_io_cb_idx = scsi_io_cb_idx;
5473 ioc->tm_cb_idx = tm_cb_idx;
5474 ioc->ctl_cb_idx = ctl_cb_idx;
5475 ioc->base_cb_idx = base_cb_idx;
5476 ioc->transport_cb_idx = transport_cb_idx;
5477 ioc->config_cb_idx = config_cb_idx;
5478 ioc->logging_level = logging_level;
5479 /* misc semaphores and spin locks */
5480 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
5481 spin_lock_init(&ioc->scsi_lookup_lock);
5482 spin_lock_init(&ioc->sas_device_lock);
5483 spin_lock_init(&ioc->sas_node_lock);
5484 spin_lock_init(&ioc->fw_event_lock);
5485 spin_lock_init(&ioc->raid_device_lock);
5486
5487 INIT_LIST_HEAD(&ioc->sas_device_list);
5488 INIT_LIST_HEAD(&ioc->sas_device_init_list);
5489 INIT_LIST_HEAD(&ioc->sas_expander_list);
5490 INIT_LIST_HEAD(&ioc->fw_event_list);
5491 INIT_LIST_HEAD(&ioc->raid_device_list);
5492 INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
5493
5494 /* init shost parameters */
5495 shost->max_cmd_len = 16;
5496 shost->max_lun = max_lun;
5497 shost->transportt = mpt2sas_transport_template;
5498 shost->unique_id = ioc->id;
5499
5500 if ((scsi_add_host(shost, &pdev->dev))) {
5501 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5502 ioc->name, __FILE__, __LINE__, __func__);
5503 list_del(&ioc->list);
5504 goto out_add_shost_fail;
5505 }
5506
5507 /* event thread */
5508 snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
5509 "fw_event%d", ioc->id);
5510 ioc->firmware_event_thread = create_singlethread_workqueue(
5511 ioc->firmware_event_name);
5512 if (!ioc->firmware_event_thread) {
5513 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5514 ioc->name, __FILE__, __LINE__, __func__);
5515 goto out_thread_fail;
5516 }
5517
5518 ioc->wait_for_port_enable_to_complete = 1;
5519 if ((mpt2sas_base_attach(ioc))) {
5520 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
5521 ioc->name, __FILE__, __LINE__, __func__);
5522 goto out_attach_fail;
5523 }
5524
5525 ioc->wait_for_port_enable_to_complete = 0;
5526 _scsih_probe_devices(ioc);
5527 return 0;
5528
5529 out_attach_fail:
5530 destroy_workqueue(ioc->firmware_event_thread);
5531 out_thread_fail:
5532 list_del(&ioc->list);
5533 scsi_remove_host(shost);
5534 out_add_shost_fail:
5535 return -ENODEV;
5536}
5537
5538#ifdef CONFIG_PM
5539/**
5540 * scsih_suspend - power management suspend main entry point
5541 * @pdev: PCI device struct
5542 * @state: PM state change to (usually PCI_D3)
5543 *
5544 * Returns 0 success, anything else error.
5545 */
5546static int
5547scsih_suspend(struct pci_dev *pdev, pm_message_t state)
5548{
5549 struct Scsi_Host *shost = pci_get_drvdata(pdev);
5550 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
5551 u32 device_state;
5552
5553 flush_scheduled_work();
5554 scsi_block_requests(shost);
5555 device_state = pci_choose_state(pdev, state);
5556 printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering "
5557 "operating state [D%d]\n", ioc->name, pdev,
5558 pci_name(pdev), device_state);
5559
5560 mpt2sas_base_free_resources(ioc);
5561 pci_save_state(pdev);
5562 pci_disable_device(pdev);
5563 pci_set_power_state(pdev, device_state);
5564 return 0;
5565}
5566
5567/**
5568 * scsih_resume - power management resume main entry point
5569 * @pdev: PCI device struct
5570 *
5571 * Returns 0 success, anything else error.
5572 */
5573static int
5574scsih_resume(struct pci_dev *pdev)
5575{
5576 struct Scsi_Host *shost = pci_get_drvdata(pdev);
5577 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
5578 u32 device_state = pdev->current_state;
5579 int r;
5580
5581 printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
5582 "operating state [D%d]\n", ioc->name, pdev,
5583 pci_name(pdev), device_state);
5584
5585 pci_set_power_state(pdev, PCI_D0);
5586 pci_enable_wake(pdev, PCI_D0, 0);
5587 pci_restore_state(pdev);
5588 ioc->pdev = pdev;
5589 r = mpt2sas_base_map_resources(ioc);
5590 if (r)
5591 return r;
5592
5593 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
5594 scsi_unblock_requests(shost);
5595 return 0;
5596}
5597#endif /* CONFIG_PM */
5598
5599
5600static struct pci_driver scsih_driver = {
5601 .name = MPT2SAS_DRIVER_NAME,
5602 .id_table = scsih_pci_table,
5603 .probe = scsih_probe,
5604 .remove = __devexit_p(scsih_remove),
5605#ifdef CONFIG_PM
5606 .suspend = scsih_suspend,
5607 .resume = scsih_resume,
5608#endif
5609};
5610
5611
5612/**
5613 * scsih_init - main entry point for this driver.
5614 *
5615 * Returns 0 success, anything else error.
5616 */
5617static int __init
5618scsih_init(void)
5619{
5620 int error;
5621
5622 mpt_ids = 0;
5623 printk(KERN_INFO "%s version %s loaded\n", MPT2SAS_DRIVER_NAME,
5624 MPT2SAS_DRIVER_VERSION);
5625
5626 mpt2sas_transport_template =
5627 sas_attach_transport(&mpt2sas_transport_functions);
5628 if (!mpt2sas_transport_template)
5629 return -ENODEV;
5630
5631 mpt2sas_base_initialize_callback_handler();
5632
5633 /* queuecommand callback hander */
5634 scsi_io_cb_idx = mpt2sas_base_register_callback_handler(scsih_io_done);
5635
5636 /* task managment callback handler */
5637 tm_cb_idx = mpt2sas_base_register_callback_handler(scsih_tm_done);
5638
5639 /* base internal commands callback handler */
5640 base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
5641
5642 /* transport internal commands callback handler */
5643 transport_cb_idx = mpt2sas_base_register_callback_handler(
5644 mpt2sas_transport_done);
5645
5646 /* configuration page API internal commands callback handler */
5647 config_cb_idx = mpt2sas_base_register_callback_handler(
5648 mpt2sas_config_done);
5649
5650 /* ctl module callback handler */
5651 ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done);
5652
5653 mpt2sas_ctl_init();
5654
5655 error = pci_register_driver(&scsih_driver);
5656 if (error)
5657 sas_release_transport(mpt2sas_transport_template);
5658
5659 return error;
5660}
5661
5662/**
5663 * scsih_exit - exit point for this driver (when it is a module).
5664 *
5665 * Returns 0 success, anything else error.
5666 */
5667static void __exit
5668scsih_exit(void)
5669{
5670 printk(KERN_INFO "mpt2sas version %s unloading\n",
5671 MPT2SAS_DRIVER_VERSION);
5672
5673 pci_unregister_driver(&scsih_driver);
5674
5675 sas_release_transport(mpt2sas_transport_template);
5676 mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
5677 mpt2sas_base_release_callback_handler(tm_cb_idx);
5678 mpt2sas_base_release_callback_handler(base_cb_idx);
5679 mpt2sas_base_release_callback_handler(transport_cb_idx);
5680 mpt2sas_base_release_callback_handler(config_cb_idx);
5681 mpt2sas_base_release_callback_handler(ctl_cb_idx);
5682
5683 mpt2sas_ctl_exit();
5684}
5685
5686module_init(scsih_init);
5687module_exit(scsih_exit);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
new file mode 100644
index 000000000000..e03dc0b1e1a0
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -0,0 +1,1211 @@
1/*
2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
5 * Copyright (C) 2007-2008 LSI Corporation
6 * (mailto:DL-MPTFusionLinux@lsi.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * NO WARRANTY
19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23 * solely responsible for determining the appropriateness of using and
24 * distributing the Program and assumes all risks associated with its
25 * exercise of rights under this Agreement, including but not limited to
26 * the risks and costs of program errors, damage to or loss of data,
27 * programs or equipment, and unavailability or interruption of operations.
28
29 * DISCLAIMER OF LIABILITY
30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
41 * USA.
42 */
43
44#include <linux/module.h>
45#include <linux/kernel.h>
46#include <linux/init.h>
47#include <linux/errno.h>
48#include <linux/sched.h>
49#include <linux/workqueue.h>
50#include <linux/delay.h>
51#include <linux/pci.h>
52
53#include <scsi/scsi.h>
54#include <scsi/scsi_cmnd.h>
55#include <scsi/scsi_device.h>
56#include <scsi/scsi_host.h>
57#include <scsi/scsi_transport_sas.h>
58#include <scsi/scsi_dbg.h>
59
60#include "mpt2sas_base.h"
61/**
62 * _transport_sas_node_find_by_handle - sas node search
63 * @ioc: per adapter object
64 * @handle: expander or hba handle (assigned by firmware)
65 * Context: Calling function should acquire ioc->sas_node_lock.
66 *
67 * Search for either hba phys or expander device based on handle, then returns
68 * the sas_node object.
69 */
70static struct _sas_node *
71_transport_sas_node_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
72{
73 int i;
74
75 for (i = 0; i < ioc->sas_hba.num_phys; i++)
76 if (ioc->sas_hba.phy[i].handle == handle)
77 return &ioc->sas_hba;
78
79 return mpt2sas_scsih_expander_find_by_handle(ioc, handle);
80}
81
82/**
83 * _transport_convert_phy_link_rate -
84 * @link_rate: link rate returned from mpt firmware
85 *
86 * Convert link_rate from mpi fusion into sas_transport form.
87 */
88static enum sas_linkrate
89_transport_convert_phy_link_rate(u8 link_rate)
90{
91 enum sas_linkrate rc;
92
93 switch (link_rate) {
94 case MPI2_SAS_NEG_LINK_RATE_1_5:
95 rc = SAS_LINK_RATE_1_5_GBPS;
96 break;
97 case MPI2_SAS_NEG_LINK_RATE_3_0:
98 rc = SAS_LINK_RATE_3_0_GBPS;
99 break;
100 case MPI2_SAS_NEG_LINK_RATE_6_0:
101 rc = SAS_LINK_RATE_6_0_GBPS;
102 break;
103 case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
104 rc = SAS_PHY_DISABLED;
105 break;
106 case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
107 rc = SAS_LINK_RATE_FAILED;
108 break;
109 case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
110 rc = SAS_SATA_PORT_SELECTOR;
111 break;
112 case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
113 rc = SAS_PHY_RESET_IN_PROGRESS;
114 break;
115 default:
116 case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
117 case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
118 rc = SAS_LINK_RATE_UNKNOWN;
119 break;
120 }
121 return rc;
122}
123
124/**
125 * _transport_set_identify - set identify for phys and end devices
126 * @ioc: per adapter object
127 * @handle: device handle
128 * @identify: sas identify info
129 *
130 * Populates sas identify info.
131 *
132 * Returns 0 for success, non-zero for failure.
133 */
134static int
135_transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
136 struct sas_identify *identify)
137{
138 Mpi2SasDevicePage0_t sas_device_pg0;
139 Mpi2ConfigReply_t mpi_reply;
140 u32 device_info;
141 u32 ioc_status;
142
143 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
144 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
145 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
146 ioc->name, __FILE__, __LINE__, __func__);
147 return -1;
148 }
149
150 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
151 MPI2_IOCSTATUS_MASK;
152 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
153 printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
154 "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
155 __FILE__, __LINE__, __func__);
156 return -1;
157 }
158
159 memset(identify, 0, sizeof(identify));
160 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
161
162 /* sas_address */
163 identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
164
165 /* device_type */
166 switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
167 case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
168 identify->device_type = SAS_PHY_UNUSED;
169 break;
170 case MPI2_SAS_DEVICE_INFO_END_DEVICE:
171 identify->device_type = SAS_END_DEVICE;
172 break;
173 case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
174 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
175 break;
176 case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
177 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
178 break;
179 }
180
181 /* initiator_port_protocols */
182 if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
183 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
184 if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
185 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
186 if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
187 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
188 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
189 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
190
191 /* target_port_protocols */
192 if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
193 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
194 if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
195 identify->target_port_protocols |= SAS_PROTOCOL_STP;
196 if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
197 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
198 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
199 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
200
201 return 0;
202}
203
204/**
205 * mpt2sas_transport_done - internal transport layer callback handler.
206 * @ioc: per adapter object
207 * @smid: system request message index
208 * @VF_ID: virtual function id
209 * @reply: reply message frame(lower 32bit addr)
210 *
211 * Callback handler when sending internal generated transport cmds.
212 * The callback index passed is `ioc->transport_cb_idx`
213 *
214 * Return nothing.
215 */
216void
217mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
218 u32 reply)
219{
220 MPI2DefaultReply_t *mpi_reply;
221
222 mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
223 if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
224 return;
225 if (ioc->transport_cmds.smid != smid)
226 return;
227 ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
228 if (mpi_reply) {
229 memcpy(ioc->transport_cmds.reply, mpi_reply,
230 mpi_reply->MsgLength*4);
231 ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
232 }
233 ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
234 complete(&ioc->transport_cmds.done);
235}
236
237/* report manufacture request structure */
238struct rep_manu_request{
239 u8 smp_frame_type;
240 u8 function;
241 u8 reserved;
242 u8 request_length;
243};
244
245/* report manufacture reply structure */
246struct rep_manu_reply{
247 u8 smp_frame_type; /* 0x41 */
248 u8 function; /* 0x01 */
249 u8 function_result;
250 u8 response_length;
251 u16 expander_change_count;
252 u8 reserved0[2];
253 u8 sas_format:1;
254 u8 reserved1:7;
255 u8 reserved2[3];
256 u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
257 u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
258 u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
259 u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
260 u16 component_id;
261 u8 component_revision_id;
262 u8 reserved3;
263 u8 vendor_specific[8];
264};
265
266/**
267 * transport_expander_report_manufacture - obtain SMP report_manufacture
268 * @ioc: per adapter object
269 * @sas_address: expander sas address
270 * @edev: the sas_expander_device object
271 *
272 * Fills in the sas_expander_device object when SMP port is created.
273 *
274 * Returns 0 for success, non-zero for failure.
275 */
276static int
277transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
278 u64 sas_address, struct sas_expander_device *edev)
279{
280 Mpi2SmpPassthroughRequest_t *mpi_request;
281 Mpi2SmpPassthroughReply_t *mpi_reply;
282 struct rep_manu_reply *manufacture_reply;
283 struct rep_manu_request *manufacture_request;
284 int rc;
285 u16 smid;
286 u32 ioc_state;
287 unsigned long timeleft;
288 void *psge;
289 u32 sgl_flags;
290 u8 issue_reset = 0;
291 unsigned long flags;
292 void *data_out = NULL;
293 dma_addr_t data_out_dma;
294 u32 sz;
295 u64 *sas_address_le;
296 u16 wait_state_count;
297
298 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
299 if (ioc->ioc_reset_in_progress) {
300 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
301 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
302 __func__, ioc->name);
303 return -EFAULT;
304 }
305 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
306
307 mutex_lock(&ioc->transport_cmds.mutex);
308
309 if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
310 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
311 ioc->name, __func__);
312 rc = -EAGAIN;
313 goto out;
314 }
315 ioc->transport_cmds.status = MPT2_CMD_PENDING;
316
317 wait_state_count = 0;
318 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
319 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
320 if (wait_state_count++ == 10) {
321 printk(MPT2SAS_ERR_FMT
322 "%s: failed due to ioc not operational\n",
323 ioc->name, __func__);
324 rc = -EFAULT;
325 goto out;
326 }
327 ssleep(1);
328 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
329 printk(MPT2SAS_INFO_FMT "%s: waiting for "
330 "operational state(count=%d)\n", ioc->name,
331 __func__, wait_state_count);
332 }
333 if (wait_state_count)
334 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
335 ioc->name, __func__);
336
337 smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
338 if (!smid) {
339 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
340 ioc->name, __func__);
341 rc = -EAGAIN;
342 goto out;
343 }
344
345 rc = 0;
346 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
347 ioc->transport_cmds.smid = smid;
348
349 sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
350 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
351
352 if (!data_out) {
353 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
354 __LINE__, __func__);
355 rc = -ENOMEM;
356 mpt2sas_base_free_smid(ioc, smid);
357 goto out;
358 }
359
360 manufacture_request = data_out;
361 manufacture_request->smp_frame_type = 0x40;
362 manufacture_request->function = 1;
363 manufacture_request->reserved = 0;
364 manufacture_request->request_length = 0;
365
366 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
367 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
368 mpi_request->PhysicalPort = 0xFF;
369 sas_address_le = (u64 *)&mpi_request->SASAddress;
370 *sas_address_le = cpu_to_le64(sas_address);
371 mpi_request->RequestDataLength = sizeof(struct rep_manu_request);
372 psge = &mpi_request->SGL;
373
374 /* WRITE sgel first */
375 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
376 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
377 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
378 ioc->base_add_sg_single(psge, sgl_flags |
379 sizeof(struct rep_manu_request), data_out_dma);
380
381 /* incr sgel */
382 psge += ioc->sge_size;
383
384 /* READ sgel last */
385 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
386 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
387 MPI2_SGE_FLAGS_END_OF_LIST);
388 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
389 ioc->base_add_sg_single(psge, sgl_flags |
390 sizeof(struct rep_manu_reply), data_out_dma +
391 sizeof(struct rep_manu_request));
392
393 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
394 "send to sas_addr(0x%016llx)\n", ioc->name,
395 (unsigned long long)sas_address));
396 mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
397 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
398 10*HZ);
399
400 if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
401 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
402 ioc->name, __func__);
403 _debug_dump_mf(mpi_request,
404 sizeof(Mpi2SmpPassthroughRequest_t)/4);
405 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
406 issue_reset = 1;
407 goto issue_host_reset;
408 }
409
410 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
411 "complete\n", ioc->name));
412
413 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
414 u8 *tmp;
415
416 mpi_reply = ioc->transport_cmds.reply;
417
418 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
419 "report_manufacture - reply data transfer size(%d)\n",
420 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
421
422 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
423 sizeof(struct rep_manu_reply))
424 goto out;
425
426 manufacture_reply = data_out + sizeof(struct rep_manu_request);
427 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
428 SAS_EXPANDER_VENDOR_ID_LEN);
429 strncpy(edev->product_id, manufacture_reply->product_id,
430 SAS_EXPANDER_PRODUCT_ID_LEN);
431 strncpy(edev->product_rev, manufacture_reply->product_rev,
432 SAS_EXPANDER_PRODUCT_REV_LEN);
433 edev->level = manufacture_reply->sas_format;
434 if (manufacture_reply->sas_format) {
435 strncpy(edev->component_vendor_id,
436 manufacture_reply->component_vendor_id,
437 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
438 tmp = (u8 *)&manufacture_reply->component_id;
439 edev->component_id = tmp[0] << 8 | tmp[1];
440 edev->component_revision_id =
441 manufacture_reply->component_revision_id;
442 }
443 } else
444 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
445 "report_manufacture - no reply\n", ioc->name));
446
447 issue_host_reset:
448 if (issue_reset)
449 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
450 FORCE_BIG_HAMMER);
451 out:
452 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
453 if (data_out)
454 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
455
456 mutex_unlock(&ioc->transport_cmds.mutex);
457 return rc;
458}
459
460/**
461 * mpt2sas_transport_port_add - insert port to the list
462 * @ioc: per adapter object
463 * @handle: handle of attached device
464 * @parent_handle: parent handle(either hba or expander)
465 * Context: This function will acquire ioc->sas_node_lock.
466 *
467 * Adding new port object to the sas_node->sas_port_list.
468 *
469 * Returns mpt2sas_port.
470 */
471struct _sas_port *
472mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
473 u16 parent_handle)
474{
475 struct _sas_phy *mpt2sas_phy, *next;
476 struct _sas_port *mpt2sas_port;
477 unsigned long flags;
478 struct _sas_node *sas_node;
479 struct sas_rphy *rphy;
480 int i;
481 struct sas_port *port;
482
483 if (!parent_handle)
484 return NULL;
485
486 mpt2sas_port = kzalloc(sizeof(struct _sas_port),
487 GFP_KERNEL);
488 if (!mpt2sas_port) {
489 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
490 ioc->name, __FILE__, __LINE__, __func__);
491 return NULL;
492 }
493
494 INIT_LIST_HEAD(&mpt2sas_port->port_list);
495 INIT_LIST_HEAD(&mpt2sas_port->phy_list);
496 spin_lock_irqsave(&ioc->sas_node_lock, flags);
497 sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
498 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
499
500 if (!sas_node) {
501 printk(MPT2SAS_ERR_FMT "%s: Could not find parent(0x%04x)!\n",
502 ioc->name, __func__, parent_handle);
503 goto out_fail;
504 }
505
506 mpt2sas_port->handle = parent_handle;
507 mpt2sas_port->sas_address = sas_node->sas_address;
508 if ((_transport_set_identify(ioc, handle,
509 &mpt2sas_port->remote_identify))) {
510 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
511 ioc->name, __FILE__, __LINE__, __func__);
512 goto out_fail;
513 }
514
515 if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
516 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
517 ioc->name, __FILE__, __LINE__, __func__);
518 goto out_fail;
519 }
520
521 for (i = 0; i < sas_node->num_phys; i++) {
522 if (sas_node->phy[i].remote_identify.sas_address !=
523 mpt2sas_port->remote_identify.sas_address)
524 continue;
525 list_add_tail(&sas_node->phy[i].port_siblings,
526 &mpt2sas_port->phy_list);
527 mpt2sas_port->num_phys++;
528 }
529
530 if (!mpt2sas_port->num_phys) {
531 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
532 ioc->name, __FILE__, __LINE__, __func__);
533 goto out_fail;
534 }
535
536 port = sas_port_alloc_num(sas_node->parent_dev);
537 if ((sas_port_add(port))) {
538 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
539 ioc->name, __FILE__, __LINE__, __func__);
540 goto out_fail;
541 }
542
543 list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
544 port_siblings) {
545 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
546 dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
547 ", sas_addr(0x%016llx), phy(%d)\n", handle,
548 (unsigned long long)
549 mpt2sas_port->remote_identify.sas_address,
550 mpt2sas_phy->phy_id);
551 sas_port_add_phy(port, mpt2sas_phy->phy);
552 }
553
554 mpt2sas_port->port = port;
555 if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
556 rphy = sas_end_device_alloc(port);
557 else
558 rphy = sas_expander_alloc(port,
559 mpt2sas_port->remote_identify.device_type);
560
561 rphy->identify = mpt2sas_port->remote_identify;
562 if ((sas_rphy_add(rphy))) {
563 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
564 ioc->name, __FILE__, __LINE__, __func__);
565 }
566 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
567 dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
568 "sas_addr(0x%016llx)\n", handle,
569 (unsigned long long)
570 mpt2sas_port->remote_identify.sas_address);
571 mpt2sas_port->rphy = rphy;
572 spin_lock_irqsave(&ioc->sas_node_lock, flags);
573 list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
574 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
575
576 /* fill in report manufacture */
577 if (mpt2sas_port->remote_identify.device_type ==
578 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
579 mpt2sas_port->remote_identify.device_type ==
580 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
581 transport_expander_report_manufacture(ioc,
582 mpt2sas_port->remote_identify.sas_address,
583 rphy_to_expander_device(rphy));
584
585 return mpt2sas_port;
586
587 out_fail:
588 list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
589 port_siblings)
590 list_del(&mpt2sas_phy->port_siblings);
591 kfree(mpt2sas_port);
592 return NULL;
593}
594
595/**
596 * mpt2sas_transport_port_remove - remove port from the list
597 * @ioc: per adapter object
598 * @sas_address: sas address of attached device
599 * @parent_handle: handle to the upstream parent(either hba or expander)
600 * Context: This function will acquire ioc->sas_node_lock.
601 *
602 * Removing object and freeing associated memory from the
603 * ioc->sas_port_list.
604 *
605 * Return nothing.
606 */
607void
608mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
609 u16 parent_handle)
610{
611 int i;
612 unsigned long flags;
613 struct _sas_port *mpt2sas_port, *next;
614 struct _sas_node *sas_node;
615 u8 found = 0;
616 struct _sas_phy *mpt2sas_phy, *next_phy;
617
618 spin_lock_irqsave(&ioc->sas_node_lock, flags);
619 sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
620 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
621 if (!sas_node)
622 return;
623 list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
624 port_list) {
625 if (mpt2sas_port->remote_identify.sas_address != sas_address)
626 continue;
627 found = 1;
628 list_del(&mpt2sas_port->port_list);
629 goto out;
630 }
631 out:
632 if (!found)
633 return;
634
635 for (i = 0; i < sas_node->num_phys; i++) {
636 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
637 memset(&sas_node->phy[i].remote_identify, 0 ,
638 sizeof(struct sas_identify));
639 }
640
641 list_for_each_entry_safe(mpt2sas_phy, next_phy,
642 &mpt2sas_port->phy_list, port_siblings) {
643 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
644 dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
645 "remove: parent_handle(0x%04x), "
646 "sas_addr(0x%016llx), phy(%d)\n", parent_handle,
647 (unsigned long long)
648 mpt2sas_port->remote_identify.sas_address,
649 mpt2sas_phy->phy_id);
650 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
651 list_del(&mpt2sas_phy->port_siblings);
652 }
653 sas_port_delete(mpt2sas_port->port);
654 kfree(mpt2sas_port);
655}
656
657/**
658 * mpt2sas_transport_add_host_phy - report sas_host phy to transport
659 * @ioc: per adapter object
660 * @mpt2sas_phy: mpt2sas per phy object
661 * @phy_pg0: sas phy page 0
662 * @parent_dev: parent device class object
663 *
664 * Returns 0 for success, non-zero for failure.
665 */
666int
667mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
668 *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
669{
670 struct sas_phy *phy;
671 int phy_index = mpt2sas_phy->phy_id;
672
673
674 INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
675 phy = sas_phy_alloc(parent_dev, phy_index);
676 if (!phy) {
677 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
678 ioc->name, __FILE__, __LINE__, __func__);
679 return -1;
680 }
681 if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
682 &mpt2sas_phy->identify))) {
683 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
684 ioc->name, __FILE__, __LINE__, __func__);
685 return -1;
686 }
687 phy->identify = mpt2sas_phy->identify;
688 mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
689 if (mpt2sas_phy->attached_handle)
690 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
691 &mpt2sas_phy->remote_identify);
692 phy->identify.phy_identifier = mpt2sas_phy->phy_id;
693 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
694 phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
695 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
696 phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
697 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
698 phy_pg0.HwLinkRate >> 4);
699 phy->minimum_linkrate = _transport_convert_phy_link_rate(
700 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
701 phy->maximum_linkrate = _transport_convert_phy_link_rate(
702 phy_pg0.ProgrammedLinkRate >> 4);
703
704 if ((sas_phy_add(phy))) {
705 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
706 ioc->name, __FILE__, __LINE__, __func__);
707 sas_phy_free(phy);
708 return -1;
709 }
710 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
711 dev_printk(KERN_INFO, &phy->dev,
712 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
713 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
714 mpt2sas_phy->handle, (unsigned long long)
715 mpt2sas_phy->identify.sas_address,
716 mpt2sas_phy->attached_handle,
717 (unsigned long long)
718 mpt2sas_phy->remote_identify.sas_address);
719 mpt2sas_phy->phy = phy;
720 return 0;
721}
722
723
724/**
725 * mpt2sas_transport_add_expander_phy - report expander phy to transport
726 * @ioc: per adapter object
727 * @mpt2sas_phy: mpt2sas per phy object
728 * @expander_pg1: expander page 1
729 * @parent_dev: parent device class object
730 *
731 * Returns 0 for success, non-zero for failure.
732 */
733int
734mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
735 *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
736{
737 struct sas_phy *phy;
738 int phy_index = mpt2sas_phy->phy_id;
739
740 INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
741 phy = sas_phy_alloc(parent_dev, phy_index);
742 if (!phy) {
743 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
744 ioc->name, __FILE__, __LINE__, __func__);
745 return -1;
746 }
747 if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
748 &mpt2sas_phy->identify))) {
749 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
750 ioc->name, __FILE__, __LINE__, __func__);
751 return -1;
752 }
753 phy->identify = mpt2sas_phy->identify;
754 mpt2sas_phy->attached_handle =
755 le16_to_cpu(expander_pg1.AttachedDevHandle);
756 if (mpt2sas_phy->attached_handle)
757 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
758 &mpt2sas_phy->remote_identify);
759 phy->identify.phy_identifier = mpt2sas_phy->phy_id;
760 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
761 expander_pg1.NegotiatedLinkRate &
762 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
763 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
764 expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
765 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
766 expander_pg1.HwLinkRate >> 4);
767 phy->minimum_linkrate = _transport_convert_phy_link_rate(
768 expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
769 phy->maximum_linkrate = _transport_convert_phy_link_rate(
770 expander_pg1.ProgrammedLinkRate >> 4);
771
772 if ((sas_phy_add(phy))) {
773 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
774 ioc->name, __FILE__, __LINE__, __func__);
775 sas_phy_free(phy);
776 return -1;
777 }
778 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
779 dev_printk(KERN_INFO, &phy->dev,
780 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
781 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
782 mpt2sas_phy->handle, (unsigned long long)
783 mpt2sas_phy->identify.sas_address,
784 mpt2sas_phy->attached_handle,
785 (unsigned long long)
786 mpt2sas_phy->remote_identify.sas_address);
787 mpt2sas_phy->phy = phy;
788 return 0;
789}
790
791/**
792 * mpt2sas_transport_update_phy_link_change - refreshing phy link changes and attached devices
793 * @ioc: per adapter object
794 * @handle: handle to sas_host or expander
795 * @attached_handle: attached device handle
796 * @phy_numberv: phy number
797 * @link_rate: new link rate
798 *
799 * Returns nothing.
800 */
801void
802mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc,
803 u16 handle, u16 attached_handle, u8 phy_number, u8 link_rate)
804{
805 unsigned long flags;
806 struct _sas_node *sas_node;
807 struct _sas_phy *mpt2sas_phy;
808
809 spin_lock_irqsave(&ioc->sas_node_lock, flags);
810 sas_node = _transport_sas_node_find_by_handle(ioc, handle);
811 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
812 if (!sas_node)
813 return;
814
815 mpt2sas_phy = &sas_node->phy[phy_number];
816 mpt2sas_phy->attached_handle = attached_handle;
817 if (attached_handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
818 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
819 &mpt2sas_phy->remote_identify);
820 else
821 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
822 sas_identify));
823
824 if (mpt2sas_phy->phy)
825 mpt2sas_phy->phy->negotiated_linkrate =
826 _transport_convert_phy_link_rate(link_rate);
827
828 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
829 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
830 "refresh: handle(0x%04x), sas_addr(0x%016llx),\n"
831 "\tlink_rate(0x%02x), phy(%d)\n"
832 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
833 handle, (unsigned long long)
834 mpt2sas_phy->identify.sas_address, link_rate,
835 phy_number, attached_handle,
836 (unsigned long long)
837 mpt2sas_phy->remote_identify.sas_address);
838}
839
840static inline void *
841phy_to_ioc(struct sas_phy *phy)
842{
843 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
844 return shost_priv(shost);
845}
846
847static inline void *
848rphy_to_ioc(struct sas_rphy *rphy)
849{
850 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
851 return shost_priv(shost);
852}
853
854/**
855 * transport_get_linkerrors -
856 * @phy: The sas phy object
857 *
858 * Only support sas_host direct attached phys.
859 * Returns 0 for success, non-zero for failure.
860 *
861 */
862static int
863transport_get_linkerrors(struct sas_phy *phy)
864{
865 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
866 struct _sas_phy *mpt2sas_phy;
867 Mpi2ConfigReply_t mpi_reply;
868 Mpi2SasPhyPage1_t phy_pg1;
869 int i;
870
871 for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
872 !mpt2sas_phy; i++) {
873 if (ioc->sas_hba.phy[i].phy != phy)
874 continue;
875 mpt2sas_phy = &ioc->sas_hba.phy[i];
876 }
877
878 if (!mpt2sas_phy) /* this phy not on sas_host */
879 return -EINVAL;
880
881 if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
882 mpt2sas_phy->phy_id))) {
883 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
884 ioc->name, __FILE__, __LINE__, __func__);
885 return -ENXIO;
886 }
887
888 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
889 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
890 "(0x%04x), loginfo(0x%08x)\n", ioc->name,
891 mpt2sas_phy->phy_id,
892 le16_to_cpu(mpi_reply.IOCStatus),
893 le32_to_cpu(mpi_reply.IOCLogInfo));
894
895 phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
896 phy->running_disparity_error_count =
897 le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
898 phy->loss_of_dword_sync_count =
899 le32_to_cpu(phy_pg1.LossDwordSynchCount);
900 phy->phy_reset_problem_count =
901 le32_to_cpu(phy_pg1.PhyResetProblemCount);
902 return 0;
903}
904
905/**
906 * transport_get_enclosure_identifier -
907 * @phy: The sas phy object
908 *
909 * Obtain the enclosure logical id for an expander.
910 * Returns 0 for success, non-zero for failure.
911 */
912static int
913transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
914{
915 struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
916 struct _sas_node *sas_expander;
917 unsigned long flags;
918
919 spin_lock_irqsave(&ioc->sas_node_lock, flags);
920 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
921 rphy->identify.sas_address);
922 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
923
924 if (!sas_expander)
925 return -ENXIO;
926
927 *identifier = sas_expander->enclosure_logical_id;
928 return 0;
929}
930
931/**
932 * transport_get_bay_identifier -
933 * @phy: The sas phy object
934 *
935 * Returns the slot id for a device that resides inside an enclosure.
936 */
937static int
938transport_get_bay_identifier(struct sas_rphy *rphy)
939{
940 struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
941 struct _sas_device *sas_device;
942 unsigned long flags;
943
944 spin_lock_irqsave(&ioc->sas_device_lock, flags);
945 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
946 rphy->identify.sas_address);
947 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
948
949 if (!sas_device)
950 return -ENXIO;
951
952 return sas_device->slot;
953}
954
955/**
956 * transport_phy_reset -
957 * @phy: The sas phy object
958 * @hard_reset:
959 *
960 * Only support sas_host direct attached phys.
961 * Returns 0 for success, non-zero for failure.
962 */
963static int
964transport_phy_reset(struct sas_phy *phy, int hard_reset)
965{
966 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
967 struct _sas_phy *mpt2sas_phy;
968 Mpi2SasIoUnitControlReply_t mpi_reply;
969 Mpi2SasIoUnitControlRequest_t mpi_request;
970 int i;
971
972 for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
973 !mpt2sas_phy; i++) {
974 if (ioc->sas_hba.phy[i].phy != phy)
975 continue;
976 mpt2sas_phy = &ioc->sas_hba.phy[i];
977 }
978
979 if (!mpt2sas_phy) /* this phy not on sas_host */
980 return -EINVAL;
981
982 memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
983 mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
984 mpi_request.Operation = hard_reset ?
985 MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
986 mpi_request.PhyNum = mpt2sas_phy->phy_id;
987
988 if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
989 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
990 ioc->name, __FILE__, __LINE__, __func__);
991 return -ENXIO;
992 }
993
994 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
995 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
996 "(0x%04x), loginfo(0x%08x)\n", ioc->name,
997 mpt2sas_phy->phy_id,
998 le16_to_cpu(mpi_reply.IOCStatus),
999 le32_to_cpu(mpi_reply.IOCLogInfo));
1000
1001 return 0;
1002}
1003
1004/**
1005 * transport_smp_handler - transport portal for smp passthru
1006 * @shost: shost object
1007 * @rphy: sas transport rphy object
1008 * @req:
1009 *
1010 * This used primarily for smp_utils.
1011 * Example:
1012 * smp_rep_general /sys/class/bsg/expander-5:0
1013 */
1014static int
1015transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1016 struct request *req)
1017{
1018 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1019 Mpi2SmpPassthroughRequest_t *mpi_request;
1020 Mpi2SmpPassthroughReply_t *mpi_reply;
1021 int rc;
1022 u16 smid;
1023 u32 ioc_state;
1024 unsigned long timeleft;
1025 void *psge;
1026 u32 sgl_flags;
1027 u8 issue_reset = 0;
1028 unsigned long flags;
1029 dma_addr_t dma_addr_in = 0;
1030 dma_addr_t dma_addr_out = 0;
1031 u16 wait_state_count;
1032 struct request *rsp = req->next_rq;
1033
1034 if (!rsp) {
1035 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1036 "missing\n", ioc->name, __func__);
1037 return -EINVAL;
1038 }
1039
1040 /* do we need to support multiple segments? */
1041 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1042 printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1043 "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1044 req->data_len, rsp->bio->bi_vcnt, rsp->data_len);
1045 return -EINVAL;
1046 }
1047
1048 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
1049 if (ioc->ioc_reset_in_progress) {
1050 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
1051 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1052 __func__, ioc->name);
1053 return -EFAULT;
1054 }
1055 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
1056
1057 rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1058 if (rc)
1059 return rc;
1060
1061 if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1062 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1063 __func__);
1064 rc = -EAGAIN;
1065 goto out;
1066 }
1067 ioc->transport_cmds.status = MPT2_CMD_PENDING;
1068
1069 wait_state_count = 0;
1070 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1071 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1072 if (wait_state_count++ == 10) {
1073 printk(MPT2SAS_ERR_FMT
1074 "%s: failed due to ioc not operational\n",
1075 ioc->name, __func__);
1076 rc = -EFAULT;
1077 goto out;
1078 }
1079 ssleep(1);
1080 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1081 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1082 "operational state(count=%d)\n", ioc->name,
1083 __func__, wait_state_count);
1084 }
1085 if (wait_state_count)
1086 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1087 ioc->name, __func__);
1088
1089 smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1090 if (!smid) {
1091 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1092 ioc->name, __func__);
1093 rc = -EAGAIN;
1094 goto out;
1095 }
1096
1097 rc = 0;
1098 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1099 ioc->transport_cmds.smid = smid;
1100
1101 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1102 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1103 mpi_request->PhysicalPort = 0xFF;
1104 *((u64 *)&mpi_request->SASAddress) = (rphy) ?
1105 cpu_to_le64(rphy->identify.sas_address) :
1106 cpu_to_le64(ioc->sas_hba.sas_address);
1107 mpi_request->RequestDataLength = cpu_to_le16(req->data_len - 4);
1108 psge = &mpi_request->SGL;
1109
1110 /* WRITE sgel first */
1111 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1112 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1113 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1114 dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1115 req->data_len, PCI_DMA_BIDIRECTIONAL);
1116 if (!dma_addr_out) {
1117 mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
1118 goto unmap;
1119 }
1120
1121 ioc->base_add_sg_single(psge, sgl_flags | (req->data_len - 4),
1122 dma_addr_out);
1123
1124 /* incr sgel */
1125 psge += ioc->sge_size;
1126
1127 /* READ sgel last */
1128 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1129 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1130 MPI2_SGE_FLAGS_END_OF_LIST);
1131 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1132 dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1133 rsp->data_len, PCI_DMA_BIDIRECTIONAL);
1134 if (!dma_addr_in) {
1135 mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
1136 goto unmap;
1137 }
1138
1139 ioc->base_add_sg_single(psge, sgl_flags | (rsp->data_len + 4),
1140 dma_addr_in);
1141
1142 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1143 "sending smp request\n", ioc->name, __func__));
1144
1145 mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
1146 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1147 10*HZ);
1148
1149 if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1150 printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1151 __func__, ioc->name);
1152 _debug_dump_mf(mpi_request,
1153 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1154 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1155 issue_reset = 1;
1156 goto issue_host_reset;
1157 }
1158
1159 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1160 "complete\n", ioc->name, __func__));
1161
1162 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1163
1164 mpi_reply = ioc->transport_cmds.reply;
1165
1166 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1167 "%s - reply data transfer size(%d)\n",
1168 ioc->name, __func__,
1169 le16_to_cpu(mpi_reply->ResponseDataLength)));
1170
1171 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1172 req->sense_len = sizeof(*mpi_reply);
1173 req->data_len = 0;
1174 rsp->data_len -= mpi_reply->ResponseDataLength;
1175
1176 } else {
1177 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1178 "%s - no reply\n", ioc->name, __func__));
1179 rc = -ENXIO;
1180 }
1181
1182 issue_host_reset:
1183 if (issue_reset) {
1184 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1185 FORCE_BIG_HAMMER);
1186 rc = -ETIMEDOUT;
1187 }
1188
1189 unmap:
1190 if (dma_addr_out)
1191 pci_unmap_single(ioc->pdev, dma_addr_out, req->data_len,
1192 PCI_DMA_BIDIRECTIONAL);
1193 if (dma_addr_in)
1194 pci_unmap_single(ioc->pdev, dma_addr_in, rsp->data_len,
1195 PCI_DMA_BIDIRECTIONAL);
1196
1197 out:
1198 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1199 mutex_unlock(&ioc->transport_cmds.mutex);
1200 return rc;
1201}
1202
1203struct sas_function_template mpt2sas_transport_functions = {
1204 .get_linkerrors = transport_get_linkerrors,
1205 .get_enclosure_identifier = transport_get_enclosure_identifier,
1206 .get_bay_identifier = transport_get_bay_identifier,
1207 .phy_reset = transport_phy_reset,
1208 .smp_handler = transport_smp_handler,
1209};
1210
1211struct scsi_transport_template *mpt2sas_transport_template;