aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/Kconfig1
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/mpt3sas/Kconfig67
-rw-r--r--drivers/scsi/mpt3sas/Makefile8
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2.h1164
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h3323
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_init.h560
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_ioc.h1665
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_raid.h346
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_sas.h295
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_tool.h437
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_type.h56
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c4840
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h1139
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_config.c1650
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.c3297
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.h418
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_debug.h219
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c8167
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_transport.c2128
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c434
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h193
22 files changed, 30408 insertions, 0 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index af7a3e727cd4..142f632e2a2e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -603,6 +603,7 @@ config SCSI_ARCMSR
603 603
604source "drivers/scsi/megaraid/Kconfig.megaraid" 604source "drivers/scsi/megaraid/Kconfig.megaraid"
605source "drivers/scsi/mpt2sas/Kconfig" 605source "drivers/scsi/mpt2sas/Kconfig"
606source "drivers/scsi/mpt3sas/Kconfig"
606source "drivers/scsi/ufs/Kconfig" 607source "drivers/scsi/ufs/Kconfig"
607 608
608config SCSI_HPTIOP 609config SCSI_HPTIOP
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 8739aa7a379c..b607ba4f5630 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -107,6 +107,7 @@ obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
107obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ 107obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
108obj-$(CONFIG_MEGARAID_SAS) += megaraid/ 108obj-$(CONFIG_MEGARAID_SAS) += megaraid/
109obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas/ 109obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas/
110obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas/
110obj-$(CONFIG_SCSI_UFSHCD) += ufs/ 111obj-$(CONFIG_SCSI_UFSHCD) += ufs/
111obj-$(CONFIG_SCSI_ACARD) += atp870u.o 112obj-$(CONFIG_SCSI_ACARD) += atp870u.o
112obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o 113obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o
diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig
new file mode 100644
index 000000000000..81471bf415d8
--- /dev/null
+++ b/drivers/scsi/mpt3sas/Kconfig
@@ -0,0 +1,67 @@
1#
2# Kernel configuration file for the MPT3SAS
3#
4# This code is based on drivers/scsi/mpt3sas/Kconfig
5# Copyright (C) 2012 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_MPT3SAS
44 tristate "LSI MPT Fusion SAS 3.0 Device Driver"
45 depends on PCI && SCSI
46 select SCSI_SAS_ATTRS
47 select RAID_ATTRS
48 ---help---
49 This driver supports PCI-Express SAS 12Gb/s Host Adapters.
50
51config SCSI_MPT3SAS_MAX_SGE
52 int "LSI MPT Fusion Max number of SG Entries (16 - 256)"
53 depends on PCI && SCSI && SCSI_MPT3SAS
54 default "128"
55 range 16 256
56 ---help---
57 This option allows you to specify the maximum number of scatter-
58 gather entries per I/O. The driver default is 128, which matches
59 MAX_PHYS_SEGMENTS in most kernels. However in SuSE kernels this
60 can be 256. However, it may decreased down to 16. Decreasing this
61 parameter will reduce memory requirements on a per controller instance.
62
63config SCSI_MPT3SAS_LOGGING
64 bool "LSI MPT Fusion logging facility"
65 depends on PCI && SCSI && SCSI_MPT3SAS
66 ---help---
67 This turns on a logging facility.
diff --git a/drivers/scsi/mpt3sas/Makefile b/drivers/scsi/mpt3sas/Makefile
new file mode 100644
index 000000000000..4c1d2e7a1176
--- /dev/null
+++ b/drivers/scsi/mpt3sas/Makefile
@@ -0,0 +1,8 @@
1# mpt3sas makefile
2obj-m += mpt3sas.o
3mpt3sas-y += mpt3sas_base.o \
4 mpt3sas_config.o \
5 mpt3sas_scsih.o \
6 mpt3sas_transport.o \
7 mpt3sas_ctl.o \
8 mpt3sas_trigger_diag.o
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h
new file mode 100644
index 000000000000..03317ffea62c
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpi/mpi2.h
@@ -0,0 +1,1164 @@
1/*
2 * Copyright (c) 2000-2012 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.26
12 *
13 * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
14 * prefix are for use only on MPI v2.5 products, and must not be used
15 * with MPI v2.0 products. Unless otherwise noted, names beginning with
16 * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
17 *
18 * Version History
19 * ---------------
20 *
21 * Date Version Description
22 * -------- -------- ------------------------------------------------------
23 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
24 * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT.
25 * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT.
26 * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT.
27 * Moved ReplyPostHostIndex register to offset 0x6C of the
28 * MPI2_SYSTEM_INTERFACE_REGS and modified the define for
29 * MPI2_REPLY_POST_HOST_INDEX_OFFSET.
30 * Added union of request descriptors.
31 * Added union of reply descriptors.
32 * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT.
33 * Added define for MPI2_VERSION_02_00.
34 * Fixed the size of the FunctionDependent5 field in the
35 * MPI2_DEFAULT_REPLY structure.
36 * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT.
37 * Removed the MPI-defined Fault Codes and extended the
38 * product specific codes up to 0xEFFF.
39 * Added a sixth key value for the WriteSequence register
40 * and changed the flush value to 0x0.
41 * Added message function codes for Diagnostic Buffer Post
42 * and Diagnsotic Release.
43 * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
44 * Moved MPI2_VERSION_UNION from mpi2_ioc.h.
45 * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT.
46 * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT.
47 * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT.
48 * Added #defines for marking a reply descriptor as unused.
49 * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT.
50 * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT.
51 * Moved LUN field defines from mpi2_init.h.
52 * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT.
53 * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT.
54 * In all request and reply descriptors, replaced VF_ID
55 * field with MSIxIndex field.
56 * Removed DevHandle field from
57 * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
58 * bytes reserved.
59 * Added RAID Accelerator functionality.
60 * 07-30-09 02.00.13 Bumped MPI2_HEADER_VERSION_UNIT.
61 * 10-28-09 02.00.14 Bumped MPI2_HEADER_VERSION_UNIT.
62 * Added MSI-x index mask and shift for Reply Post Host
63 * Index register.
64 * Added function code for Host Based Discovery Action.
65 * 02-10-10 02.00.15 Bumped MPI2_HEADER_VERSION_UNIT.
66 * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL.
67 * Added defines for product-specific range of message
68 * function codes, 0xF0 to 0xFF.
69 * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT.
70 * Added alternative defines for the SGE Direction bit.
71 * 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT.
72 * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT.
73 * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
74 * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT.
75 * Added MPI2_FUNCTION_SEND_HOST_MESSAGE.
76 * 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT.
77 * 05-25-11 02.00.21 Bumped MPI2_HEADER_VERSION_UNIT.
78 * 08-24-11 02.00.22 Bumped MPI2_HEADER_VERSION_UNIT.
79 * 11-18-11 02.00.23 Bumped MPI2_HEADER_VERSION_UNIT.
80 * Incorporating additions for MPI v2.5.
81 * 02-06-12 02.00.24 Bumped MPI2_HEADER_VERSION_UNIT.
82 * 03-29-12 02.00.25 Bumped MPI2_HEADER_VERSION_UNIT.
83 * Added Hard Reset delay timings.
84 * 07-10-12 02.00.26 Bumped MPI2_HEADER_VERSION_UNIT.
85 * --------------------------------------------------------------------------
86 */
87
88#ifndef MPI2_H
89#define MPI2_H
90
91/*****************************************************************************
92*
93* MPI Version Definitions
94*
95*****************************************************************************/
96
97#define MPI2_VERSION_MAJOR_MASK (0xFF00)
98#define MPI2_VERSION_MAJOR_SHIFT (8)
99#define MPI2_VERSION_MINOR_MASK (0x00FF)
100#define MPI2_VERSION_MINOR_SHIFT (0)
101
102/*major version for all MPI v2.x */
103#define MPI2_VERSION_MAJOR (0x02)
104
105/*minor version for MPI v2.0 compatible products */
106#define MPI2_VERSION_MINOR (0x00)
107#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
108 MPI2_VERSION_MINOR)
109#define MPI2_VERSION_02_00 (0x0200)
110
111/*minor version for MPI v2.5 compatible products */
112#define MPI25_VERSION_MINOR (0x05)
113#define MPI25_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
114 MPI25_VERSION_MINOR)
115#define MPI2_VERSION_02_05 (0x0205)
116
117/*Unit and Dev versioning for this MPI header set */
118#define MPI2_HEADER_VERSION_UNIT (0x1A)
119#define MPI2_HEADER_VERSION_DEV (0x00)
120#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
121#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
122#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF)
123#define MPI2_HEADER_VERSION_DEV_SHIFT (0)
124#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \
125 MPI2_HEADER_VERSION_DEV)
126
127/*****************************************************************************
128*
129* IOC State Definitions
130*
131*****************************************************************************/
132
133#define MPI2_IOC_STATE_RESET (0x00000000)
134#define MPI2_IOC_STATE_READY (0x10000000)
135#define MPI2_IOC_STATE_OPERATIONAL (0x20000000)
136#define MPI2_IOC_STATE_FAULT (0x40000000)
137
138#define MPI2_IOC_STATE_MASK (0xF0000000)
139#define MPI2_IOC_STATE_SHIFT (28)
140
141/*Fault state range for prodcut specific codes */
142#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000)
143#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF)
144
145/*****************************************************************************
146*
147* System Interface Register Definitions
148*
149*****************************************************************************/
150
151typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS {
152 U32 Doorbell; /*0x00 */
153 U32 WriteSequence; /*0x04 */
154 U32 HostDiagnostic; /*0x08 */
155 U32 Reserved1; /*0x0C */
156 U32 DiagRWData; /*0x10 */
157 U32 DiagRWAddressLow; /*0x14 */
158 U32 DiagRWAddressHigh; /*0x18 */
159 U32 Reserved2[5]; /*0x1C */
160 U32 HostInterruptStatus; /*0x30 */
161 U32 HostInterruptMask; /*0x34 */
162 U32 DCRData; /*0x38 */
163 U32 DCRAddress; /*0x3C */
164 U32 Reserved3[2]; /*0x40 */
165 U32 ReplyFreeHostIndex; /*0x48 */
166 U32 Reserved4[8]; /*0x4C */
167 U32 ReplyPostHostIndex; /*0x6C */
168 U32 Reserved5; /*0x70 */
169 U32 HCBSize; /*0x74 */
170 U32 HCBAddressLow; /*0x78 */
171 U32 HCBAddressHigh; /*0x7C */
172 U32 Reserved6[16]; /*0x80 */
173 U32 RequestDescriptorPostLow; /*0xC0 */
174 U32 RequestDescriptorPostHigh; /*0xC4 */
175 U32 Reserved7[14]; /*0xC8 */
176} MPI2_SYSTEM_INTERFACE_REGS,
177 *PTR_MPI2_SYSTEM_INTERFACE_REGS,
178 Mpi2SystemInterfaceRegs_t,
179 *pMpi2SystemInterfaceRegs_t;
180
181/*
182 *Defines for working with the Doorbell register.
183 */
184#define MPI2_DOORBELL_OFFSET (0x00000000)
185
186/*IOC --> System values */
187#define MPI2_DOORBELL_USED (0x08000000)
188#define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000)
189#define MPI2_DOORBELL_WHO_INIT_SHIFT (24)
190#define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF)
191#define MPI2_DOORBELL_DATA_MASK (0x0000FFFF)
192
193/*System --> IOC values */
194#define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000)
195#define MPI2_DOORBELL_FUNCTION_SHIFT (24)
196#define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000)
197#define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16)
198
199/*
200 *Defines for the WriteSequence register
201 */
202#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004)
203#define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F)
204#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0)
205#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF)
206#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4)
207#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB)
208#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2)
209#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7)
210#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD)
211
212/*
213 *Defines for the HostDiagnostic register
214 */
215#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008)
216
217#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800)
218#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000)
219#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800)
220
221#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400)
222#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200)
223#define MPI2_DIAG_HCB_MODE (0x00000100)
224#define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080)
225#define MPI2_DIAG_FLASH_BAD_SIG (0x00000040)
226#define MPI2_DIAG_RESET_HISTORY (0x00000020)
227#define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010)
228#define MPI2_DIAG_RESET_ADAPTER (0x00000004)
229#define MPI2_DIAG_HOLD_IOC_RESET (0x00000002)
230
231/*
232 *Offsets for DiagRWData and address
233 */
234#define MPI2_DIAG_RW_DATA_OFFSET (0x00000010)
235#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014)
236#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018)
237
238/*
239 *Defines for the HostInterruptStatus register
240 */
241#define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030)
242#define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000)
243#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS
244#define MPI2_HIS_RESET_IRQ_STATUS (0x40000000)
245#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008)
246#define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001)
247#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS
248
249/*
250 *Defines for the HostInterruptMask register
251 */
252#define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034)
253#define MPI2_HIM_RESET_IRQ_MASK (0x40000000)
254#define MPI2_HIM_REPLY_INT_MASK (0x00000008)
255#define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK
256#define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001)
257#define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK
258
259/*
260 *Offsets for DCRData and address
261 */
262#define MPI2_DCR_DATA_OFFSET (0x00000038)
263#define MPI2_DCR_ADDRESS_OFFSET (0x0000003C)
264
265/*
266 *Offset for the Reply Free Queue
267 */
268#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048)
269
270/*
271 *Defines for the Reply Descriptor Post Queue
272 */
273#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C)
274#define MPI2_REPLY_POST_HOST_INDEX_MASK (0x00FFFFFF)
275#define MPI2_RPHI_MSIX_INDEX_MASK (0xFF000000)
276#define MPI2_RPHI_MSIX_INDEX_SHIFT (24)
277
278/*
279 *Defines for the HCBSize and address
280 */
281#define MPI2_HCB_SIZE_OFFSET (0x00000074)
282#define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000)
283#define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001)
284
285#define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078)
286#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C)
287
288/*
289 *Offsets for the Request Queue
290 */
291#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0)
292#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4)
293
294/*Hard Reset delay timings */
295#define MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC (50000)
296#define MPI2_HARD_RESET_PCIE_RESET_READ_WINDOW_MICRO_SEC (255000)
297#define MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC (256000)
298
299/*****************************************************************************
300*
301* Message Descriptors
302*
303*****************************************************************************/
304
305/*Request Descriptors */
306
307/*Default Request Descriptor */
308typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR {
309 U8 RequestFlags; /*0x00 */
310 U8 MSIxIndex; /*0x01 */
311 U16 SMID; /*0x02 */
312 U16 LMID; /*0x04 */
313 U16 DescriptorTypeDependent; /*0x06 */
314} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
315 *PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
316 Mpi2DefaultRequestDescriptor_t,
317 *pMpi2DefaultRequestDescriptor_t;
318
319/*defines for the RequestFlags field */
320#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E)
321#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
322#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02)
323#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
324#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08)
325#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A)
326#define MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO (0x0C)
327
328#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
329
330/*High Priority Request Descriptor */
331typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR {
332 U8 RequestFlags; /*0x00 */
333 U8 MSIxIndex; /*0x01 */
334 U16 SMID; /*0x02 */
335 U16 LMID; /*0x04 */
336 U16 Reserved1; /*0x06 */
337} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
338 *PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
339 Mpi2HighPriorityRequestDescriptor_t,
340 *pMpi2HighPriorityRequestDescriptor_t;
341
342/*SCSI IO Request Descriptor */
343typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR {
344 U8 RequestFlags; /*0x00 */
345 U8 MSIxIndex; /*0x01 */
346 U16 SMID; /*0x02 */
347 U16 LMID; /*0x04 */
348 U16 DevHandle; /*0x06 */
349} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
350 *PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
351 Mpi2SCSIIORequestDescriptor_t,
352 *pMpi2SCSIIORequestDescriptor_t;
353
354/*SCSI Target Request Descriptor */
355typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR {
356 U8 RequestFlags; /*0x00 */
357 U8 MSIxIndex; /*0x01 */
358 U16 SMID; /*0x02 */
359 U16 LMID; /*0x04 */
360 U16 IoIndex; /*0x06 */
361} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
362 *PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
363 Mpi2SCSITargetRequestDescriptor_t,
364 *pMpi2SCSITargetRequestDescriptor_t;
365
366/*RAID Accelerator Request Descriptor */
367typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR {
368 U8 RequestFlags; /*0x00 */
369 U8 MSIxIndex; /*0x01 */
370 U16 SMID; /*0x02 */
371 U16 LMID; /*0x04 */
372 U16 Reserved; /*0x06 */
373} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
374 *PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR,
375 Mpi2RAIDAcceleratorRequestDescriptor_t,
376 *pMpi2RAIDAcceleratorRequestDescriptor_t;
377
378/*Fast Path SCSI IO Request Descriptor */
379typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR
380 MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR,
381 *PTR_MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR,
382 Mpi25FastPathSCSIIORequestDescriptor_t,
383 *pMpi25FastPathSCSIIORequestDescriptor_t;
384
385/*union of Request Descriptors */
386typedef union _MPI2_REQUEST_DESCRIPTOR_UNION {
387 MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
388 MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority;
389 MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO;
390 MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
391 MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator;
392 MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR FastPathSCSIIO;
393 U64 Words;
394} MPI2_REQUEST_DESCRIPTOR_UNION,
395 *PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
396 Mpi2RequestDescriptorUnion_t,
397 *pMpi2RequestDescriptorUnion_t;
398
399/*Reply Descriptors */
400
401/*Default Reply Descriptor */
402typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR {
403 U8 ReplyFlags; /*0x00 */
404 U8 MSIxIndex; /*0x01 */
405 U16 DescriptorTypeDependent1; /*0x02 */
406 U32 DescriptorTypeDependent2; /*0x04 */
407} MPI2_DEFAULT_REPLY_DESCRIPTOR,
408 *PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
409 Mpi2DefaultReplyDescriptor_t,
410 *pMpi2DefaultReplyDescriptor_t;
411
412/*defines for the ReplyFlags field */
413#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F)
414#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
415#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01)
416#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02)
417#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03)
418#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05)
419#define MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS (0x06)
420#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
421
422/*values for marking a reply descriptor as unused */
423#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF)
424#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF)
425
426/*Address Reply Descriptor */
427typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR {
428 U8 ReplyFlags; /*0x00 */
429 U8 MSIxIndex; /*0x01 */
430 U16 SMID; /*0x02 */
431 U32 ReplyFrameAddress; /*0x04 */
432} MPI2_ADDRESS_REPLY_DESCRIPTOR,
433 *PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
434 Mpi2AddressReplyDescriptor_t,
435 *pMpi2AddressReplyDescriptor_t;
436
437#define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00)
438
439/*SCSI IO Success Reply Descriptor */
440typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR {
441 U8 ReplyFlags; /*0x00 */
442 U8 MSIxIndex; /*0x01 */
443 U16 SMID; /*0x02 */
444 U16 TaskTag; /*0x04 */
445 U16 Reserved1; /*0x06 */
446} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
447 *PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
448 Mpi2SCSIIOSuccessReplyDescriptor_t,
449 *pMpi2SCSIIOSuccessReplyDescriptor_t;
450
451/*TargetAssist Success Reply Descriptor */
452typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR {
453 U8 ReplyFlags; /*0x00 */
454 U8 MSIxIndex; /*0x01 */
455 U16 SMID; /*0x02 */
456 U8 SequenceNumber; /*0x04 */
457 U8 Reserved1; /*0x05 */
458 U16 IoIndex; /*0x06 */
459} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
460 *PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
461 Mpi2TargetAssistSuccessReplyDescriptor_t,
462 *pMpi2TargetAssistSuccessReplyDescriptor_t;
463
464/*Target Command Buffer Reply Descriptor */
465typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR {
466 U8 ReplyFlags; /*0x00 */
467 U8 MSIxIndex; /*0x01 */
468 U8 VP_ID; /*0x02 */
469 U8 Flags; /*0x03 */
470 U16 InitiatorDevHandle; /*0x04 */
471 U16 IoIndex; /*0x06 */
472} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
473 *PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
474 Mpi2TargetCommandBufferReplyDescriptor_t,
475 *pMpi2TargetCommandBufferReplyDescriptor_t;
476
477/*defines for Flags field */
478#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F)
479
480/*RAID Accelerator Success Reply Descriptor */
481typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR {
482 U8 ReplyFlags; /*0x00 */
483 U8 MSIxIndex; /*0x01 */
484 U16 SMID; /*0x02 */
485 U32 Reserved; /*0x04 */
486} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
487 *PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR,
488 Mpi2RAIDAcceleratorSuccessReplyDescriptor_t,
489 *pMpi2RAIDAcceleratorSuccessReplyDescriptor_t;
490
491/*Fast Path SCSI IO Success Reply Descriptor */
492typedef MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
493 MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
494 *PTR_MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
495 Mpi25FastPathSCSIIOSuccessReplyDescriptor_t,
496 *pMpi25FastPathSCSIIOSuccessReplyDescriptor_t;
497
498/*union of Reply Descriptors */
499typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
500 MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
501 MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply;
502 MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess;
503 MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
504 MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
505 MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess;
506 MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR FastPathSCSIIOSuccess;
507 U64 Words;
508} MPI2_REPLY_DESCRIPTORS_UNION,
509 *PTR_MPI2_REPLY_DESCRIPTORS_UNION,
510 Mpi2ReplyDescriptorsUnion_t,
511 *pMpi2ReplyDescriptorsUnion_t;
512
513/*****************************************************************************
514*
515* Message Functions
516*
517*****************************************************************************/
518
519#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00)
520#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01)
521#define MPI2_FUNCTION_IOC_INIT (0x02)
522#define MPI2_FUNCTION_IOC_FACTS (0x03)
523#define MPI2_FUNCTION_CONFIG (0x04)
524#define MPI2_FUNCTION_PORT_FACTS (0x05)
525#define MPI2_FUNCTION_PORT_ENABLE (0x06)
526#define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07)
527#define MPI2_FUNCTION_EVENT_ACK (0x08)
528#define MPI2_FUNCTION_FW_DOWNLOAD (0x09)
529#define MPI2_FUNCTION_TARGET_ASSIST (0x0B)
530#define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C)
531#define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D)
532#define MPI2_FUNCTION_FW_UPLOAD (0x12)
533#define MPI2_FUNCTION_RAID_ACTION (0x15)
534#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16)
535#define MPI2_FUNCTION_TOOLBOX (0x17)
536#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18)
537#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A)
538#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B)
539#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C)
540#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D)
541#define MPI2_FUNCTION_DIAG_RELEASE (0x1E)
542#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24)
543#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25)
544#define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C)
545#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F)
546#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30)
547#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31)
548#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0)
549#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF)
550
551/*Doorbell functions */
552#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40)
553#define MPI2_FUNCTION_HANDSHAKE (0x42)
554
555/*****************************************************************************
556*
557* IOC Status Values
558*
559*****************************************************************************/
560
561/*mask for IOCStatus status value */
562#define MPI2_IOCSTATUS_MASK (0x7FFF)
563
564/****************************************************************************
565* Common IOCStatus values for all replies
566****************************************************************************/
567
568#define MPI2_IOCSTATUS_SUCCESS (0x0000)
569#define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001)
570#define MPI2_IOCSTATUS_BUSY (0x0002)
571#define MPI2_IOCSTATUS_INVALID_SGL (0x0003)
572#define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004)
573#define MPI2_IOCSTATUS_INVALID_VPID (0x0005)
574#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006)
575#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007)
576#define MPI2_IOCSTATUS_INVALID_STATE (0x0008)
577#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009)
578
579/****************************************************************************
580* Config IOCStatus values
581****************************************************************************/
582
583#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020)
584#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021)
585#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022)
586#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023)
587#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024)
588#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025)
589
590/****************************************************************************
591* SCSI IO Reply
592****************************************************************************/
593
594#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040)
595#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042)
596#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043)
597#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044)
598#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045)
599#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046)
600#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047)
601#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048)
602#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049)
603#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A)
604#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B)
605#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C)
606
607/****************************************************************************
608* For use by SCSI Initiator and SCSI Target end-to-end data protection
609****************************************************************************/
610
611#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D)
612#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E)
613#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F)
614
615/****************************************************************************
616* SCSI Target values
617****************************************************************************/
618
619#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062)
620#define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063)
621#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064)
622#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065)
623#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
624#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
625#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
626#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
627#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)
628#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)
629
630/****************************************************************************
631* Serial Attached SCSI values
632****************************************************************************/
633
634#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
635#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091)
636
637/****************************************************************************
638* Diagnostic Buffer Post / Diagnostic Release values
639****************************************************************************/
640
641#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0)
642
643/****************************************************************************
644* RAID Accelerator values
645****************************************************************************/
646
647#define MPI2_IOCSTATUS_RAID_ACCEL_ERROR (0x00B0)
648
649/****************************************************************************
650* IOCStatus flag to indicate that log info is available
651****************************************************************************/
652
653#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000)
654
655/****************************************************************************
656* IOCLogInfo Types
657****************************************************************************/
658
659#define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000)
660#define MPI2_IOCLOGINFO_TYPE_SHIFT (28)
661#define MPI2_IOCLOGINFO_TYPE_NONE (0x0)
662#define MPI2_IOCLOGINFO_TYPE_SCSI (0x1)
663#define MPI2_IOCLOGINFO_TYPE_FC (0x2)
664#define MPI2_IOCLOGINFO_TYPE_SAS (0x3)
665#define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4)
666#define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF)
667
668/*****************************************************************************
669*
670* Standard Message Structures
671*
672*****************************************************************************/
673
674/****************************************************************************
675*Request Message Header for all request messages
676****************************************************************************/
677
678typedef struct _MPI2_REQUEST_HEADER {
679 U16 FunctionDependent1; /*0x00 */
680 U8 ChainOffset; /*0x02 */
681 U8 Function; /*0x03 */
682 U16 FunctionDependent2; /*0x04 */
683 U8 FunctionDependent3; /*0x06 */
684 U8 MsgFlags; /*0x07 */
685 U8 VP_ID; /*0x08 */
686 U8 VF_ID; /*0x09 */
687 U16 Reserved1; /*0x0A */
688} MPI2_REQUEST_HEADER, *PTR_MPI2_REQUEST_HEADER,
689 MPI2RequestHeader_t, *pMPI2RequestHeader_t;
690
691/****************************************************************************
692* Default Reply
693****************************************************************************/
694
695typedef struct _MPI2_DEFAULT_REPLY {
696 U16 FunctionDependent1; /*0x00 */
697 U8 MsgLength; /*0x02 */
698 U8 Function; /*0x03 */
699 U16 FunctionDependent2; /*0x04 */
700 U8 FunctionDependent3; /*0x06 */
701 U8 MsgFlags; /*0x07 */
702 U8 VP_ID; /*0x08 */
703 U8 VF_ID; /*0x09 */
704 U16 Reserved1; /*0x0A */
705 U16 FunctionDependent5; /*0x0C */
706 U16 IOCStatus; /*0x0E */
707 U32 IOCLogInfo; /*0x10 */
708} MPI2_DEFAULT_REPLY, *PTR_MPI2_DEFAULT_REPLY,
709 MPI2DefaultReply_t, *pMPI2DefaultReply_t;
710
711/*common version structure/union used in messages and configuration pages */
712
713typedef struct _MPI2_VERSION_STRUCT {
714 U8 Dev; /*0x00 */
715 U8 Unit; /*0x01 */
716 U8 Minor; /*0x02 */
717 U8 Major; /*0x03 */
718} MPI2_VERSION_STRUCT;
719
720typedef union _MPI2_VERSION_UNION {
721 MPI2_VERSION_STRUCT Struct;
722 U32 Word;
723} MPI2_VERSION_UNION;
724
725/*LUN field defines, common to many structures */
726#define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF)
727#define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000)
728#define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF)
729#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000)
730#define MPI2_LUN_LEVEL_1_WORD (0xFF00)
731#define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00)
732
733/*****************************************************************************
734*
735* Fusion-MPT MPI Scatter Gather Elements
736*
737*****************************************************************************/
738
739/****************************************************************************
740* MPI Simple Element structures
741****************************************************************************/
742
743typedef struct _MPI2_SGE_SIMPLE32 {
744 U32 FlagsLength;
745 U32 Address;
746} MPI2_SGE_SIMPLE32, *PTR_MPI2_SGE_SIMPLE32,
747 Mpi2SGESimple32_t, *pMpi2SGESimple32_t;
748
749typedef struct _MPI2_SGE_SIMPLE64 {
750 U32 FlagsLength;
751 U64 Address;
752} MPI2_SGE_SIMPLE64, *PTR_MPI2_SGE_SIMPLE64,
753 Mpi2SGESimple64_t, *pMpi2SGESimple64_t;
754
755typedef struct _MPI2_SGE_SIMPLE_UNION {
756 U32 FlagsLength;
757 union {
758 U32 Address32;
759 U64 Address64;
760 } u;
761} MPI2_SGE_SIMPLE_UNION,
762 *PTR_MPI2_SGE_SIMPLE_UNION,
763 Mpi2SGESimpleUnion_t,
764 *pMpi2SGESimpleUnion_t;
765
766/****************************************************************************
767* MPI Chain Element structures - for MPI v2.0 products only
768****************************************************************************/
769
770typedef struct _MPI2_SGE_CHAIN32 {
771 U16 Length;
772 U8 NextChainOffset;
773 U8 Flags;
774 U32 Address;
775} MPI2_SGE_CHAIN32, *PTR_MPI2_SGE_CHAIN32,
776 Mpi2SGEChain32_t, *pMpi2SGEChain32_t;
777
778typedef struct _MPI2_SGE_CHAIN64 {
779 U16 Length;
780 U8 NextChainOffset;
781 U8 Flags;
782 U64 Address;
783} MPI2_SGE_CHAIN64, *PTR_MPI2_SGE_CHAIN64,
784 Mpi2SGEChain64_t, *pMpi2SGEChain64_t;
785
786typedef struct _MPI2_SGE_CHAIN_UNION {
787 U16 Length;
788 U8 NextChainOffset;
789 U8 Flags;
790 union {
791 U32 Address32;
792 U64 Address64;
793 } u;
794} MPI2_SGE_CHAIN_UNION,
795 *PTR_MPI2_SGE_CHAIN_UNION,
796 Mpi2SGEChainUnion_t,
797 *pMpi2SGEChainUnion_t;
798
799/****************************************************************************
800* MPI Transaction Context Element structures - for MPI v2.0 products only
801****************************************************************************/
802
803typedef struct _MPI2_SGE_TRANSACTION32 {
804 U8 Reserved;
805 U8 ContextSize;
806 U8 DetailsLength;
807 U8 Flags;
808 U32 TransactionContext[1];
809 U32 TransactionDetails[1];
810} MPI2_SGE_TRANSACTION32,
811 *PTR_MPI2_SGE_TRANSACTION32,
812 Mpi2SGETransaction32_t,
813 *pMpi2SGETransaction32_t;
814
815typedef struct _MPI2_SGE_TRANSACTION64 {
816 U8 Reserved;
817 U8 ContextSize;
818 U8 DetailsLength;
819 U8 Flags;
820 U32 TransactionContext[2];
821 U32 TransactionDetails[1];
822} MPI2_SGE_TRANSACTION64,
823 *PTR_MPI2_SGE_TRANSACTION64,
824 Mpi2SGETransaction64_t,
825 *pMpi2SGETransaction64_t;
826
827typedef struct _MPI2_SGE_TRANSACTION96 {
828 U8 Reserved;
829 U8 ContextSize;
830 U8 DetailsLength;
831 U8 Flags;
832 U32 TransactionContext[3];
833 U32 TransactionDetails[1];
834} MPI2_SGE_TRANSACTION96, *PTR_MPI2_SGE_TRANSACTION96,
835 Mpi2SGETransaction96_t, *pMpi2SGETransaction96_t;
836
837typedef struct _MPI2_SGE_TRANSACTION128 {
838 U8 Reserved;
839 U8 ContextSize;
840 U8 DetailsLength;
841 U8 Flags;
842 U32 TransactionContext[4];
843 U32 TransactionDetails[1];
844} MPI2_SGE_TRANSACTION128, *PTR_MPI2_SGE_TRANSACTION128,
845 Mpi2SGETransaction_t128, *pMpi2SGETransaction_t128;
846
847typedef struct _MPI2_SGE_TRANSACTION_UNION {
848 U8 Reserved;
849 U8 ContextSize;
850 U8 DetailsLength;
851 U8 Flags;
852 union {
853 U32 TransactionContext32[1];
854 U32 TransactionContext64[2];
855 U32 TransactionContext96[3];
856 U32 TransactionContext128[4];
857 } u;
858 U32 TransactionDetails[1];
859} MPI2_SGE_TRANSACTION_UNION,
860 *PTR_MPI2_SGE_TRANSACTION_UNION,
861 Mpi2SGETransactionUnion_t,
862 *pMpi2SGETransactionUnion_t;
863
864/****************************************************************************
865* MPI SGE union for IO SGL's - for MPI v2.0 products only
866****************************************************************************/
867
868typedef struct _MPI2_MPI_SGE_IO_UNION {
869 union {
870 MPI2_SGE_SIMPLE_UNION Simple;
871 MPI2_SGE_CHAIN_UNION Chain;
872 } u;
873} MPI2_MPI_SGE_IO_UNION, *PTR_MPI2_MPI_SGE_IO_UNION,
874 Mpi2MpiSGEIOUnion_t, *pMpi2MpiSGEIOUnion_t;
875
876/****************************************************************************
877* MPI SGE union for SGL's with Simple and Transaction elements - for MPI v2.0 products only
878****************************************************************************/
879
880typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION {
881 union {
882 MPI2_SGE_SIMPLE_UNION Simple;
883 MPI2_SGE_TRANSACTION_UNION Transaction;
884 } u;
885} MPI2_SGE_TRANS_SIMPLE_UNION,
886 *PTR_MPI2_SGE_TRANS_SIMPLE_UNION,
887 Mpi2SGETransSimpleUnion_t,
888 *pMpi2SGETransSimpleUnion_t;
889
890/****************************************************************************
891* All MPI SGE types union
892****************************************************************************/
893
894typedef struct _MPI2_MPI_SGE_UNION {
895 union {
896 MPI2_SGE_SIMPLE_UNION Simple;
897 MPI2_SGE_CHAIN_UNION Chain;
898 MPI2_SGE_TRANSACTION_UNION Transaction;
899 } u;
900} MPI2_MPI_SGE_UNION, *PTR_MPI2_MPI_SGE_UNION,
901 Mpi2MpiSgeUnion_t, *pMpi2MpiSgeUnion_t;
902
903/****************************************************************************
904* MPI SGE field definition and masks
905****************************************************************************/
906
907/*Flags field bit definitions */
908
909#define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80)
910#define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40)
911#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30)
912#define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08)
913#define MPI2_SGE_FLAGS_DIRECTION (0x04)
914#define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02)
915#define MPI2_SGE_FLAGS_END_OF_LIST (0x01)
916
917#define MPI2_SGE_FLAGS_SHIFT (24)
918
919#define MPI2_SGE_LENGTH_MASK (0x00FFFFFF)
920#define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF)
921
922/*Element Type */
923
924#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00)
925#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10)
926#define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30)
927#define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30)
928
929/*Address location */
930
931#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00)
932
933/*Direction */
934
935#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00)
936#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04)
937
938#define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST)
939#define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC)
940
941/*Address Size */
942
943#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00)
944#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02)
945
946/*Context Size */
947
948#define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00)
949#define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02)
950#define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04)
951#define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06)
952
953#define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000)
954#define MPI2_SGE_CHAIN_OFFSET_SHIFT (16)
955
956/****************************************************************************
957* MPI SGE operation Macros
958****************************************************************************/
959
960/*SIMPLE FlagsLength manipulations... */
961#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT)
962#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> \
963 MPI2_SGE_FLAGS_SHIFT)
964#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK)
965#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK)
966
967#define MPI2_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_SGE_SET_FLAGS(f) | \
968 MPI2_SGE_LENGTH(l))
969
970#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength)
971#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength)
972#define MPI2_pSGE_SET_FLAGS_LENGTH(psg, f, l) ((psg)->FlagsLength = \
973 MPI2_SGE_SET_FLAGS_LENGTH(f, l))
974
975/*CAUTION - The following are READ-MODIFY-WRITE! */
976#define MPI2_pSGE_SET_FLAGS(psg, f) ((psg)->FlagsLength |= \
977 MPI2_SGE_SET_FLAGS(f))
978#define MPI2_pSGE_SET_LENGTH(psg, l) ((psg)->FlagsLength |= \
979 MPI2_SGE_LENGTH(l))
980
981#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> \
982 MPI2_SGE_CHAIN_OFFSET_SHIFT)
983
984/*****************************************************************************
985*
986* Fusion-MPT IEEE Scatter Gather Elements
987*
988*****************************************************************************/
989
990/****************************************************************************
991* IEEE Simple Element structures
992****************************************************************************/
993
994/*MPI2_IEEE_SGE_SIMPLE32 is for MPI v2.0 products only */
995typedef struct _MPI2_IEEE_SGE_SIMPLE32 {
996 U32 Address;
997 U32 FlagsLength;
998} MPI2_IEEE_SGE_SIMPLE32, *PTR_MPI2_IEEE_SGE_SIMPLE32,
999 Mpi2IeeeSgeSimple32_t, *pMpi2IeeeSgeSimple32_t;
1000
1001typedef struct _MPI2_IEEE_SGE_SIMPLE64 {
1002 U64 Address;
1003 U32 Length;
1004 U16 Reserved1;
1005 U8 Reserved2;
1006 U8 Flags;
1007} MPI2_IEEE_SGE_SIMPLE64, *PTR_MPI2_IEEE_SGE_SIMPLE64,
1008 Mpi2IeeeSgeSimple64_t, *pMpi2IeeeSgeSimple64_t;
1009
1010typedef union _MPI2_IEEE_SGE_SIMPLE_UNION {
1011 MPI2_IEEE_SGE_SIMPLE32 Simple32;
1012 MPI2_IEEE_SGE_SIMPLE64 Simple64;
1013} MPI2_IEEE_SGE_SIMPLE_UNION,
1014 *PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
1015 Mpi2IeeeSgeSimpleUnion_t,
1016 *pMpi2IeeeSgeSimpleUnion_t;
1017
1018/****************************************************************************
1019* IEEE Chain Element structures
1020****************************************************************************/
1021
1022/*MPI2_IEEE_SGE_CHAIN32 is for MPI v2.0 products only */
1023typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32;
1024
1025/*MPI2_IEEE_SGE_CHAIN64 is for MPI v2.0 products only */
1026typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64;
1027
1028typedef union _MPI2_IEEE_SGE_CHAIN_UNION {
1029 MPI2_IEEE_SGE_CHAIN32 Chain32;
1030 MPI2_IEEE_SGE_CHAIN64 Chain64;
1031} MPI2_IEEE_SGE_CHAIN_UNION,
1032 *PTR_MPI2_IEEE_SGE_CHAIN_UNION,
1033 Mpi2IeeeSgeChainUnion_t,
1034 *pMpi2IeeeSgeChainUnion_t;
1035
1036/*MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 products only */
1037typedef struct _MPI25_IEEE_SGE_CHAIN64 {
1038 U64 Address;
1039 U32 Length;
1040 U16 Reserved1;
1041 U8 NextChainOffset;
1042 U8 Flags;
1043} MPI25_IEEE_SGE_CHAIN64,
1044 *PTR_MPI25_IEEE_SGE_CHAIN64,
1045 Mpi25IeeeSgeChain64_t,
1046 *pMpi25IeeeSgeChain64_t;
1047
1048/****************************************************************************
1049* All IEEE SGE types union
1050****************************************************************************/
1051
1052/*MPI2_IEEE_SGE_UNION is for MPI v2.0 products only */
1053typedef struct _MPI2_IEEE_SGE_UNION {
1054 union {
1055 MPI2_IEEE_SGE_SIMPLE_UNION Simple;
1056 MPI2_IEEE_SGE_CHAIN_UNION Chain;
1057 } u;
1058} MPI2_IEEE_SGE_UNION, *PTR_MPI2_IEEE_SGE_UNION,
1059 Mpi2IeeeSgeUnion_t, *pMpi2IeeeSgeUnion_t;
1060
1061/****************************************************************************
1062* IEEE SGE union for IO SGL's
1063****************************************************************************/
1064
1065typedef union _MPI25_SGE_IO_UNION {
1066 MPI2_IEEE_SGE_SIMPLE64 IeeeSimple;
1067 MPI25_IEEE_SGE_CHAIN64 IeeeChain;
1068} MPI25_SGE_IO_UNION, *PTR_MPI25_SGE_IO_UNION,
1069 Mpi25SGEIOUnion_t, *pMpi25SGEIOUnion_t;
1070
1071/****************************************************************************
1072* IEEE SGE field definitions and masks
1073****************************************************************************/
1074
1075/*Flags field bit definitions */
1076
1077#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80)
1078#define MPI25_IEEE_SGE_FLAGS_END_OF_LIST (0x40)
1079
1080#define MPI2_IEEE32_SGE_FLAGS_SHIFT (24)
1081
1082#define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF)
1083
1084/*Element Type */
1085
1086#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00)
1087#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
1088
1089/*Data Location Address Space */
1090
1091#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03)
1092#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
1093#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
1094#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
1095#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
1096#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR (0x03)
1097#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR \
1098 (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR)
1099
1100/****************************************************************************
1101* IEEE SGE operation Macros
1102****************************************************************************/
1103
1104/*SIMPLE FlagsLength manipulations... */
1105#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT)
1106#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) \
1107 >> MPI2_IEEE32_SGE_FLAGS_SHIFT)
1108#define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK)
1109
1110#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) |\
1111 MPI2_IEEE32_SGE_LENGTH(l))
1112
1113#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) \
1114 MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength)
1115#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) \
1116 MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength)
1117#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg, f, l) ((psg)->FlagsLength = \
1118 MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l))
1119
1120/*CAUTION - The following are READ-MODIFY-WRITE! */
1121#define MPI2_IEEE32_pSGE_SET_FLAGS(psg, f) ((psg)->FlagsLength |= \
1122 MPI2_IEEE32_SGE_SET_FLAGS(f))
1123#define MPI2_IEEE32_pSGE_SET_LENGTH(psg, l) ((psg)->FlagsLength |= \
1124 MPI2_IEEE32_SGE_LENGTH(l))
1125
1126/*****************************************************************************
1127*
1128* Fusion-MPT MPI/IEEE Scatter Gather Unions
1129*
1130*****************************************************************************/
1131
1132typedef union _MPI2_SIMPLE_SGE_UNION {
1133 MPI2_SGE_SIMPLE_UNION MpiSimple;
1134 MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
1135} MPI2_SIMPLE_SGE_UNION, *PTR_MPI2_SIMPLE_SGE_UNION,
1136 Mpi2SimpleSgeUntion_t, *pMpi2SimpleSgeUntion_t;
1137
1138typedef union _MPI2_SGE_IO_UNION {
1139 MPI2_SGE_SIMPLE_UNION MpiSimple;
1140 MPI2_SGE_CHAIN_UNION MpiChain;
1141 MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
1142 MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;
1143} MPI2_SGE_IO_UNION, *PTR_MPI2_SGE_IO_UNION,
1144 Mpi2SGEIOUnion_t, *pMpi2SGEIOUnion_t;
1145
1146/****************************************************************************
1147*
1148* Values for SGLFlags field, used in many request messages with an SGL
1149*
1150****************************************************************************/
1151
1152/*values for MPI SGL Data Location Address Space subfield */
1153#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C)
1154#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00)
1155#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04)
1156#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08)
1157#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C)
1158/*values for SGL Type subfield */
1159#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03)
1160#define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00)
1161#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01)
1162#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02)
1163
1164#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
new file mode 100644
index 000000000000..d8b2c3eedb57
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -0,0 +1,3323 @@
1/*
2 * Copyright (c) 2000-2011 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.22
10 *
11 * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
12 * prefix are for use only on MPI v2.5 products, and must not be used
13 * with MPI v2.0 products. Unless otherwise noted, names beginning with
14 * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
15 *
16 * Version History
17 * ---------------
18 *
19 * Date Version Description
20 * -------- -------- ------------------------------------------------------
21 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
22 * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags.
23 * Added Manufacturing Page 11.
24 * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
25 * define.
26 * 06-26-07 02.00.02 Adding generic structure for product-specific
27 * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
28 * Rework of BIOS Page 2 configuration page.
29 * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
30 * forms.
31 * Added configuration pages IOC Page 8 and Driver
32 * Persistent Mapping Page 0.
33 * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated
34 * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
35 * RAID Physical Disk Pages 0 and 1, RAID Configuration
36 * Page 0).
37 * Added new value for AccessStatus field of SAS Device
38 * Page 0 (_SATA_NEEDS_INITIALIZATION).
39 * 10-31-07 02.00.04 Added missing SEPDevHandle field to
40 * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
41 * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for
42 * NVDATA.
43 * Modified IOC Page 7 to use masks and added field for
44 * SASBroadcastPrimitiveMasks.
45 * Added MPI2_CONFIG_PAGE_BIOS_4.
46 * Added MPI2_CONFIG_PAGE_LOG_0.
47 * 02-29-08 02.00.06 Modified various names to make them 32-character unique.
48 * Added SAS Device IDs.
49 * Updated Integrated RAID configuration pages including
50 * Manufacturing Page 4, IOC Page 6, and RAID Configuration
51 * Page 0.
52 * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
53 * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
54 * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
55 * Added missing MaxNumRoutedSasAddresses field to
56 * MPI2_CONFIG_PAGE_EXPANDER_0.
57 * Added SAS Port Page 0.
58 * Modified structure layout for
59 * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
60 * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
61 * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
62 * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
63 * to 0x000000FF.
64 * Added two new values for the Physical Disk Coercion Size
65 * bits in the Flags field of Manufacturing Page 4.
66 * Added product-specific Manufacturing pages 16 to 31.
67 * Modified Flags bits for controlling write cache on SATA
68 * drives in IO Unit Page 1.
69 * Added new bit to AdditionalControlFlags of SAS IO Unit
70 * Page 1 to control Invalid Topology Correction.
71 * Added additional defines for RAID Volume Page 0
72 * VolumeStatusFlags field.
73 * Modified meaning of RAID Volume Page 0 VolumeSettings
74 * define for auto-configure of hot-swap drives.
75 * Added SupportedPhysDisks field to RAID Volume Page 1 and
76 * added related defines.
77 * Added PhysDiskAttributes field (and related defines) to
78 * RAID Physical Disk Page 0.
79 * Added MPI2_SAS_PHYINFO_PHY_VACANT define.
80 * Added three new DiscoveryStatus bits for SAS IO Unit
81 * Page 0 and SAS Expander Page 0.
82 * Removed multiplexing information from SAS IO Unit pages.
83 * Added BootDeviceWaitTime field to SAS IO Unit Page 4.
84 * Removed Zone Address Resolved bit from PhyInfo and from
85 * Expander Page 0 Flags field.
86 * Added two new AccessStatus values to SAS Device Page 0
87 * for indicating routing problems. Added 3 reserved words
88 * to this page.
89 * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3.
90 * Inserted missing reserved field into structure for IOC
91 * Page 6.
92 * Added more pending task bits to RAID Volume Page 0
93 * VolumeStatusFlags defines.
94 * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
95 * Added a new DiscoveryStatus bit for SAS IO Unit Page 0
96 * and SAS Expander Page 0 to flag a downstream initiator
97 * when in simplified routing mode.
98 * Removed SATA Init Failure defines for DiscoveryStatus
99 * fields of SAS IO Unit Page 0 and SAS Expander Page 0.
100 * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
101 * Added PortGroups, DmaGroup, and ControlGroup fields to
102 * SAS Device Page 0.
103 * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO
104 * Unit Page 6.
105 * Added expander reduced functionality data to SAS
106 * Expander Page 0.
107 * Added SAS PHY Page 2 and SAS PHY Page 3.
108 * 07-30-09 02.00.12 Added IO Unit Page 7.
109 * Added new device ids.
110 * Added SAS IO Unit Page 5.
111 * Added partial and slumber power management capable flags
112 * to SAS Device Page 0 Flags field.
113 * Added PhyInfo defines for power condition.
114 * Added Ethernet configuration pages.
115 * 10-28-09 02.00.13 Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY.
116 * Added SAS PHY Page 4 structure and defines.
117 * 02-10-10 02.00.14 Modified the comments for the configuration page
118 * structures that contain an array of data. The host
119 * should use the "count" field in the page data (e.g. the
120 * NumPhys field) to determine the number of valid elements
121 * in the array.
122 * Added/modified some MPI2_MFGPAGE_DEVID_SAS defines.
123 * Added PowerManagementCapabilities to IO Unit Page 7.
124 * Added PortWidthModGroup field to
125 * MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS.
126 * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines.
127 * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines.
128 * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines.
129 * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT
130 * define.
131 * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
132 * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
133 * 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing)
134 * defines.
135 * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to
136 * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
137 * the Pinout field.
138 * Added BoardTemperature and BoardTemperatureUnits fields
139 * to MPI2_CONFIG_PAGE_IO_UNIT_7.
140 * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
141 * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
142 * 02-23-11 02.00.18 Added ProxyVF_ID field to MPI2_CONFIG_REQUEST.
143 * Added IO Unit Page 8, IO Unit Page 9,
144 * and IO Unit Page 10.
145 * Added SASNotifyPrimitiveMasks field to
146 * MPI2_CONFIG_PAGE_IOC_7.
147 * 03-09-11 02.00.19 Fixed IO Unit Page 10 (to match the spec).
148 * 05-25-11 02.00.20 Cleaned up a few comments.
149 * 08-24-11 02.00.21 Marked the IO Unit Page 7 PowerManagementCapabilities
150 * for PCIe link as obsolete.
151 * Added SpinupFlags field containing a Disable Spin-up bit
152 * to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of SAS IO
153 * Unit Page 4.
154 * 11-18-11 02.00.22 Added define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT.
155 * Added UEFIVersion field to BIOS Page 1 and defined new
156 * BiosOptions bits.
157 * Incorporating additions for MPI v2.5.
158 * --------------------------------------------------------------------------
159 */
160
161#ifndef MPI2_CNFG_H
162#define MPI2_CNFG_H
163
164/*****************************************************************************
165* Configuration Page Header and defines
166*****************************************************************************/
167
168/*Config Page Header */
169typedef struct _MPI2_CONFIG_PAGE_HEADER {
170 U8 PageVersion; /*0x00 */
171 U8 PageLength; /*0x01 */
172 U8 PageNumber; /*0x02 */
173 U8 PageType; /*0x03 */
174} MPI2_CONFIG_PAGE_HEADER, *PTR_MPI2_CONFIG_PAGE_HEADER,
175 Mpi2ConfigPageHeader_t, *pMpi2ConfigPageHeader_t;
176
177typedef union _MPI2_CONFIG_PAGE_HEADER_UNION {
178 MPI2_CONFIG_PAGE_HEADER Struct;
179 U8 Bytes[4];
180 U16 Word16[2];
181 U32 Word32;
182} MPI2_CONFIG_PAGE_HEADER_UNION, *PTR_MPI2_CONFIG_PAGE_HEADER_UNION,
183 Mpi2ConfigPageHeaderUnion, *pMpi2ConfigPageHeaderUnion;
184
185/*Extended Config Page Header */
186typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER {
187 U8 PageVersion; /*0x00 */
188 U8 Reserved1; /*0x01 */
189 U8 PageNumber; /*0x02 */
190 U8 PageType; /*0x03 */
191 U16 ExtPageLength; /*0x04 */
192 U8 ExtPageType; /*0x06 */
193 U8 Reserved2; /*0x07 */
194} MPI2_CONFIG_EXTENDED_PAGE_HEADER,
195 *PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER,
196 Mpi2ConfigExtendedPageHeader_t,
197 *pMpi2ConfigExtendedPageHeader_t;
198
199typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION {
200 MPI2_CONFIG_PAGE_HEADER Struct;
201 MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext;
202 U8 Bytes[8];
203 U16 Word16[4];
204 U32 Word32[2];
205} MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
206 *PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
207 Mpi2ConfigPageExtendedHeaderUnion,
208 *pMpi2ConfigPageExtendedHeaderUnion;
209
210
211/*PageType field values */
212#define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00)
213#define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10)
214#define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20)
215#define MPI2_CONFIG_PAGEATTR_MASK (0xF0)
216
217#define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00)
218#define MPI2_CONFIG_PAGETYPE_IOC (0x01)
219#define MPI2_CONFIG_PAGETYPE_BIOS (0x02)
220#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08)
221#define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09)
222#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A)
223#define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F)
224#define MPI2_CONFIG_PAGETYPE_MASK (0x0F)
225
226#define MPI2_CONFIG_TYPENUM_MASK (0x0FFF)
227
228
229/*ExtPageType field values */
230#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10)
231#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11)
232#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12)
233#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13)
234#define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14)
235#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15)
236#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16)
237#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17)
238#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
239#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19)
240#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A)
241
242
243/*****************************************************************************
244* PageAddress defines
245*****************************************************************************/
246
247/*RAID Volume PageAddress format */
248#define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000)
249#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
250#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000)
251
252#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF)
253
254
255/*RAID Physical Disk PageAddress format */
256#define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000)
257#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000)
258#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000)
259#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000)
260
261#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF)
262#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF)
263
264
265/*SAS Expander PageAddress format */
266#define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000)
267#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000)
268#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000)
269#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000)
270
271#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF)
272#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000)
273#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16)
274
275
276/*SAS Device PageAddress format */
277#define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000)
278#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
279#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000)
280
281#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF)
282
283
284/*SAS PHY PageAddress format */
285#define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000)
286#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000)
287#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000)
288
289#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF)
290#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF)
291
292
293/*SAS Port PageAddress format */
294#define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000)
295#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000)
296#define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000)
297
298#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF)
299
300
301/*SAS Enclosure PageAddress format */
302#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000)
303#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
304#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000)
305
306#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF)
307
308
309/*RAID Configuration PageAddress format */
310#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000)
311#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000)
312#define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000)
313#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000)
314
315#define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF)
316
317
318/*Driver Persistent Mapping PageAddress format */
319#define MPI2_DPM_PGAD_FORM_MASK (0xF0000000)
320#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000)
321
322#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000)
323#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16)
324#define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF)
325
326
327/*Ethernet PageAddress format */
328#define MPI2_ETHERNET_PGAD_FORM_MASK (0xF0000000)
329#define MPI2_ETHERNET_PGAD_FORM_IF_NUM (0x00000000)
330
331#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF)
332
333
334
335/****************************************************************************
336* Configuration messages
337****************************************************************************/
338
339/*Configuration Request Message */
340typedef struct _MPI2_CONFIG_REQUEST {
341 U8 Action; /*0x00 */
342 U8 SGLFlags; /*0x01 */
343 U8 ChainOffset; /*0x02 */
344 U8 Function; /*0x03 */
345 U16 ExtPageLength; /*0x04 */
346 U8 ExtPageType; /*0x06 */
347 U8 MsgFlags; /*0x07 */
348 U8 VP_ID; /*0x08 */
349 U8 VF_ID; /*0x09 */
350 U16 Reserved1; /*0x0A */
351 U8 Reserved2; /*0x0C */
352 U8 ProxyVF_ID; /*0x0D */
353 U16 Reserved4; /*0x0E */
354 U32 Reserved3; /*0x10 */
355 MPI2_CONFIG_PAGE_HEADER Header; /*0x14 */
356 U32 PageAddress; /*0x18 */
357 MPI2_SGE_IO_UNION PageBufferSGE; /*0x1C */
358} MPI2_CONFIG_REQUEST, *PTR_MPI2_CONFIG_REQUEST,
359 Mpi2ConfigRequest_t, *pMpi2ConfigRequest_t;
360
361/*values for the Action field */
362#define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00)
363#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01)
364#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02)
365#define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03)
366#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04)
367#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05)
368#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06)
369#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07)
370
371/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
372
373
374/*Config Reply Message */
375typedef struct _MPI2_CONFIG_REPLY {
376 U8 Action; /*0x00 */
377 U8 SGLFlags; /*0x01 */
378 U8 MsgLength; /*0x02 */
379 U8 Function; /*0x03 */
380 U16 ExtPageLength; /*0x04 */
381 U8 ExtPageType; /*0x06 */
382 U8 MsgFlags; /*0x07 */
383 U8 VP_ID; /*0x08 */
384 U8 VF_ID; /*0x09 */
385 U16 Reserved1; /*0x0A */
386 U16 Reserved2; /*0x0C */
387 U16 IOCStatus; /*0x0E */
388 U32 IOCLogInfo; /*0x10 */
389 MPI2_CONFIG_PAGE_HEADER Header; /*0x14 */
390} MPI2_CONFIG_REPLY, *PTR_MPI2_CONFIG_REPLY,
391 Mpi2ConfigReply_t, *pMpi2ConfigReply_t;
392
393
394
395/*****************************************************************************
396*
397* C o n f i g u r a t i o n P a g e s
398*
399*****************************************************************************/
400
401/****************************************************************************
402* Manufacturing Config pages
403****************************************************************************/
404
405#define MPI2_MFGPAGE_VENDORID_LSI (0x1000)
406
407/*MPI v2.0 SAS products */
408#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070)
409#define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072)
410#define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074)
411#define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076)
412#define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077)
413#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064)
414#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065)
415
416#define MPI2_MFGPAGE_DEVID_SSS6200 (0x007E)
417
418#define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080)
419#define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081)
420#define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082)
421#define MPI2_MFGPAGE_DEVID_SAS2208_4 (0x0083)
422#define MPI2_MFGPAGE_DEVID_SAS2208_5 (0x0084)
423#define MPI2_MFGPAGE_DEVID_SAS2208_6 (0x0085)
424#define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086)
425#define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087)
426#define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E)
427
428/*MPI v2.5 SAS products */
429#define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096)
430#define MPI25_MFGPAGE_DEVID_SAS3008 (0x0097)
431#define MPI25_MFGPAGE_DEVID_SAS3108_1 (0x0090)
432#define MPI25_MFGPAGE_DEVID_SAS3108_2 (0x0091)
433#define MPI25_MFGPAGE_DEVID_SAS3108_5 (0x0094)
434#define MPI25_MFGPAGE_DEVID_SAS3108_6 (0x0095)
435
436
437
438
439/*Manufacturing Page 0 */
440
441typedef struct _MPI2_CONFIG_PAGE_MAN_0 {
442 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
443 U8 ChipName[16]; /*0x04 */
444 U8 ChipRevision[8]; /*0x14 */
445 U8 BoardName[16]; /*0x1C */
446 U8 BoardAssembly[16]; /*0x2C */
447 U8 BoardTracerNumber[16]; /*0x3C */
448} MPI2_CONFIG_PAGE_MAN_0,
449 *PTR_MPI2_CONFIG_PAGE_MAN_0,
450 Mpi2ManufacturingPage0_t,
451 *pMpi2ManufacturingPage0_t;
452
453#define MPI2_MANUFACTURING0_PAGEVERSION (0x00)
454
455
456/*Manufacturing Page 1 */
457
458typedef struct _MPI2_CONFIG_PAGE_MAN_1 {
459 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
460 U8 VPD[256]; /*0x04 */
461} MPI2_CONFIG_PAGE_MAN_1,
462 *PTR_MPI2_CONFIG_PAGE_MAN_1,
463 Mpi2ManufacturingPage1_t,
464 *pMpi2ManufacturingPage1_t;
465
466#define MPI2_MANUFACTURING1_PAGEVERSION (0x00)
467
468
469typedef struct _MPI2_CHIP_REVISION_ID {
470 U16 DeviceID; /*0x00 */
471 U8 PCIRevisionID; /*0x02 */
472 U8 Reserved; /*0x03 */
473} MPI2_CHIP_REVISION_ID, *PTR_MPI2_CHIP_REVISION_ID,
474 Mpi2ChipRevisionId_t, *pMpi2ChipRevisionId_t;
475
476
477/*Manufacturing Page 2 */
478
479/*
480 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
481 *one and check Header.PageLength at runtime.
482 */
483#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
484#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1)
485#endif
486
487typedef struct _MPI2_CONFIG_PAGE_MAN_2 {
488 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
489 MPI2_CHIP_REVISION_ID ChipId; /*0x04 */
490 U32
491 HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/*0x08 */
492} MPI2_CONFIG_PAGE_MAN_2,
493 *PTR_MPI2_CONFIG_PAGE_MAN_2,
494 Mpi2ManufacturingPage2_t,
495 *pMpi2ManufacturingPage2_t;
496
497#define MPI2_MANUFACTURING2_PAGEVERSION (0x00)
498
499
500/*Manufacturing Page 3 */
501
502/*
503 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
504 *one and check Header.PageLength at runtime.
505 */
506#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
507#define MPI2_MAN_PAGE_3_INFO_WORDS (1)
508#endif
509
510typedef struct _MPI2_CONFIG_PAGE_MAN_3 {
511 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
512 MPI2_CHIP_REVISION_ID ChipId; /*0x04 */
513 U32
514 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/*0x08 */
515} MPI2_CONFIG_PAGE_MAN_3,
516 *PTR_MPI2_CONFIG_PAGE_MAN_3,
517 Mpi2ManufacturingPage3_t,
518 *pMpi2ManufacturingPage3_t;
519
520#define MPI2_MANUFACTURING3_PAGEVERSION (0x00)
521
522
523/*Manufacturing Page 4 */
524
525typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS {
526 U8 PowerSaveFlags; /*0x00 */
527 U8 InternalOperationsSleepTime; /*0x01 */
528 U8 InternalOperationsRunTime; /*0x02 */
529 U8 HostIdleTime; /*0x03 */
530} MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
531 *PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
532 Mpi2ManPage4PwrSaveSettings_t,
533 *pMpi2ManPage4PwrSaveSettings_t;
534
535/*defines for the PowerSaveFlags field */
536#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03)
537#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00)
538#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01)
539#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02)
540
541typedef struct _MPI2_CONFIG_PAGE_MAN_4 {
542 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
543 U32 Reserved1; /*0x04 */
544 U32 Flags; /*0x08 */
545 U8 InquirySize; /*0x0C */
546 U8 Reserved2; /*0x0D */
547 U16 Reserved3; /*0x0E */
548 U8 InquiryData[56]; /*0x10 */
549 U32 RAID0VolumeSettings; /*0x48 */
550 U32 RAID1EVolumeSettings; /*0x4C */
551 U32 RAID1VolumeSettings; /*0x50 */
552 U32 RAID10VolumeSettings; /*0x54 */
553 U32 Reserved4; /*0x58 */
554 U32 Reserved5; /*0x5C */
555 MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /*0x60 */
556 U8 MaxOCEDisks; /*0x64 */
557 U8 ResyncRate; /*0x65 */
558 U16 DataScrubDuration; /*0x66 */
559 U8 MaxHotSpares; /*0x68 */
560 U8 MaxPhysDisksPerVol; /*0x69 */
561 U8 MaxPhysDisks; /*0x6A */
562 U8 MaxVolumes; /*0x6B */
563} MPI2_CONFIG_PAGE_MAN_4,
564 *PTR_MPI2_CONFIG_PAGE_MAN_4,
565 Mpi2ManufacturingPage4_t,
566 *pMpi2ManufacturingPage4_t;
567
568#define MPI2_MANUFACTURING4_PAGEVERSION (0x0A)
569
570/*Manufacturing Page 4 Flags field */
571#define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000)
572#define MPI2_MANPAGE4_METADATA_512MB (0x00000000)
573
574#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000)
575#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000)
576#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000)
577
578#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00)
579#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000)
580#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400)
581#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800)
582#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00)
583
584#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300)
585#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000)
586#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100)
587#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200)
588
589#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080)
590#define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040)
591#define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020)
592#define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010)
593#define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008)
594#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004)
595#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002)
596#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001)
597
598
599/*Manufacturing Page 5 */
600
601/*
602 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
603 *one and check the value returned for NumPhys at runtime.
604 */
605#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
606#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1)
607#endif
608
609typedef struct _MPI2_MANUFACTURING5_ENTRY {
610 U64 WWID; /*0x00 */
611 U64 DeviceName; /*0x08 */
612} MPI2_MANUFACTURING5_ENTRY,
613 *PTR_MPI2_MANUFACTURING5_ENTRY,
614 Mpi2Manufacturing5Entry_t,
615 *pMpi2Manufacturing5Entry_t;
616
617typedef struct _MPI2_CONFIG_PAGE_MAN_5 {
618 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
619 U8 NumPhys; /*0x04 */
620 U8 Reserved1; /*0x05 */
621 U16 Reserved2; /*0x06 */
622 U32 Reserved3; /*0x08 */
623 U32 Reserved4; /*0x0C */
624 MPI2_MANUFACTURING5_ENTRY
625 Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/*0x08 */
626} MPI2_CONFIG_PAGE_MAN_5,
627 *PTR_MPI2_CONFIG_PAGE_MAN_5,
628 Mpi2ManufacturingPage5_t,
629 *pMpi2ManufacturingPage5_t;
630
631#define MPI2_MANUFACTURING5_PAGEVERSION (0x03)
632
633
634/*Manufacturing Page 6 */
635
636typedef struct _MPI2_CONFIG_PAGE_MAN_6 {
637 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
638 U32 ProductSpecificInfo;/*0x04 */
639} MPI2_CONFIG_PAGE_MAN_6,
640 *PTR_MPI2_CONFIG_PAGE_MAN_6,
641 Mpi2ManufacturingPage6_t,
642 *pMpi2ManufacturingPage6_t;
643
644#define MPI2_MANUFACTURING6_PAGEVERSION (0x00)
645
646
647/*Manufacturing Page 7 */
648
649typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO {
650 U32 Pinout; /*0x00 */
651 U8 Connector[16]; /*0x04 */
652 U8 Location; /*0x14 */
653 U8 ReceptacleID; /*0x15 */
654 U16 Slot; /*0x16 */
655 U32 Reserved2; /*0x18 */
656} MPI2_MANPAGE7_CONNECTOR_INFO,
657 *PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
658 Mpi2ManPage7ConnectorInfo_t,
659 *pMpi2ManPage7ConnectorInfo_t;
660
661/*defines for the Pinout field */
662#define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00)
663#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8)
664
665#define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF)
666#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00)
667#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01)
668#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02)
669#define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03)
670#define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04)
671#define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05)
672#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06)
673#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07)
674#define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08)
675#define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09)
676#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A)
677#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B)
678#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C)
679#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D)
680
681/*defines for the Location field */
682#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
683#define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02)
684#define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04)
685#define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08)
686#define MPI2_MANPAGE7_LOCATION_AUTO (0x10)
687#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20)
688#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80)
689
690/*
691 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
692 *one and check the value returned for NumPhys at runtime.
693 */
694#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
695#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1)
696#endif
697
698typedef struct _MPI2_CONFIG_PAGE_MAN_7 {
699 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
700 U32 Reserved1; /*0x04 */
701 U32 Reserved2; /*0x08 */
702 U32 Flags; /*0x0C */
703 U8 EnclosureName[16]; /*0x10 */
704 U8 NumPhys; /*0x20 */
705 U8 Reserved3; /*0x21 */
706 U16 Reserved4; /*0x22 */
707 MPI2_MANPAGE7_CONNECTOR_INFO
708 ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /*0x24 */
709} MPI2_CONFIG_PAGE_MAN_7,
710 *PTR_MPI2_CONFIG_PAGE_MAN_7,
711 Mpi2ManufacturingPage7_t,
712 *pMpi2ManufacturingPage7_t;
713
714#define MPI2_MANUFACTURING7_PAGEVERSION (0x01)
715
716/*defines for the Flags field */
717#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
718
719
720/*
721 *Generic structure to use for product-specific manufacturing pages
722 *(currently Manufacturing Page 8 through Manufacturing Page 31).
723 */
724
725typedef struct _MPI2_CONFIG_PAGE_MAN_PS {
726 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
727 U32 ProductSpecificInfo;/*0x04 */
728} MPI2_CONFIG_PAGE_MAN_PS,
729 *PTR_MPI2_CONFIG_PAGE_MAN_PS,
730 Mpi2ManufacturingPagePS_t,
731 *pMpi2ManufacturingPagePS_t;
732
733#define MPI2_MANUFACTURING8_PAGEVERSION (0x00)
734#define MPI2_MANUFACTURING9_PAGEVERSION (0x00)
735#define MPI2_MANUFACTURING10_PAGEVERSION (0x00)
736#define MPI2_MANUFACTURING11_PAGEVERSION (0x00)
737#define MPI2_MANUFACTURING12_PAGEVERSION (0x00)
738#define MPI2_MANUFACTURING13_PAGEVERSION (0x00)
739#define MPI2_MANUFACTURING14_PAGEVERSION (0x00)
740#define MPI2_MANUFACTURING15_PAGEVERSION (0x00)
741#define MPI2_MANUFACTURING16_PAGEVERSION (0x00)
742#define MPI2_MANUFACTURING17_PAGEVERSION (0x00)
743#define MPI2_MANUFACTURING18_PAGEVERSION (0x00)
744#define MPI2_MANUFACTURING19_PAGEVERSION (0x00)
745#define MPI2_MANUFACTURING20_PAGEVERSION (0x00)
746#define MPI2_MANUFACTURING21_PAGEVERSION (0x00)
747#define MPI2_MANUFACTURING22_PAGEVERSION (0x00)
748#define MPI2_MANUFACTURING23_PAGEVERSION (0x00)
749#define MPI2_MANUFACTURING24_PAGEVERSION (0x00)
750#define MPI2_MANUFACTURING25_PAGEVERSION (0x00)
751#define MPI2_MANUFACTURING26_PAGEVERSION (0x00)
752#define MPI2_MANUFACTURING27_PAGEVERSION (0x00)
753#define MPI2_MANUFACTURING28_PAGEVERSION (0x00)
754#define MPI2_MANUFACTURING29_PAGEVERSION (0x00)
755#define MPI2_MANUFACTURING30_PAGEVERSION (0x00)
756#define MPI2_MANUFACTURING31_PAGEVERSION (0x00)
757
758
759/****************************************************************************
760* IO Unit Config Pages
761****************************************************************************/
762
763/*IO Unit Page 0 */
764
765typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0 {
766 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
767 U64 UniqueValue; /*0x04 */
768 MPI2_VERSION_UNION NvdataVersionDefault; /*0x08 */
769 MPI2_VERSION_UNION NvdataVersionPersistent; /*0x0A */
770} MPI2_CONFIG_PAGE_IO_UNIT_0,
771 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_0,
772 Mpi2IOUnitPage0_t, *pMpi2IOUnitPage0_t;
773
774#define MPI2_IOUNITPAGE0_PAGEVERSION (0x02)
775
776
777/*IO Unit Page 1 */
778
779typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 {
780 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
781 U32 Flags; /*0x04 */
782} MPI2_CONFIG_PAGE_IO_UNIT_1,
783 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_1,
784 Mpi2IOUnitPage1_t, *pMpi2IOUnitPage1_t;
785
786#define MPI2_IOUNITPAGE1_PAGEVERSION (0x04)
787
788/*IO Unit Page 1 Flags defines */
789#define MPI25_IOUNITPAGE1_NEW_DEVICE_FAST_PATH_DISABLE (0x00002000)
790#define MPI25_IOUNITPAGE1_DISABLE_FAST_PATH (0x00001000)
791#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY (0x00000800)
792#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600)
793#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT (9)
794#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000)
795#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200)
796#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400)
797#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100)
798#define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040)
799#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
800#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004)
801
802
803/*IO Unit Page 3 */
804
805/*
806 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
807 *one and check the value returned for GPIOCount at runtime.
808 */
809#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
810#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1)
811#endif
812
813typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 {
814 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
815 U8 GPIOCount; /*0x04 */
816 U8 Reserved1; /*0x05 */
817 U16 Reserved2; /*0x06 */
818 U16
819 GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/*0x08 */
820} MPI2_CONFIG_PAGE_IO_UNIT_3,
821 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
822 Mpi2IOUnitPage3_t, *pMpi2IOUnitPage3_t;
823
824#define MPI2_IOUNITPAGE3_PAGEVERSION (0x01)
825
826/*defines for IO Unit Page 3 GPIOVal field */
827#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC)
828#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2)
829#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000)
830#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001)
831
832
833/*IO Unit Page 5 */
834
835/*
836 *Upper layer code (drivers, utilities, etc.) should leave this define set to
837 *one and check the value returned for NumDmaEngines at runtime.
838 */
839#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES
840#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1)
841#endif
842
843typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 {
844 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
845 U64
846 RaidAcceleratorBufferBaseAddress; /*0x04 */
847 U64
848 RaidAcceleratorBufferSize; /*0x0C */
849 U64
850 RaidAcceleratorControlBaseAddress; /*0x14 */
851 U8 RAControlSize; /*0x1C */
852 U8 NumDmaEngines; /*0x1D */
853 U8 RAMinControlSize; /*0x1E */
854 U8 RAMaxControlSize; /*0x1F */
855 U32 Reserved1; /*0x20 */
856 U32 Reserved2; /*0x24 */
857 U32 Reserved3; /*0x28 */
858 U32
859 DmaEngineCapabilities[MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /*0x2C */
860} MPI2_CONFIG_PAGE_IO_UNIT_5,
861 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_5,
862 Mpi2IOUnitPage5_t, *pMpi2IOUnitPage5_t;
863
864#define MPI2_IOUNITPAGE5_PAGEVERSION (0x00)
865
866/*defines for IO Unit Page 5 DmaEngineCapabilities field */
867#define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS (0xFF00)
868#define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS (16)
869
870#define MPI2_IOUNITPAGE5_DMA_CAP_EEDP (0x0008)
871#define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION (0x0004)
872#define MPI2_IOUNITPAGE5_DMA_CAP_HASHING (0x0002)
873#define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION (0x0001)
874
875
876/*IO Unit Page 6 */
877
878typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 {
879 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
880 U16 Flags; /*0x04 */
881 U8 RAHostControlSize; /*0x06 */
882 U8 Reserved0; /*0x07 */
883 U64
884 RaidAcceleratorHostControlBaseAddress; /*0x08 */
885 U32 Reserved1; /*0x10 */
886 U32 Reserved2; /*0x14 */
887 U32 Reserved3; /*0x18 */
888} MPI2_CONFIG_PAGE_IO_UNIT_6,
889 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_6,
890 Mpi2IOUnitPage6_t, *pMpi2IOUnitPage6_t;
891
892#define MPI2_IOUNITPAGE6_PAGEVERSION (0x00)
893
894/*defines for IO Unit Page 6 Flags field */
895#define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR (0x0001)
896
897
898/*IO Unit Page 7 */
899
900typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
901 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
902 U8 CurrentPowerMode; /*0x04 */
903 U8 PreviousPowerMode; /*0x05 */
904 U8 PCIeWidth; /*0x06 */
905 U8 PCIeSpeed; /*0x07 */
906 U32 ProcessorState; /*0x08 */
907 U32
908 PowerManagementCapabilities; /*0x0C */
909 U16 IOCTemperature; /*0x10 */
910 U8
911 IOCTemperatureUnits; /*0x12 */
912 U8 IOCSpeed; /*0x13 */
913 U16 BoardTemperature; /*0x14 */
914 U8
915 BoardTemperatureUnits; /*0x16 */
916 U8 Reserved3; /*0x17 */
917} MPI2_CONFIG_PAGE_IO_UNIT_7,
918 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
919 Mpi2IOUnitPage7_t, *pMpi2IOUnitPage7_t;
920
921#define MPI2_IOUNITPAGE7_PAGEVERSION (0x02)
922
923/*defines for IO Unit Page 7 CurrentPowerMode and PreviousPowerMode fields */
924#define MPI25_IOUNITPAGE7_PM_INIT_MASK (0xC0)
925#define MPI25_IOUNITPAGE7_PM_INIT_UNAVAILABLE (0x00)
926#define MPI25_IOUNITPAGE7_PM_INIT_HOST (0x40)
927#define MPI25_IOUNITPAGE7_PM_INIT_IO_UNIT (0x80)
928#define MPI25_IOUNITPAGE7_PM_INIT_PCIE_DPA (0xC0)
929
930#define MPI25_IOUNITPAGE7_PM_MODE_MASK (0x07)
931#define MPI25_IOUNITPAGE7_PM_MODE_UNAVAILABLE (0x00)
932#define MPI25_IOUNITPAGE7_PM_MODE_UNKNOWN (0x01)
933#define MPI25_IOUNITPAGE7_PM_MODE_FULL_POWER (0x04)
934#define MPI25_IOUNITPAGE7_PM_MODE_REDUCED_POWER (0x05)
935#define MPI25_IOUNITPAGE7_PM_MODE_STANDBY (0x06)
936
937
938/*defines for IO Unit Page 7 PCIeWidth field */
939#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01)
940#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2 (0x02)
941#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4 (0x04)
942#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8 (0x08)
943
944/*defines for IO Unit Page 7 PCIeSpeed field */
945#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS (0x00)
946#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01)
947#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02)
948
949/*defines for IO Unit Page 7 ProcessorState field */
950#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F)
951#define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND (0)
952
953#define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT (0x00)
954#define MPI2_IOUNITPAGE7_PSTATE_DISABLED (0x01)
955#define MPI2_IOUNITPAGE7_PSTATE_ENABLED (0x02)
956
957/*defines for IO Unit Page 7 PowerManagementCapabilities field */
958#define MPI25_IOUNITPAGE7_PMCAP_DPA_FULL_PWR_MODE (0x00400000)
959#define MPI25_IOUNITPAGE7_PMCAP_DPA_REDUCED_PWR_MODE (0x00200000)
960#define MPI25_IOUNITPAGE7_PMCAP_DPA_STANDBY_MODE (0x00100000)
961#define MPI25_IOUNITPAGE7_PMCAP_HOST_FULL_PWR_MODE (0x00040000)
962#define MPI25_IOUNITPAGE7_PMCAP_HOST_REDUCED_PWR_MODE (0x00020000)
963#define MPI25_IOUNITPAGE7_PMCAP_HOST_STANDBY_MODE (0x00010000)
964#define MPI25_IOUNITPAGE7_PMCAP_IO_FULL_PWR_MODE (0x00004000)
965#define MPI25_IOUNITPAGE7_PMCAP_IO_REDUCED_PWR_MODE (0x00002000)
966#define MPI25_IOUNITPAGE7_PMCAP_IO_STANDBY_MODE (0x00001000)
967#define MPI2_IOUNITPAGE7_PMCAP_HOST_12_5_PCT_IOCSPEED (0x00000400)
968#define MPI2_IOUNITPAGE7_PMCAP_HOST_25_0_PCT_IOCSPEED (0x00000200)
969#define MPI2_IOUNITPAGE7_PMCAP_HOST_50_0_PCT_IOCSPEED (0x00000100)
970#define MPI25_IOUNITPAGE7_PMCAP_IO_12_5_PCT_IOCSPEED (0x00000040)
971#define MPI25_IOUNITPAGE7_PMCAP_IO_25_0_PCT_IOCSPEED (0x00000020)
972#define MPI25_IOUNITPAGE7_PMCAP_IO_50_0_PCT_IOCSPEED (0x00000010)
973#define MPI2_IOUNITPAGE7_PMCAP_HOST_WIDTH_CHANGE_PCIE (0x00000008)
974#define MPI2_IOUNITPAGE7_PMCAP_HOST_SPEED_CHANGE_PCIE (0x00000004)
975#define MPI25_IOUNITPAGE7_PMCAP_IO_WIDTH_CHANGE_PCIE (0x00000002)
976#define MPI25_IOUNITPAGE7_PMCAP_IO_SPEED_CHANGE_PCIE (0x00000001)
977
978/*obsolete names for the PowerManagementCapabilities bits (above) */
979#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED (0x00000400)
980#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED (0x00000200)
981#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED (0x00000100)
982#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) /*obsolete */
983#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) /*obsolete */
984
985
986/*defines for IO Unit Page 7 IOCTemperatureUnits field */
987#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00)
988#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01)
989#define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS (0x02)
990
991/*defines for IO Unit Page 7 IOCSpeed field */
992#define MPI2_IOUNITPAGE7_IOC_SPEED_FULL (0x01)
993#define MPI2_IOUNITPAGE7_IOC_SPEED_HALF (0x02)
994#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04)
995#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08)
996
997/*defines for IO Unit Page 7 BoardTemperatureUnits field */
998#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00)
999#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01)
1000#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02)
1001
1002
1003/*IO Unit Page 8 */
1004
1005#define MPI2_IOUNIT8_NUM_THRESHOLDS (4)
1006
1007typedef struct _MPI2_IOUNIT8_SENSOR {
1008 U16 Flags; /*0x00 */
1009 U16 Reserved1; /*0x02 */
1010 U16
1011 Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /*0x04 */
1012 U32 Reserved2; /*0x0C */
1013 U32 Reserved3; /*0x10 */
1014 U32 Reserved4; /*0x14 */
1015} MPI2_IOUNIT8_SENSOR, *PTR_MPI2_IOUNIT8_SENSOR,
1016 Mpi2IOUnit8Sensor_t, *pMpi2IOUnit8Sensor_t;
1017
1018/*defines for IO Unit Page 8 Sensor Flags field */
1019#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE (0x0008)
1020#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE (0x0004)
1021#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE (0x0002)
1022#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001)
1023
1024/*
1025 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1026 *one and check the value returned for NumSensors at runtime.
1027 */
1028#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES
1029#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1)
1030#endif
1031
1032typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
1033 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1034 U32 Reserved1; /*0x04 */
1035 U32 Reserved2; /*0x08 */
1036 U8 NumSensors; /*0x0C */
1037 U8 PollingInterval; /*0x0D */
1038 U16 Reserved3; /*0x0E */
1039 MPI2_IOUNIT8_SENSOR
1040 Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/*0x10 */
1041} MPI2_CONFIG_PAGE_IO_UNIT_8,
1042 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_8,
1043 Mpi2IOUnitPage8_t, *pMpi2IOUnitPage8_t;
1044
1045#define MPI2_IOUNITPAGE8_PAGEVERSION (0x00)
1046
1047
1048/*IO Unit Page 9 */
1049
1050typedef struct _MPI2_IOUNIT9_SENSOR {
1051 U16 CurrentTemperature; /*0x00 */
1052 U16 Reserved1; /*0x02 */
1053 U8 Flags; /*0x04 */
1054 U8 Reserved2; /*0x05 */
1055 U16 Reserved3; /*0x06 */
1056 U32 Reserved4; /*0x08 */
1057 U32 Reserved5; /*0x0C */
1058} MPI2_IOUNIT9_SENSOR, *PTR_MPI2_IOUNIT9_SENSOR,
1059 Mpi2IOUnit9Sensor_t, *pMpi2IOUnit9Sensor_t;
1060
1061/*defines for IO Unit Page 9 Sensor Flags field */
1062#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01)
1063
1064/*
1065 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1066 *one and check the value returned for NumSensors at runtime.
1067 */
1068#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES
1069#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1)
1070#endif
1071
1072typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
1073 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1074 U32 Reserved1; /*0x04 */
1075 U32 Reserved2; /*0x08 */
1076 U8 NumSensors; /*0x0C */
1077 U8 Reserved4; /*0x0D */
1078 U16 Reserved3; /*0x0E */
1079 MPI2_IOUNIT9_SENSOR
1080 Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/*0x10 */
1081} MPI2_CONFIG_PAGE_IO_UNIT_9,
1082 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_9,
1083 Mpi2IOUnitPage9_t, *pMpi2IOUnitPage9_t;
1084
1085#define MPI2_IOUNITPAGE9_PAGEVERSION (0x00)
1086
1087
1088/*IO Unit Page 10 */
1089
1090typedef struct _MPI2_IOUNIT10_FUNCTION {
1091 U8 CreditPercent; /*0x00 */
1092 U8 Reserved1; /*0x01 */
1093 U16 Reserved2; /*0x02 */
1094} MPI2_IOUNIT10_FUNCTION,
1095 *PTR_MPI2_IOUNIT10_FUNCTION,
1096 Mpi2IOUnit10Function_t,
1097 *pMpi2IOUnit10Function_t;
1098
1099/*
1100 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1101 *one and check the value returned for NumFunctions at runtime.
1102 */
1103#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES
1104#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1)
1105#endif
1106
1107typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
1108 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1109 U8 NumFunctions; /*0x04 */
1110 U8 Reserved1; /*0x05 */
1111 U16 Reserved2; /*0x06 */
1112 U32 Reserved3; /*0x08 */
1113 U32 Reserved4; /*0x0C */
1114 MPI2_IOUNIT10_FUNCTION
1115 Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/*0x10 */
1116} MPI2_CONFIG_PAGE_IO_UNIT_10,
1117 *PTR_MPI2_CONFIG_PAGE_IO_UNIT_10,
1118 Mpi2IOUnitPage10_t, *pMpi2IOUnitPage10_t;
1119
1120#define MPI2_IOUNITPAGE10_PAGEVERSION (0x01)
1121
1122
1123
1124/****************************************************************************
1125* IOC Config Pages
1126****************************************************************************/
1127
1128/*IOC Page 0 */
1129
1130typedef struct _MPI2_CONFIG_PAGE_IOC_0 {
1131 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1132 U32 Reserved1; /*0x04 */
1133 U32 Reserved2; /*0x08 */
1134 U16 VendorID; /*0x0C */
1135 U16 DeviceID; /*0x0E */
1136 U8 RevisionID; /*0x10 */
1137 U8 Reserved3; /*0x11 */
1138 U16 Reserved4; /*0x12 */
1139 U32 ClassCode; /*0x14 */
1140 U16 SubsystemVendorID; /*0x18 */
1141 U16 SubsystemID; /*0x1A */
1142} MPI2_CONFIG_PAGE_IOC_0,
1143 *PTR_MPI2_CONFIG_PAGE_IOC_0,
1144 Mpi2IOCPage0_t, *pMpi2IOCPage0_t;
1145
1146#define MPI2_IOCPAGE0_PAGEVERSION (0x02)
1147
1148
1149/*IOC Page 1 */
1150
1151typedef struct _MPI2_CONFIG_PAGE_IOC_1 {
1152 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1153 U32 Flags; /*0x04 */
1154 U32 CoalescingTimeout; /*0x08 */
1155 U8 CoalescingDepth; /*0x0C */
1156 U8 PCISlotNum; /*0x0D */
1157 U8 PCIBusNum; /*0x0E */
1158 U8 PCIDomainSegment; /*0x0F */
1159 U32 Reserved1; /*0x10 */
1160 U32 Reserved2; /*0x14 */
1161} MPI2_CONFIG_PAGE_IOC_1,
1162 *PTR_MPI2_CONFIG_PAGE_IOC_1,
1163 Mpi2IOCPage1_t, *pMpi2IOCPage1_t;
1164
1165#define MPI2_IOCPAGE1_PAGEVERSION (0x05)
1166
1167/*defines for IOC Page 1 Flags field */
1168#define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001)
1169
1170#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF)
1171#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF)
1172#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF)
1173
1174/*IOC Page 6 */
1175
1176typedef struct _MPI2_CONFIG_PAGE_IOC_6 {
1177 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1178 U32
1179 CapabilitiesFlags; /*0x04 */
1180 U8 MaxDrivesRAID0; /*0x08 */
1181 U8 MaxDrivesRAID1; /*0x09 */
1182 U8
1183 MaxDrivesRAID1E; /*0x0A */
1184 U8
1185 MaxDrivesRAID10; /*0x0B */
1186 U8 MinDrivesRAID0; /*0x0C */
1187 U8 MinDrivesRAID1; /*0x0D */
1188 U8
1189 MinDrivesRAID1E; /*0x0E */
1190 U8
1191 MinDrivesRAID10; /*0x0F */
1192 U32 Reserved1; /*0x10 */
1193 U8
1194 MaxGlobalHotSpares; /*0x14 */
1195 U8 MaxPhysDisks; /*0x15 */
1196 U8 MaxVolumes; /*0x16 */
1197 U8 MaxConfigs; /*0x17 */
1198 U8 MaxOCEDisks; /*0x18 */
1199 U8 Reserved2; /*0x19 */
1200 U16 Reserved3; /*0x1A */
1201 U32
1202 SupportedStripeSizeMapRAID0; /*0x1C */
1203 U32
1204 SupportedStripeSizeMapRAID1E; /*0x20 */
1205 U32
1206 SupportedStripeSizeMapRAID10; /*0x24 */
1207 U32 Reserved4; /*0x28 */
1208 U32 Reserved5; /*0x2C */
1209 U16
1210 DefaultMetadataSize; /*0x30 */
1211 U16 Reserved6; /*0x32 */
1212 U16
1213 MaxBadBlockTableEntries; /*0x34 */
1214 U16 Reserved7; /*0x36 */
1215 U32
1216 IRNvsramVersion; /*0x38 */
1217} MPI2_CONFIG_PAGE_IOC_6,
1218 *PTR_MPI2_CONFIG_PAGE_IOC_6,
1219 Mpi2IOCPage6_t, *pMpi2IOCPage6_t;
1220
1221#define MPI2_IOCPAGE6_PAGEVERSION (0x05)
1222
1223/*defines for IOC Page 6 CapabilitiesFlags */
1224#define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT (0x00000020)
1225#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010)
1226#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008)
1227#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004)
1228#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002)
1229#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001)
1230
1231
1232/*IOC Page 7 */
1233
1234#define MPI2_IOCPAGE7_EVENTMASK_WORDS (4)
1235
1236typedef struct _MPI2_CONFIG_PAGE_IOC_7 {
1237 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1238 U32 Reserved1; /*0x04 */
1239 U32
1240 EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/*0x08 */
1241 U16 SASBroadcastPrimitiveMasks; /*0x18 */
1242 U16 SASNotifyPrimitiveMasks; /*0x1A */
1243 U32 Reserved3; /*0x1C */
1244} MPI2_CONFIG_PAGE_IOC_7,
1245 *PTR_MPI2_CONFIG_PAGE_IOC_7,
1246 Mpi2IOCPage7_t, *pMpi2IOCPage7_t;
1247
1248#define MPI2_IOCPAGE7_PAGEVERSION (0x02)
1249
1250
1251/*IOC Page 8 */
1252
1253typedef struct _MPI2_CONFIG_PAGE_IOC_8 {
1254 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1255 U8 NumDevsPerEnclosure; /*0x04 */
1256 U8 Reserved1; /*0x05 */
1257 U16 Reserved2; /*0x06 */
1258 U16 MaxPersistentEntries; /*0x08 */
1259 U16 MaxNumPhysicalMappedIDs; /*0x0A */
1260 U16 Flags; /*0x0C */
1261 U16 Reserved3; /*0x0E */
1262 U16 IRVolumeMappingFlags; /*0x10 */
1263 U16 Reserved4; /*0x12 */
1264 U32 Reserved5; /*0x14 */
1265} MPI2_CONFIG_PAGE_IOC_8,
1266 *PTR_MPI2_CONFIG_PAGE_IOC_8,
1267 Mpi2IOCPage8_t, *pMpi2IOCPage8_t;
1268
1269#define MPI2_IOCPAGE8_PAGEVERSION (0x00)
1270
1271/*defines for IOC Page 8 Flags field */
1272#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020)
1273#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010)
1274
1275#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E)
1276#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000)
1277#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002)
1278
1279#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001)
1280#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000)
1281
1282/*defines for IOC Page 8 IRVolumeMappingFlags */
1283#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003)
1284#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000)
1285#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001)
1286
1287
1288/****************************************************************************
1289* BIOS Config Pages
1290****************************************************************************/
1291
1292/*BIOS Page 1 */
1293
1294typedef struct _MPI2_CONFIG_PAGE_BIOS_1 {
1295 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1296 U32 BiosOptions; /*0x04 */
1297 U32 IOCSettings; /*0x08 */
1298 U32 Reserved1; /*0x0C */
1299 U32 DeviceSettings; /*0x10 */
1300 U16 NumberOfDevices; /*0x14 */
1301 U16 UEFIVersion; /*0x16 */
1302 U16 IOTimeoutBlockDevicesNonRM; /*0x18 */
1303 U16 IOTimeoutSequential; /*0x1A */
1304 U16 IOTimeoutOther; /*0x1C */
1305 U16 IOTimeoutBlockDevicesRM; /*0x1E */
1306} MPI2_CONFIG_PAGE_BIOS_1,
1307 *PTR_MPI2_CONFIG_PAGE_BIOS_1,
1308 Mpi2BiosPage1_t, *pMpi2BiosPage1_t;
1309
1310#define MPI2_BIOSPAGE1_PAGEVERSION (0x05)
1311
1312/*values for BIOS Page 1 BiosOptions field */
1313#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006)
1314#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000)
1315#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002)
1316#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII (0x00000004)
1317
1318#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
1319
1320/*values for BIOS Page 1 IOCSettings field */
1321#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
1322#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
1323#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
1324
1325#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0)
1326#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000)
1327#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040)
1328#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080)
1329
1330#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030)
1331#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000)
1332#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010)
1333#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020)
1334#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030)
1335
1336#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008)
1337
1338/*values for BIOS Page 1 DeviceSettings field */
1339#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010)
1340#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008)
1341#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004)
1342#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
1343#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
1344
1345/*defines for BIOS Page 1 UEFIVersion field */
1346#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_MASK (0xFF00)
1347#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_SHIFT (8)
1348#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_MASK (0x00FF)
1349#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_SHIFT (0)
1350
1351
1352
1353/*BIOS Page 2 */
1354
1355typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER {
1356 U32 Reserved1; /*0x00 */
1357 U32 Reserved2; /*0x04 */
1358 U32 Reserved3; /*0x08 */
1359 U32 Reserved4; /*0x0C */
1360 U32 Reserved5; /*0x10 */
1361 U32 Reserved6; /*0x14 */
1362} MPI2_BOOT_DEVICE_ADAPTER_ORDER,
1363 *PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER,
1364 Mpi2BootDeviceAdapterOrder_t,
1365 *pMpi2BootDeviceAdapterOrder_t;
1366
1367typedef struct _MPI2_BOOT_DEVICE_SAS_WWID {
1368 U64 SASAddress; /*0x00 */
1369 U8 LUN[8]; /*0x08 */
1370 U32 Reserved1; /*0x10 */
1371 U32 Reserved2; /*0x14 */
1372} MPI2_BOOT_DEVICE_SAS_WWID,
1373 *PTR_MPI2_BOOT_DEVICE_SAS_WWID,
1374 Mpi2BootDeviceSasWwid_t,
1375 *pMpi2BootDeviceSasWwid_t;
1376
1377typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT {
1378 U64 EnclosureLogicalID; /*0x00 */
1379 U32 Reserved1; /*0x08 */
1380 U32 Reserved2; /*0x0C */
1381 U16 SlotNumber; /*0x10 */
1382 U16 Reserved3; /*0x12 */
1383 U32 Reserved4; /*0x14 */
1384} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
1385 *PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
1386 Mpi2BootDeviceEnclosureSlot_t,
1387 *pMpi2BootDeviceEnclosureSlot_t;
1388
1389typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME {
1390 U64 DeviceName; /*0x00 */
1391 U8 LUN[8]; /*0x08 */
1392 U32 Reserved1; /*0x10 */
1393 U32 Reserved2; /*0x14 */
1394} MPI2_BOOT_DEVICE_DEVICE_NAME,
1395 *PTR_MPI2_BOOT_DEVICE_DEVICE_NAME,
1396 Mpi2BootDeviceDeviceName_t,
1397 *pMpi2BootDeviceDeviceName_t;
1398
1399typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE {
1400 MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder;
1401 MPI2_BOOT_DEVICE_SAS_WWID SasWwid;
1402 MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot;
1403 MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName;
1404} MPI2_BIOSPAGE2_BOOT_DEVICE,
1405 *PTR_MPI2_BIOSPAGE2_BOOT_DEVICE,
1406 Mpi2BiosPage2BootDevice_t,
1407 *pMpi2BiosPage2BootDevice_t;
1408
1409typedef struct _MPI2_CONFIG_PAGE_BIOS_2 {
1410 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1411 U32 Reserved1; /*0x04 */
1412 U32 Reserved2; /*0x08 */
1413 U32 Reserved3; /*0x0C */
1414 U32 Reserved4; /*0x10 */
1415 U32 Reserved5; /*0x14 */
1416 U32 Reserved6; /*0x18 */
1417 U8 ReqBootDeviceForm; /*0x1C */
1418 U8 Reserved7; /*0x1D */
1419 U16 Reserved8; /*0x1E */
1420 MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /*0x20 */
1421 U8 ReqAltBootDeviceForm; /*0x38 */
1422 U8 Reserved9; /*0x39 */
1423 U16 Reserved10; /*0x3A */
1424 MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /*0x3C */
1425 U8 CurrentBootDeviceForm; /*0x58 */
1426 U8 Reserved11; /*0x59 */
1427 U16 Reserved12; /*0x5A */
1428 MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /*0x58 */
1429} MPI2_CONFIG_PAGE_BIOS_2, *PTR_MPI2_CONFIG_PAGE_BIOS_2,
1430 Mpi2BiosPage2_t, *pMpi2BiosPage2_t;
1431
1432#define MPI2_BIOSPAGE2_PAGEVERSION (0x04)
1433
1434/*values for BIOS Page 2 BootDeviceForm fields */
1435#define MPI2_BIOSPAGE2_FORM_MASK (0x0F)
1436#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00)
1437#define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05)
1438#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06)
1439#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07)
1440
1441
1442/*BIOS Page 3 */
1443
1444typedef struct _MPI2_ADAPTER_INFO {
1445 U8 PciBusNumber; /*0x00 */
1446 U8 PciDeviceAndFunctionNumber; /*0x01 */
1447 U16 AdapterFlags; /*0x02 */
1448} MPI2_ADAPTER_INFO, *PTR_MPI2_ADAPTER_INFO,
1449 Mpi2AdapterInfo_t, *pMpi2AdapterInfo_t;
1450
1451#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001)
1452#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002)
1453
1454typedef struct _MPI2_CONFIG_PAGE_BIOS_3 {
1455 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1456 U32 GlobalFlags; /*0x04 */
1457 U32 BiosVersion; /*0x08 */
1458 MPI2_ADAPTER_INFO AdapterOrder[4]; /*0x0C */
1459 U32 Reserved1; /*0x1C */
1460} MPI2_CONFIG_PAGE_BIOS_3,
1461 *PTR_MPI2_CONFIG_PAGE_BIOS_3,
1462 Mpi2BiosPage3_t, *pMpi2BiosPage3_t;
1463
1464#define MPI2_BIOSPAGE3_PAGEVERSION (0x00)
1465
1466/*values for BIOS Page 3 GlobalFlags */
1467#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002)
1468#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004)
1469#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010)
1470
1471#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0)
1472#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000)
1473#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020)
1474#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040)
1475
1476
1477/*BIOS Page 4 */
1478
1479/*
1480 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1481 *one and check the value returned for NumPhys at runtime.
1482 */
1483#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
1484#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1)
1485#endif
1486
1487typedef struct _MPI2_BIOS4_ENTRY {
1488 U64 ReassignmentWWID; /*0x00 */
1489 U64 ReassignmentDeviceName; /*0x08 */
1490} MPI2_BIOS4_ENTRY, *PTR_MPI2_BIOS4_ENTRY,
1491 Mpi2MBios4Entry_t, *pMpi2Bios4Entry_t;
1492
1493typedef struct _MPI2_CONFIG_PAGE_BIOS_4 {
1494 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1495 U8 NumPhys; /*0x04 */
1496 U8 Reserved1; /*0x05 */
1497 U16 Reserved2; /*0x06 */
1498 MPI2_BIOS4_ENTRY
1499 Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /*0x08 */
1500} MPI2_CONFIG_PAGE_BIOS_4, *PTR_MPI2_CONFIG_PAGE_BIOS_4,
1501 Mpi2BiosPage4_t, *pMpi2BiosPage4_t;
1502
1503#define MPI2_BIOSPAGE4_PAGEVERSION (0x01)
1504
1505
1506/****************************************************************************
1507* RAID Volume Config Pages
1508****************************************************************************/
1509
1510/*RAID Volume Page 0 */
1511
1512typedef struct _MPI2_RAIDVOL0_PHYS_DISK {
1513 U8 RAIDSetNum; /*0x00 */
1514 U8 PhysDiskMap; /*0x01 */
1515 U8 PhysDiskNum; /*0x02 */
1516 U8 Reserved; /*0x03 */
1517} MPI2_RAIDVOL0_PHYS_DISK, *PTR_MPI2_RAIDVOL0_PHYS_DISK,
1518 Mpi2RaidVol0PhysDisk_t, *pMpi2RaidVol0PhysDisk_t;
1519
1520/*defines for the PhysDiskMap field */
1521#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01)
1522#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02)
1523
1524typedef struct _MPI2_RAIDVOL0_SETTINGS {
1525 U16 Settings; /*0x00 */
1526 U8 HotSparePool; /*0x01 */
1527 U8 Reserved; /*0x02 */
1528} MPI2_RAIDVOL0_SETTINGS, *PTR_MPI2_RAIDVOL0_SETTINGS,
1529 Mpi2RaidVol0Settings_t,
1530 *pMpi2RaidVol0Settings_t;
1531
1532/*RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */
1533#define MPI2_RAID_HOT_SPARE_POOL_0 (0x01)
1534#define MPI2_RAID_HOT_SPARE_POOL_1 (0x02)
1535#define MPI2_RAID_HOT_SPARE_POOL_2 (0x04)
1536#define MPI2_RAID_HOT_SPARE_POOL_3 (0x08)
1537#define MPI2_RAID_HOT_SPARE_POOL_4 (0x10)
1538#define MPI2_RAID_HOT_SPARE_POOL_5 (0x20)
1539#define MPI2_RAID_HOT_SPARE_POOL_6 (0x40)
1540#define MPI2_RAID_HOT_SPARE_POOL_7 (0x80)
1541
1542/*RAID Volume Page 0 VolumeSettings defines */
1543#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008)
1544#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004)
1545
1546#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003)
1547#define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000)
1548#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001)
1549#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002)
1550
1551/*
1552 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1553 *one and check the value returned for NumPhysDisks at runtime.
1554 */
1555#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
1556#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1)
1557#endif
1558
1559typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 {
1560 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1561 U16 DevHandle; /*0x04 */
1562 U8 VolumeState; /*0x06 */
1563 U8 VolumeType; /*0x07 */
1564 U32 VolumeStatusFlags; /*0x08 */
1565 MPI2_RAIDVOL0_SETTINGS VolumeSettings; /*0x0C */
1566 U64 MaxLBA; /*0x10 */
1567 U32 StripeSize; /*0x18 */
1568 U16 BlockSize; /*0x1C */
1569 U16 Reserved1; /*0x1E */
1570 U8 SupportedPhysDisks;/*0x20 */
1571 U8 ResyncRate; /*0x21 */
1572 U16 DataScrubDuration; /*0x22 */
1573 U8 NumPhysDisks; /*0x24 */
1574 U8 Reserved2; /*0x25 */
1575 U8 Reserved3; /*0x26 */
1576 U8 InactiveStatus; /*0x27 */
1577 MPI2_RAIDVOL0_PHYS_DISK
1578 PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /*0x28 */
1579} MPI2_CONFIG_PAGE_RAID_VOL_0,
1580 *PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
1581 Mpi2RaidVolPage0_t, *pMpi2RaidVolPage0_t;
1582
1583#define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A)
1584
1585/*values for RAID VolumeState */
1586#define MPI2_RAID_VOL_STATE_MISSING (0x00)
1587#define MPI2_RAID_VOL_STATE_FAILED (0x01)
1588#define MPI2_RAID_VOL_STATE_INITIALIZING (0x02)
1589#define MPI2_RAID_VOL_STATE_ONLINE (0x03)
1590#define MPI2_RAID_VOL_STATE_DEGRADED (0x04)
1591#define MPI2_RAID_VOL_STATE_OPTIMAL (0x05)
1592
1593/*values for RAID VolumeType */
1594#define MPI2_RAID_VOL_TYPE_RAID0 (0x00)
1595#define MPI2_RAID_VOL_TYPE_RAID1E (0x01)
1596#define MPI2_RAID_VOL_TYPE_RAID1 (0x02)
1597#define MPI2_RAID_VOL_TYPE_RAID10 (0x05)
1598#define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF)
1599
1600/*values for RAID Volume Page 0 VolumeStatusFlags field */
1601#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000)
1602#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000)
1603#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000)
1604#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000)
1605#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000)
1606#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000)
1607#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000)
1608#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000)
1609#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000)
1610#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000)
1611#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT (0x00000080)
1612#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040)
1613#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020)
1614#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000)
1615#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010)
1616#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008)
1617#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004)
1618#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002)
1619#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001)
1620
1621/*values for RAID Volume Page 0 SupportedPhysDisks field */
1622#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08)
1623#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04)
1624#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02)
1625#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01)
1626
1627/*values for RAID Volume Page 0 InactiveStatus field */
1628#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
1629#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01)
1630#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02)
1631#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03)
1632#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04)
1633#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05)
1634#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06)
1635
1636
1637/*RAID Volume Page 1 */
1638
1639typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1 {
1640 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1641 U16 DevHandle; /*0x04 */
1642 U16 Reserved0; /*0x06 */
1643 U8 GUID[24]; /*0x08 */
1644 U8 Name[16]; /*0x20 */
1645 U64 WWID; /*0x30 */
1646 U32 Reserved1; /*0x38 */
1647 U32 Reserved2; /*0x3C */
1648} MPI2_CONFIG_PAGE_RAID_VOL_1,
1649 *PTR_MPI2_CONFIG_PAGE_RAID_VOL_1,
1650 Mpi2RaidVolPage1_t, *pMpi2RaidVolPage1_t;
1651
1652#define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03)
1653
1654
1655/****************************************************************************
1656* RAID Physical Disk Config Pages
1657****************************************************************************/
1658
1659/*RAID Physical Disk Page 0 */
1660
1661typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS {
1662 U16 Reserved1; /*0x00 */
1663 U8 HotSparePool; /*0x02 */
1664 U8 Reserved2; /*0x03 */
1665} MPI2_RAIDPHYSDISK0_SETTINGS,
1666 *PTR_MPI2_RAIDPHYSDISK0_SETTINGS,
1667 Mpi2RaidPhysDisk0Settings_t,
1668 *pMpi2RaidPhysDisk0Settings_t;
1669
1670/*use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */
1671
1672typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA {
1673 U8 VendorID[8]; /*0x00 */
1674 U8 ProductID[16]; /*0x08 */
1675 U8 ProductRevLevel[4]; /*0x18 */
1676 U8 SerialNum[32]; /*0x1C */
1677} MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
1678 *PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
1679 Mpi2RaidPhysDisk0InquiryData_t,
1680 *pMpi2RaidPhysDisk0InquiryData_t;
1681
1682typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 {
1683 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1684 U16 DevHandle; /*0x04 */
1685 U8 Reserved1; /*0x06 */
1686 U8 PhysDiskNum; /*0x07 */
1687 MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /*0x08 */
1688 U32 Reserved2; /*0x0C */
1689 MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /*0x10 */
1690 U32 Reserved3; /*0x4C */
1691 U8 PhysDiskState; /*0x50 */
1692 U8 OfflineReason; /*0x51 */
1693 U8 IncompatibleReason; /*0x52 */
1694 U8 PhysDiskAttributes; /*0x53 */
1695 U32 PhysDiskStatusFlags;/*0x54 */
1696 U64 DeviceMaxLBA; /*0x58 */
1697 U64 HostMaxLBA; /*0x60 */
1698 U64 CoercedMaxLBA; /*0x68 */
1699 U16 BlockSize; /*0x70 */
1700 U16 Reserved5; /*0x72 */
1701 U32 Reserved6; /*0x74 */
1702} MPI2_CONFIG_PAGE_RD_PDISK_0,
1703 *PTR_MPI2_CONFIG_PAGE_RD_PDISK_0,
1704 Mpi2RaidPhysDiskPage0_t,
1705 *pMpi2RaidPhysDiskPage0_t;
1706
1707#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05)
1708
1709/*PhysDiskState defines */
1710#define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00)
1711#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01)
1712#define MPI2_RAID_PD_STATE_OFFLINE (0x02)
1713#define MPI2_RAID_PD_STATE_ONLINE (0x03)
1714#define MPI2_RAID_PD_STATE_HOT_SPARE (0x04)
1715#define MPI2_RAID_PD_STATE_DEGRADED (0x05)
1716#define MPI2_RAID_PD_STATE_REBUILDING (0x06)
1717#define MPI2_RAID_PD_STATE_OPTIMAL (0x07)
1718
1719/*OfflineReason defines */
1720#define MPI2_PHYSDISK0_ONLINE (0x00)
1721#define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01)
1722#define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03)
1723#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04)
1724#define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05)
1725#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06)
1726#define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF)
1727
1728/*IncompatibleReason defines */
1729#define MPI2_PHYSDISK0_COMPATIBLE (0x00)
1730#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01)
1731#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02)
1732#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03)
1733#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04)
1734#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05)
1735#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE (0x06)
1736#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF)
1737
1738/*PhysDiskAttributes defines */
1739#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK (0x0C)
1740#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08)
1741#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04)
1742
1743#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK (0x03)
1744#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02)
1745#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01)
1746
1747/*PhysDiskStatusFlags defines */
1748#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040)
1749#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020)
1750#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010)
1751#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000)
1752#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008)
1753#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004)
1754#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002)
1755#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001)
1756
1757
1758/*RAID Physical Disk Page 1 */
1759
1760/*
1761 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1762 *one and check the value returned for NumPhysDiskPaths at runtime.
1763 */
1764#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
1765#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1)
1766#endif
1767
1768typedef struct _MPI2_RAIDPHYSDISK1_PATH {
1769 U16 DevHandle; /*0x00 */
1770 U16 Reserved1; /*0x02 */
1771 U64 WWID; /*0x04 */
1772 U64 OwnerWWID; /*0x0C */
1773 U8 OwnerIdentifier; /*0x14 */
1774 U8 Reserved2; /*0x15 */
1775 U16 Flags; /*0x16 */
1776} MPI2_RAIDPHYSDISK1_PATH, *PTR_MPI2_RAIDPHYSDISK1_PATH,
1777 Mpi2RaidPhysDisk1Path_t,
1778 *pMpi2RaidPhysDisk1Path_t;
1779
1780/*RAID Physical Disk Page 1 Physical Disk Path Flags field defines */
1781#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004)
1782#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002)
1783#define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001)
1784
1785typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 {
1786 MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
1787 U8 NumPhysDiskPaths; /*0x04 */
1788 U8 PhysDiskNum; /*0x05 */
1789 U16 Reserved1; /*0x06 */
1790 U32 Reserved2; /*0x08 */
1791 MPI2_RAIDPHYSDISK1_PATH
1792 PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/*0x0C */
1793} MPI2_CONFIG_PAGE_RD_PDISK_1,
1794 *PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
1795 Mpi2RaidPhysDiskPage1_t,
1796 *pMpi2RaidPhysDiskPage1_t;
1797
1798#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02)
1799
1800
1801/****************************************************************************
1802* values for fields used by several types of SAS Config Pages
1803****************************************************************************/
1804
1805/*values for NegotiatedLinkRates fields */
1806#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0)
1807#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4)
1808#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F)
1809/*link rates used for Negotiated Physical and Logical Link Rate */
1810#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00)
1811#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01)
1812#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02)
1813#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03)
1814#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04)
1815#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05)
1816#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06)
1817#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08)
1818#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09)
1819#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A)
1820#define MPI25_SAS_NEG_LINK_RATE_12_0 (0x0B)
1821
1822
1823/*values for AttachedPhyInfo fields */
1824#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040)
1825#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020)
1826#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010)
1827
1828#define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F)
1829#define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000)
1830#define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001)
1831#define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002)
1832#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003)
1833#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004)
1834#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005)
1835#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006)
1836#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007)
1837#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008)
1838
1839
1840/*values for PhyInfo fields */
1841#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000)
1842
1843#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000)
1844#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION (27)
1845#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE (0x00000000)
1846#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL (0x08000000)
1847#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER (0x10000000)
1848
1849#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000)
1850#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000)
1851#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000)
1852#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000)
1853#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000)
1854#define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000)
1855
1856#define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000)
1857#define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000)
1858#define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000)
1859#define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000)
1860#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000)
1861#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000)
1862#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000)
1863#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000)
1864#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000)
1865#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000)
1866
1867#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000)
1868#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000)
1869#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000)
1870#define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000)
1871
1872#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00)
1873#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8)
1874
1875#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0)
1876#define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000)
1877#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010)
1878#define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020)
1879
1880
1881/*values for SAS ProgrammedLinkRate fields */
1882#define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0)
1883#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00)
1884#define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80)
1885#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90)
1886#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0)
1887#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F)
1888#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00)
1889#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08)
1890#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09)
1891#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A)
1892#define MPI25_SAS_PRATE_MIN_RATE_12_0 (0x0B)
1893
1894
1895/*values for SAS HwLinkRate fields */
1896#define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0)
1897#define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80)
1898#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90)
1899#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0)
1900#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F)
1901#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08)
1902#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09)
1903#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A)
1904#define MPI25_SAS_HWRATE_MIN_RATE_12_0 (0x0B)
1905
1906
1907
1908/****************************************************************************
1909* SAS IO Unit Config Pages
1910****************************************************************************/
1911
1912/*SAS IO Unit Page 0 */
1913
1914typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA {
1915 U8 Port; /*0x00 */
1916 U8 PortFlags; /*0x01 */
1917 U8 PhyFlags; /*0x02 */
1918 U8 NegotiatedLinkRate; /*0x03 */
1919 U32 ControllerPhyDeviceInfo;/*0x04 */
1920 U16 AttachedDevHandle; /*0x08 */
1921 U16 ControllerDevHandle; /*0x0A */
1922 U32 DiscoveryStatus; /*0x0C */
1923 U32 Reserved; /*0x10 */
1924} MPI2_SAS_IO_UNIT0_PHY_DATA,
1925 *PTR_MPI2_SAS_IO_UNIT0_PHY_DATA,
1926 Mpi2SasIOUnit0PhyData_t,
1927 *pMpi2SasIOUnit0PhyData_t;
1928
1929/*
1930 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1931 *one and check the value returned for NumPhys at runtime.
1932 */
1933#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
1934#define MPI2_SAS_IOUNIT0_PHY_MAX (1)
1935#endif
1936
1937typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 {
1938 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
1939 U32 Reserved1;/*0x08 */
1940 U8 NumPhys; /*0x0C */
1941 U8 Reserved2;/*0x0D */
1942 U16 Reserved3;/*0x0E */
1943 MPI2_SAS_IO_UNIT0_PHY_DATA
1944 PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /*0x10 */
1945} MPI2_CONFIG_PAGE_SASIOUNIT_0,
1946 *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
1947 Mpi2SasIOUnitPage0_t, *pMpi2SasIOUnitPage0_t;
1948
1949#define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05)
1950
1951/*values for SAS IO Unit Page 0 PortFlags */
1952#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08)
1953#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01)
1954
1955/*values for SAS IO Unit Page 0 PhyFlags */
1956#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10)
1957#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08)
1958
1959/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
1960
1961/*see mpi2_sas.h for values for
1962 *SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
1963
1964/*values for SAS IO Unit Page 0 DiscoveryStatus */
1965#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
1966#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000)
1967#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000)
1968#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
1969#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000)
1970#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
1971#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
1972#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000)
1973#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
1974#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800)
1975#define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400)
1976#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200)
1977#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100)
1978#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080)
1979#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040)
1980#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020)
1981#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010)
1982#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004)
1983#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002)
1984#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001)
1985
1986
1987/*SAS IO Unit Page 1 */
1988
1989typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA {
1990 U8 Port; /*0x00 */
1991 U8 PortFlags; /*0x01 */
1992 U8 PhyFlags; /*0x02 */
1993 U8 MaxMinLinkRate; /*0x03 */
1994 U32 ControllerPhyDeviceInfo; /*0x04 */
1995 U16 MaxTargetPortConnectTime; /*0x08 */
1996 U16 Reserved1; /*0x0A */
1997} MPI2_SAS_IO_UNIT1_PHY_DATA,
1998 *PTR_MPI2_SAS_IO_UNIT1_PHY_DATA,
1999 Mpi2SasIOUnit1PhyData_t,
2000 *pMpi2SasIOUnit1PhyData_t;
2001
2002/*
2003 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2004 *one and check the value returned for NumPhys at runtime.
2005 */
2006#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
2007#define MPI2_SAS_IOUNIT1_PHY_MAX (1)
2008#endif
2009
2010typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
2011 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
2012 U16
2013 ControlFlags; /*0x08 */
2014 U16
2015 SASNarrowMaxQueueDepth; /*0x0A */
2016 U16
2017 AdditionalControlFlags; /*0x0C */
2018 U16
2019 SASWideMaxQueueDepth; /*0x0E */
2020 U8
2021 NumPhys; /*0x10 */
2022 U8
2023 SATAMaxQDepth; /*0x11 */
2024 U8
2025 ReportDeviceMissingDelay; /*0x12 */
2026 U8
2027 IODeviceMissingDelay; /*0x13 */
2028 MPI2_SAS_IO_UNIT1_PHY_DATA
2029 PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /*0x14 */
2030} MPI2_CONFIG_PAGE_SASIOUNIT_1,
2031 *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
2032 Mpi2SasIOUnitPage1_t, *pMpi2SasIOUnitPage1_t;
2033
2034#define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09)
2035
2036/*values for SAS IO Unit Page 1 ControlFlags */
2037#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
2038#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
2039#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
2040#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
2041
2042#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
2043#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
2044#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0)
2045#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1)
2046#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2)
2047
2048#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
2049#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
2050#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
2051#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
2052#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008)
2053#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
2054#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
2055#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
2056
2057/*values for SAS IO Unit Page 1 AdditionalControlFlags */
2058#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080)
2059#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040)
2060#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020)
2061#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010)
2062#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008)
2063#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004)
2064#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002)
2065#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001)
2066
2067/*defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
2068#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F)
2069#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80)
2070
2071/*values for SAS IO Unit Page 1 PortFlags */
2072#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
2073
2074/*values for SAS IO Unit Page 1 PhyFlags */
2075#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10)
2076#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08)
2077
2078/*values for SAS IO Unit Page 1 MaxMinLinkRate */
2079#define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0)
2080#define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80)
2081#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90)
2082#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0)
2083#define MPI25_SASIOUNIT1_MAX_RATE_12_0 (0xB0)
2084#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F)
2085#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08)
2086#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09)
2087#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A)
2088#define MPI25_SASIOUNIT1_MIN_RATE_12_0 (0x0B)
2089
2090/*see mpi2_sas.h for values for
2091 *SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
2092
2093
2094/*SAS IO Unit Page 4 */
2095
2096typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP {
2097 U8 MaxTargetSpinup; /*0x00 */
2098 U8 SpinupDelay; /*0x01 */
2099 U8 SpinupFlags; /*0x02 */
2100 U8 Reserved1; /*0x03 */
2101} MPI2_SAS_IOUNIT4_SPINUP_GROUP,
2102 *PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP,
2103 Mpi2SasIOUnit4SpinupGroup_t,
2104 *pMpi2SasIOUnit4SpinupGroup_t;
2105/*defines for SAS IO Unit Page 4 SpinupFlags */
2106#define MPI2_SASIOUNIT4_SPINUP_DISABLE_FLAG (0x01)
2107
2108
2109/*
2110 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2111 *one and check the value returned for NumPhys at runtime.
2112 */
2113#ifndef MPI2_SAS_IOUNIT4_PHY_MAX
2114#define MPI2_SAS_IOUNIT4_PHY_MAX (4)
2115#endif
2116
2117typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 {
2118 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header;/*0x00 */
2119 MPI2_SAS_IOUNIT4_SPINUP_GROUP
2120 SpinupGroupParameters[4]; /*0x08 */
2121 U32
2122 Reserved1; /*0x18 */
2123 U32
2124 Reserved2; /*0x1C */
2125 U32
2126 Reserved3; /*0x20 */
2127 U8
2128 BootDeviceWaitTime; /*0x24 */
2129 U8
2130 Reserved4; /*0x25 */
2131 U16
2132 Reserved5; /*0x26 */
2133 U8
2134 NumPhys; /*0x28 */
2135 U8
2136 PEInitialSpinupDelay; /*0x29 */
2137 U8
2138 PEReplyDelay; /*0x2A */
2139 U8
2140 Flags; /*0x2B */
2141 U8
2142 PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /*0x2C */
2143} MPI2_CONFIG_PAGE_SASIOUNIT_4,
2144 *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4,
2145 Mpi2SasIOUnitPage4_t, *pMpi2SasIOUnitPage4_t;
2146
2147#define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02)
2148
2149/*defines for Flags field */
2150#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01)
2151
2152/*defines for PHY field */
2153#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03)
2154
2155
2156/*SAS IO Unit Page 5 */
2157
2158typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS {
2159 U8 ControlFlags; /*0x00 */
2160 U8 PortWidthModGroup; /*0x01 */
2161 U16 InactivityTimerExponent; /*0x02 */
2162 U8 SATAPartialTimeout; /*0x04 */
2163 U8 Reserved2; /*0x05 */
2164 U8 SATASlumberTimeout; /*0x06 */
2165 U8 Reserved3; /*0x07 */
2166 U8 SASPartialTimeout; /*0x08 */
2167 U8 Reserved4; /*0x09 */
2168 U8 SASSlumberTimeout; /*0x0A */
2169 U8 Reserved5; /*0x0B */
2170} MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
2171 *PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
2172 Mpi2SasIOUnit5PhyPmSettings_t,
2173 *pMpi2SasIOUnit5PhyPmSettings_t;
2174
2175/*defines for ControlFlags field */
2176#define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE (0x08)
2177#define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE (0x04)
2178#define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE (0x02)
2179#define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE (0x01)
2180
2181/*defines for PortWidthModeGroup field */
2182#define MPI2_SASIOUNIT5_PWMG_DISABLE (0xFF)
2183
2184/*defines for InactivityTimerExponent field */
2185#define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER (0x7000)
2186#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER (12)
2187#define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL (0x0700)
2188#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL (8)
2189#define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER (0x0070)
2190#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER (4)
2191#define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL (0x0007)
2192#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL (0)
2193
2194#define MPI2_SASIOUNIT5_ITE_TEN_SECONDS (7)
2195#define MPI2_SASIOUNIT5_ITE_ONE_SECOND (6)
2196#define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS (5)
2197#define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS (4)
2198#define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND (3)
2199#define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS (2)
2200#define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS (1)
2201#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND (0)
2202
2203/*
2204 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2205 *one and check the value returned for NumPhys at runtime.
2206 */
2207#ifndef MPI2_SAS_IOUNIT5_PHY_MAX
2208#define MPI2_SAS_IOUNIT5_PHY_MAX (1)
2209#endif
2210
2211typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 {
2212 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
2213 U8 NumPhys; /*0x08 */
2214 U8 Reserved1;/*0x09 */
2215 U16 Reserved2;/*0x0A */
2216 U32 Reserved3;/*0x0C */
2217 MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS
2218 SASPhyPowerManagementSettings[MPI2_SAS_IOUNIT5_PHY_MAX];/*0x10 */
2219} MPI2_CONFIG_PAGE_SASIOUNIT_5,
2220 *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5,
2221 Mpi2SasIOUnitPage5_t, *pMpi2SasIOUnitPage5_t;
2222
2223#define MPI2_SASIOUNITPAGE5_PAGEVERSION (0x01)
2224
2225
2226/*SAS IO Unit Page 6 */
2227
2228typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS {
2229 U8 CurrentStatus; /*0x00 */
2230 U8 CurrentModulation; /*0x01 */
2231 U8 CurrentUtilization; /*0x02 */
2232 U8 Reserved1; /*0x03 */
2233 U32 Reserved2; /*0x04 */
2234} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
2235 *PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
2236 Mpi2SasIOUnit6PortWidthModGroupStatus_t,
2237 *pMpi2SasIOUnit6PortWidthModGroupStatus_t;
2238
2239/*defines for CurrentStatus field */
2240#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE (0x00)
2241#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED (0x01)
2242#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG (0x02)
2243#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN (0x03)
2244#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY (0x04)
2245#define MPI2_SASIOUNIT6_STATUS_INACTIVE (0x05)
2246#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT (0x06)
2247#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST (0x07)
2248
2249/*defines for CurrentModulation field */
2250#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT (0x00)
2251#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT (0x01)
2252#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT (0x02)
2253#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03)
2254
2255/*
2256 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2257 *one and check the value returned for NumGroups at runtime.
2258 */
2259#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX
2260#define MPI2_SAS_IOUNIT6_GROUP_MAX (1)
2261#endif
2262
2263typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 {
2264 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
2265 U32 Reserved1; /*0x08 */
2266 U32 Reserved2; /*0x0C */
2267 U8 NumGroups; /*0x10 */
2268 U8 Reserved3; /*0x11 */
2269 U16 Reserved4; /*0x12 */
2270 MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS
2271 PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /*0x14 */
2272} MPI2_CONFIG_PAGE_SASIOUNIT_6,
2273 *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6,
2274 Mpi2SasIOUnitPage6_t, *pMpi2SasIOUnitPage6_t;
2275
2276#define MPI2_SASIOUNITPAGE6_PAGEVERSION (0x00)
2277
2278
2279/*SAS IO Unit Page 7 */
2280
2281typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS {
2282 U8 Flags; /*0x00 */
2283 U8 Reserved1; /*0x01 */
2284 U16 Reserved2; /*0x02 */
2285 U8 Threshold75Pct; /*0x04 */
2286 U8 Threshold50Pct; /*0x05 */
2287 U8 Threshold25Pct; /*0x06 */
2288 U8 Reserved3; /*0x07 */
2289} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
2290 *PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
2291 Mpi2SasIOUnit7PortWidthModGroupSettings_t,
2292 *pMpi2SasIOUnit7PortWidthModGroupSettings_t;
2293
2294/*defines for Flags field */
2295#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION (0x01)
2296
2297
2298/*
2299 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2300 *one and check the value returned for NumGroups at runtime.
2301 */
2302#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX
2303#define MPI2_SAS_IOUNIT7_GROUP_MAX (1)
2304#endif
2305
2306typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 {
2307 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
2308 U8 SamplingInterval; /*0x08 */
2309 U8 WindowLength; /*0x09 */
2310 U16 Reserved1; /*0x0A */
2311 U32 Reserved2; /*0x0C */
2312 U32 Reserved3; /*0x10 */
2313 U8 NumGroups; /*0x14 */
2314 U8 Reserved4; /*0x15 */
2315 U16 Reserved5; /*0x16 */
2316 MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS
2317 PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX];/*0x18 */
2318} MPI2_CONFIG_PAGE_SASIOUNIT_7,
2319 *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7,
2320 Mpi2SasIOUnitPage7_t, *pMpi2SasIOUnitPage7_t;
2321
2322#define MPI2_SASIOUNITPAGE7_PAGEVERSION (0x00)
2323
2324
2325/*SAS IO Unit Page 8 */
2326
2327typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 {
2328 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2329 Header; /*0x00 */
2330 U32
2331 Reserved1; /*0x08 */
2332 U32
2333 PowerManagementCapabilities; /*0x0C */
2334 U8
2335 TxRxSleepStatus; /*0x10 */
2336 U8
2337 Reserved2; /*0x11 */
2338 U16
2339 Reserved3; /*0x12 */
2340} MPI2_CONFIG_PAGE_SASIOUNIT_8,
2341 *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8,
2342 Mpi2SasIOUnitPage8_t, *pMpi2SasIOUnitPage8_t;
2343
2344#define MPI2_SASIOUNITPAGE8_PAGEVERSION (0x00)
2345
2346/*defines for PowerManagementCapabilities field */
2347#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x00001000)
2348#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x00000800)
2349#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x00000400)
2350#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x00000200)
2351#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x00000100)
2352#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x00000010)
2353#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008)
2354#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004)
2355#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002)
2356#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001)
2357
2358/*defines for TxRxSleepStatus field */
2359#define MPI25_SASIOUNIT8_TXRXSLEEP_UNSUPPORTED (0x00)
2360#define MPI25_SASIOUNIT8_TXRXSLEEP_DISENGAGED (0x01)
2361#define MPI25_SASIOUNIT8_TXRXSLEEP_ACTIVE (0x02)
2362#define MPI25_SASIOUNIT8_TXRXSLEEP_SHUTDOWN (0x03)
2363
2364
2365
2366/*SAS IO Unit Page 16 */
2367
2368typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 {
2369 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2370 Header; /*0x00 */
2371 U64
2372 TimeStamp; /*0x08 */
2373 U32
2374 Reserved1; /*0x10 */
2375 U32
2376 Reserved2; /*0x14 */
2377 U32
2378 FastPathPendedRequests; /*0x18 */
2379 U32
2380 FastPathUnPendedRequests; /*0x1C */
2381 U32
2382 FastPathHostRequestStarts; /*0x20 */
2383 U32
2384 FastPathFirmwareRequestStarts; /*0x24 */
2385 U32
2386 FastPathHostCompletions; /*0x28 */
2387 U32
2388 FastPathFirmwareCompletions; /*0x2C */
2389 U32
2390 NonFastPathRequestStarts; /*0x30 */
2391 U32
2392 NonFastPathHostCompletions; /*0x30 */
2393} MPI2_CONFIG_PAGE_SASIOUNIT16,
2394 *PTR_MPI2_CONFIG_PAGE_SASIOUNIT16,
2395 Mpi2SasIOUnitPage16_t, *pMpi2SasIOUnitPage16_t;
2396
2397#define MPI2_SASIOUNITPAGE16_PAGEVERSION (0x00)
2398
2399
2400/****************************************************************************
2401* SAS Expander Config Pages
2402****************************************************************************/
2403
2404/*SAS Expander Page 0 */
2405
2406typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 {
2407 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2408 Header; /*0x00 */
2409 U8
2410 PhysicalPort; /*0x08 */
2411 U8
2412 ReportGenLength; /*0x09 */
2413 U16
2414 EnclosureHandle; /*0x0A */
2415 U64
2416 SASAddress; /*0x0C */
2417 U32
2418 DiscoveryStatus; /*0x14 */
2419 U16
2420 DevHandle; /*0x18 */
2421 U16
2422 ParentDevHandle; /*0x1A */
2423 U16
2424 ExpanderChangeCount; /*0x1C */
2425 U16
2426 ExpanderRouteIndexes; /*0x1E */
2427 U8
2428 NumPhys; /*0x20 */
2429 U8
2430 SASLevel; /*0x21 */
2431 U16
2432 Flags; /*0x22 */
2433 U16
2434 STPBusInactivityTimeLimit; /*0x24 */
2435 U16
2436 STPMaxConnectTimeLimit; /*0x26 */
2437 U16
2438 STP_SMP_NexusLossTime; /*0x28 */
2439 U16
2440 MaxNumRoutedSasAddresses; /*0x2A */
2441 U64
2442 ActiveZoneManagerSASAddress;/*0x2C */
2443 U16
2444 ZoneLockInactivityLimit; /*0x34 */
2445 U16
2446 Reserved1; /*0x36 */
2447 U8
2448 TimeToReducedFunc; /*0x38 */
2449 U8
2450 InitialTimeToReducedFunc; /*0x39 */
2451 U8
2452 MaxReducedFuncTime; /*0x3A */
2453 U8
2454 Reserved2; /*0x3B */
2455} MPI2_CONFIG_PAGE_EXPANDER_0,
2456 *PTR_MPI2_CONFIG_PAGE_EXPANDER_0,
2457 Mpi2ExpanderPage0_t, *pMpi2ExpanderPage0_t;
2458
2459#define MPI2_SASEXPANDER0_PAGEVERSION (0x06)
2460
2461/*values for SAS Expander Page 0 DiscoveryStatus field */
2462#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
2463#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000)
2464#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000)
2465#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
2466#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000)
2467#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
2468#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
2469#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000)
2470#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
2471#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800)
2472#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400)
2473#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200)
2474#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100)
2475#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080)
2476#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040)
2477#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020)
2478#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010)
2479#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004)
2480#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002)
2481#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
2482
2483/*values for SAS Expander Page 0 Flags field */
2484#define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000)
2485#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000)
2486#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800)
2487#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400)
2488#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200)
2489#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100)
2490#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080)
2491#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010)
2492#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004)
2493#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002)
2494#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001)
2495
2496
2497/*SAS Expander Page 1 */
2498
2499typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1 {
2500 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2501 Header; /*0x00 */
2502 U8
2503 PhysicalPort; /*0x08 */
2504 U8
2505 Reserved1; /*0x09 */
2506 U16
2507 Reserved2; /*0x0A */
2508 U8
2509 NumPhys; /*0x0C */
2510 U8
2511 Phy; /*0x0D */
2512 U16
2513 NumTableEntriesProgrammed; /*0x0E */
2514 U8
2515 ProgrammedLinkRate; /*0x10 */
2516 U8
2517 HwLinkRate; /*0x11 */
2518 U16
2519 AttachedDevHandle; /*0x12 */
2520 U32
2521 PhyInfo; /*0x14 */
2522 U32
2523 AttachedDeviceInfo; /*0x18 */
2524 U16
2525 ExpanderDevHandle; /*0x1C */
2526 U8
2527 ChangeCount; /*0x1E */
2528 U8
2529 NegotiatedLinkRate; /*0x1F */
2530 U8
2531 PhyIdentifier; /*0x20 */
2532 U8
2533 AttachedPhyIdentifier; /*0x21 */
2534 U8
2535 Reserved3; /*0x22 */
2536 U8
2537 DiscoveryInfo; /*0x23 */
2538 U32
2539 AttachedPhyInfo; /*0x24 */
2540 U8
2541 ZoneGroup; /*0x28 */
2542 U8
2543 SelfConfigStatus; /*0x29 */
2544 U16
2545 Reserved4; /*0x2A */
2546} MPI2_CONFIG_PAGE_EXPANDER_1,
2547 *PTR_MPI2_CONFIG_PAGE_EXPANDER_1,
2548 Mpi2ExpanderPage1_t, *pMpi2ExpanderPage1_t;
2549
2550#define MPI2_SASEXPANDER1_PAGEVERSION (0x02)
2551
2552/*use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
2553
2554/*use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
2555
2556/*use MPI2_SAS_PHYINFO_ for the PhyInfo field */
2557
2558/*see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines
2559 *used for the AttachedDeviceInfo field */
2560
2561/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
2562
2563/*values for SAS Expander Page 1 DiscoveryInfo field */
2564#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04)
2565#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02)
2566#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01)
2567
2568/*use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
2569
2570
2571/****************************************************************************
2572* SAS Device Config Pages
2573****************************************************************************/
2574
2575/*SAS Device Page 0 */
2576
2577typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 {
2578 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2579 Header; /*0x00 */
2580 U16
2581 Slot; /*0x08 */
2582 U16
2583 EnclosureHandle; /*0x0A */
2584 U64
2585 SASAddress; /*0x0C */
2586 U16
2587 ParentDevHandle; /*0x14 */
2588 U8
2589 PhyNum; /*0x16 */
2590 U8
2591 AccessStatus; /*0x17 */
2592 U16
2593 DevHandle; /*0x18 */
2594 U8
2595 AttachedPhyIdentifier; /*0x1A */
2596 U8
2597 ZoneGroup; /*0x1B */
2598 U32
2599 DeviceInfo; /*0x1C */
2600 U16
2601 Flags; /*0x20 */
2602 U8
2603 PhysicalPort; /*0x22 */
2604 U8
2605 MaxPortConnections; /*0x23 */
2606 U64
2607 DeviceName; /*0x24 */
2608 U8
2609 PortGroups; /*0x2C */
2610 U8
2611 DmaGroup; /*0x2D */
2612 U8
2613 ControlGroup; /*0x2E */
2614 U8
2615 Reserved1; /*0x2F */
2616 U32
2617 Reserved2; /*0x30 */
2618 U32
2619 Reserved3; /*0x34 */
2620} MPI2_CONFIG_PAGE_SAS_DEV_0,
2621 *PTR_MPI2_CONFIG_PAGE_SAS_DEV_0,
2622 Mpi2SasDevicePage0_t,
2623 *pMpi2SasDevicePage0_t;
2624
2625#define MPI2_SASDEVICE0_PAGEVERSION (0x08)
2626
2627/*values for SAS Device Page 0 AccessStatus field */
2628#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00)
2629#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01)
2630#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02)
2631#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03)
2632#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04)
2633#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05)
2634#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06)
2635#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07)
2636/*specific values for SATA Init failures */
2637#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10)
2638#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11)
2639#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12)
2640#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13)
2641#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14)
2642#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15)
2643#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16)
2644#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17)
2645#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18)
2646#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19)
2647#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F)
2648
2649/*see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
2650
2651/*values for SAS Device Page 0 Flags field */
2652#define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE (0x8000)
2653#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH (0x4000)
2654#define MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE (0x2000)
2655#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE (0x1000)
2656#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE (0x0800)
2657#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400)
2658#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200)
2659#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
2660#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080)
2661#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040)
2662#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020)
2663#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010)
2664#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008)
2665#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
2666
2667
2668/*SAS Device Page 1 */
2669
2670typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1 {
2671 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2672 Header; /*0x00 */
2673 U32
2674 Reserved1; /*0x08 */
2675 U64
2676 SASAddress; /*0x0C */
2677 U32
2678 Reserved2; /*0x14 */
2679 U16
2680 DevHandle; /*0x18 */
2681 U16
2682 Reserved3; /*0x1A */
2683 U8
2684 InitialRegDeviceFIS[20];/*0x1C */
2685} MPI2_CONFIG_PAGE_SAS_DEV_1,
2686 *PTR_MPI2_CONFIG_PAGE_SAS_DEV_1,
2687 Mpi2SasDevicePage1_t,
2688 *pMpi2SasDevicePage1_t;
2689
2690#define MPI2_SASDEVICE1_PAGEVERSION (0x01)
2691
2692
2693/****************************************************************************
2694* SAS PHY Config Pages
2695****************************************************************************/
2696
2697/*SAS PHY Page 0 */
2698
2699typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 {
2700 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2701 Header; /*0x00 */
2702 U16
2703 OwnerDevHandle; /*0x08 */
2704 U16
2705 Reserved1; /*0x0A */
2706 U16
2707 AttachedDevHandle; /*0x0C */
2708 U8
2709 AttachedPhyIdentifier; /*0x0E */
2710 U8
2711 Reserved2; /*0x0F */
2712 U32
2713 AttachedPhyInfo; /*0x10 */
2714 U8
2715 ProgrammedLinkRate; /*0x14 */
2716 U8
2717 HwLinkRate; /*0x15 */
2718 U8
2719 ChangeCount; /*0x16 */
2720 U8
2721 Flags; /*0x17 */
2722 U32
2723 PhyInfo; /*0x18 */
2724 U8
2725 NegotiatedLinkRate; /*0x1C */
2726 U8
2727 Reserved3; /*0x1D */
2728 U16
2729 Reserved4; /*0x1E */
2730} MPI2_CONFIG_PAGE_SAS_PHY_0,
2731 *PTR_MPI2_CONFIG_PAGE_SAS_PHY_0,
2732 Mpi2SasPhyPage0_t, *pMpi2SasPhyPage0_t;
2733
2734#define MPI2_SASPHY0_PAGEVERSION (0x03)
2735
2736/*use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
2737
2738/*use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
2739
2740/*use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
2741
2742/*values for SAS PHY Page 0 Flags field */
2743#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01)
2744
2745/*use MPI2_SAS_PHYINFO_ for the PhyInfo field */
2746
2747/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
2748
2749
2750/*SAS PHY Page 1 */
2751
2752typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1 {
2753 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2754 Header; /*0x00 */
2755 U32
2756 Reserved1; /*0x08 */
2757 U32
2758 InvalidDwordCount; /*0x0C */
2759 U32
2760 RunningDisparityErrorCount; /*0x10 */
2761 U32
2762 LossDwordSynchCount; /*0x14 */
2763 U32
2764 PhyResetProblemCount; /*0x18 */
2765} MPI2_CONFIG_PAGE_SAS_PHY_1,
2766 *PTR_MPI2_CONFIG_PAGE_SAS_PHY_1,
2767 Mpi2SasPhyPage1_t, *pMpi2SasPhyPage1_t;
2768
2769#define MPI2_SASPHY1_PAGEVERSION (0x01)
2770
2771
2772/*SAS PHY Page 2 */
2773
2774typedef struct _MPI2_SASPHY2_PHY_EVENT {
2775 U8 PhyEventCode; /*0x00 */
2776 U8 Reserved1; /*0x01 */
2777 U16 Reserved2; /*0x02 */
2778 U32 PhyEventInfo; /*0x04 */
2779} MPI2_SASPHY2_PHY_EVENT, *PTR_MPI2_SASPHY2_PHY_EVENT,
2780 Mpi2SasPhy2PhyEvent_t, *pMpi2SasPhy2PhyEvent_t;
2781
2782/*use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */
2783
2784
2785/*
2786 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2787 *one and check the value returned for NumPhyEvents at runtime.
2788 */
2789#ifndef MPI2_SASPHY2_PHY_EVENT_MAX
2790#define MPI2_SASPHY2_PHY_EVENT_MAX (1)
2791#endif
2792
2793typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 {
2794 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2795 Header; /*0x00 */
2796 U32
2797 Reserved1; /*0x08 */
2798 U8
2799 NumPhyEvents; /*0x0C */
2800 U8
2801 Reserved2; /*0x0D */
2802 U16
2803 Reserved3; /*0x0E */
2804 MPI2_SASPHY2_PHY_EVENT
2805 PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; /*0x10 */
2806} MPI2_CONFIG_PAGE_SAS_PHY_2,
2807 *PTR_MPI2_CONFIG_PAGE_SAS_PHY_2,
2808 Mpi2SasPhyPage2_t,
2809 *pMpi2SasPhyPage2_t;
2810
2811#define MPI2_SASPHY2_PAGEVERSION (0x00)
2812
2813
2814/*SAS PHY Page 3 */
2815
2816typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG {
2817 U8 PhyEventCode; /*0x00 */
2818 U8 Reserved1; /*0x01 */
2819 U16 Reserved2; /*0x02 */
2820 U8 CounterType; /*0x04 */
2821 U8 ThresholdWindow; /*0x05 */
2822 U8 TimeUnits; /*0x06 */
2823 U8 Reserved3; /*0x07 */
2824 U32 EventThreshold; /*0x08 */
2825 U16 ThresholdFlags; /*0x0C */
2826 U16 Reserved4; /*0x0E */
2827} MPI2_SASPHY3_PHY_EVENT_CONFIG,
2828 *PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG,
2829 Mpi2SasPhy3PhyEventConfig_t,
2830 *pMpi2SasPhy3PhyEventConfig_t;
2831
2832/*values for PhyEventCode field */
2833#define MPI2_SASPHY3_EVENT_CODE_NO_EVENT (0x00)
2834#define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01)
2835#define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02)
2836#define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03)
2837#define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04)
2838#define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05)
2839#define MPI2_SASPHY3_EVENT_CODE_RX_ERROR (0x06)
2840#define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20)
2841#define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21)
2842#define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22)
2843#define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23)
2844#define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24)
2845#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25)
2846#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26)
2847#define MPI2_SASPHY3_EVENT_CODE_TX_BREAK (0x27)
2848#define MPI2_SASPHY3_EVENT_CODE_RX_BREAK (0x28)
2849#define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29)
2850#define MPI2_SASPHY3_EVENT_CODE_CONNECTION (0x2A)
2851#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B)
2852#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C)
2853#define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D)
2854#define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E)
2855#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40)
2856#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41)
2857#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42)
2858#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43)
2859#define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44)
2860#define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45)
2861#define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50)
2862#define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51)
2863#define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52)
2864#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60)
2865#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61)
2866#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63)
2867#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0)
2868#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1)
2869#define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2)
2870
2871/*values for the CounterType field */
2872#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00)
2873#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01)
2874#define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02)
2875
2876/*values for the TimeUnits field */
2877#define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00)
2878#define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01)
2879#define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02)
2880#define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03)
2881
2882/*values for the ThresholdFlags field */
2883#define MPI2_SASPHY3_TFLAGS_PHY_RESET (0x0002)
2884#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001)
2885
2886/*
2887 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
2888 *one and check the value returned for NumPhyEvents at runtime.
2889 */
2890#ifndef MPI2_SASPHY3_PHY_EVENT_MAX
2891#define MPI2_SASPHY3_PHY_EVENT_MAX (1)
2892#endif
2893
2894typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 {
2895 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2896 Header; /*0x00 */
2897 U32
2898 Reserved1; /*0x08 */
2899 U8
2900 NumPhyEvents; /*0x0C */
2901 U8
2902 Reserved2; /*0x0D */
2903 U16
2904 Reserved3; /*0x0E */
2905 MPI2_SASPHY3_PHY_EVENT_CONFIG
2906 PhyEventConfig[MPI2_SASPHY3_PHY_EVENT_MAX]; /*0x10 */
2907} MPI2_CONFIG_PAGE_SAS_PHY_3,
2908 *PTR_MPI2_CONFIG_PAGE_SAS_PHY_3,
2909 Mpi2SasPhyPage3_t, *pMpi2SasPhyPage3_t;
2910
2911#define MPI2_SASPHY3_PAGEVERSION (0x00)
2912
2913
2914/*SAS PHY Page 4 */
2915
2916typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4 {
2917 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2918 Header; /*0x00 */
2919 U16
2920 Reserved1; /*0x08 */
2921 U8
2922 Reserved2; /*0x0A */
2923 U8
2924 Flags; /*0x0B */
2925 U8
2926 InitialFrame[28]; /*0x0C */
2927} MPI2_CONFIG_PAGE_SAS_PHY_4,
2928 *PTR_MPI2_CONFIG_PAGE_SAS_PHY_4,
2929 Mpi2SasPhyPage4_t, *pMpi2SasPhyPage4_t;
2930
2931#define MPI2_SASPHY4_PAGEVERSION (0x00)
2932
2933/*values for the Flags field */
2934#define MPI2_SASPHY4_FLAGS_FRAME_VALID (0x02)
2935#define MPI2_SASPHY4_FLAGS_SATA_FRAME (0x01)
2936
2937
2938
2939
2940/****************************************************************************
2941* SAS Port Config Pages
2942****************************************************************************/
2943
2944/*SAS Port Page 0 */
2945
2946typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0 {
2947 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2948 Header; /*0x00 */
2949 U8
2950 PortNumber; /*0x08 */
2951 U8
2952 PhysicalPort; /*0x09 */
2953 U8
2954 PortWidth; /*0x0A */
2955 U8
2956 PhysicalPortWidth; /*0x0B */
2957 U8
2958 ZoneGroup; /*0x0C */
2959 U8
2960 Reserved1; /*0x0D */
2961 U16
2962 Reserved2; /*0x0E */
2963 U64
2964 SASAddress; /*0x10 */
2965 U32
2966 DeviceInfo; /*0x18 */
2967 U32
2968 Reserved3; /*0x1C */
2969 U32
2970 Reserved4; /*0x20 */
2971} MPI2_CONFIG_PAGE_SAS_PORT_0,
2972 *PTR_MPI2_CONFIG_PAGE_SAS_PORT_0,
2973 Mpi2SasPortPage0_t, *pMpi2SasPortPage0_t;
2974
2975#define MPI2_SASPORT0_PAGEVERSION (0x00)
2976
2977/*see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */
2978
2979
2980/****************************************************************************
2981* SAS Enclosure Config Pages
2982****************************************************************************/
2983
2984/*SAS Enclosure Page 0 */
2985
2986typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 {
2987 MPI2_CONFIG_EXTENDED_PAGE_HEADER
2988 Header; /*0x00 */
2989 U32
2990 Reserved1; /*0x08 */
2991 U64
2992 EnclosureLogicalID; /*0x0C */
2993 U16
2994 Flags; /*0x14 */
2995 U16
2996 EnclosureHandle; /*0x16 */
2997 U16
2998 NumSlots; /*0x18 */
2999 U16
3000 StartSlot; /*0x1A */
3001 U16
3002 Reserved2; /*0x1C */
3003 U16
3004 SEPDevHandle; /*0x1E */
3005 U32
3006 Reserved3; /*0x20 */
3007 U32
3008 Reserved4; /*0x24 */
3009} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
3010 *PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
3011 Mpi2SasEnclosurePage0_t, *pMpi2SasEnclosurePage0_t;
3012
3013#define MPI2_SASENCLOSURE0_PAGEVERSION (0x03)
3014
3015/*values for SAS Enclosure Page 0 Flags field */
3016#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F)
3017#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000)
3018#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001)
3019#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
3020#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
3021#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
3022#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
3023
3024
3025/****************************************************************************
3026* Log Config Page
3027****************************************************************************/
3028
3029/*Log Page 0 */
3030
3031/*
3032 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
3033 *one and check the value returned for NumLogEntries at runtime.
3034 */
3035#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
3036#define MPI2_LOG_0_NUM_LOG_ENTRIES (1)
3037#endif
3038
3039#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C)
3040
3041typedef struct _MPI2_LOG_0_ENTRY {
3042 U64 TimeStamp; /*0x00 */
3043 U32 Reserved1; /*0x08 */
3044 U16 LogSequence; /*0x0C */
3045 U16 LogEntryQualifier; /*0x0E */
3046 U8 VP_ID; /*0x10 */
3047 U8 VF_ID; /*0x11 */
3048 U16 Reserved2; /*0x12 */
3049 U8
3050 LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/*0x14 */
3051} MPI2_LOG_0_ENTRY, *PTR_MPI2_LOG_0_ENTRY,
3052 Mpi2Log0Entry_t, *pMpi2Log0Entry_t;
3053
3054/*values for Log Page 0 LogEntry LogEntryQualifier field */
3055#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000)
3056#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001)
3057#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002)
3058#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000)
3059#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF)
3060
3061typedef struct _MPI2_CONFIG_PAGE_LOG_0 {
3062 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
3063 U32 Reserved1; /*0x08 */
3064 U32 Reserved2; /*0x0C */
3065 U16 NumLogEntries;/*0x10 */
3066 U16 Reserved3; /*0x12 */
3067 MPI2_LOG_0_ENTRY
3068 LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /*0x14 */
3069} MPI2_CONFIG_PAGE_LOG_0, *PTR_MPI2_CONFIG_PAGE_LOG_0,
3070 Mpi2LogPage0_t, *pMpi2LogPage0_t;
3071
3072#define MPI2_LOG_0_PAGEVERSION (0x02)
3073
3074
3075/****************************************************************************
3076* RAID Config Page
3077****************************************************************************/
3078
3079/*RAID Page 0 */
3080
3081/*
3082 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
3083 *one and check the value returned for NumElements at runtime.
3084 */
3085#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
3086#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1)
3087#endif
3088
3089typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT {
3090 U16 ElementFlags; /*0x00 */
3091 U16 VolDevHandle; /*0x02 */
3092 U8 HotSparePool; /*0x04 */
3093 U8 PhysDiskNum; /*0x05 */
3094 U16 PhysDiskDevHandle; /*0x06 */
3095} MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
3096 *PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
3097 Mpi2RaidConfig0ConfigElement_t,
3098 *pMpi2RaidConfig0ConfigElement_t;
3099
3100/*values for the ElementFlags field */
3101#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F)
3102#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000)
3103#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001)
3104#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002)
3105#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003)
3106
3107
3108typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 {
3109 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
3110 U8 NumHotSpares; /*0x08 */
3111 U8 NumPhysDisks; /*0x09 */
3112 U8 NumVolumes; /*0x0A */
3113 U8 ConfigNum; /*0x0B */
3114 U32 Flags; /*0x0C */
3115 U8 ConfigGUID[24]; /*0x10 */
3116 U32 Reserved1; /*0x28 */
3117 U8 NumElements; /*0x2C */
3118 U8 Reserved2; /*0x2D */
3119 U16 Reserved3; /*0x2E */
3120 MPI2_RAIDCONFIG0_CONFIG_ELEMENT
3121 ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /*0x30 */
3122} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
3123 *PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
3124 Mpi2RaidConfigurationPage0_t,
3125 *pMpi2RaidConfigurationPage0_t;
3126
3127#define MPI2_RAIDCONFIG0_PAGEVERSION (0x00)
3128
3129/*values for RAID Configuration Page 0 Flags field */
3130#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001)
3131
3132
3133/****************************************************************************
3134* Driver Persistent Mapping Config Pages
3135****************************************************************************/
3136
3137/*Driver Persistent Mapping Page 0 */
3138
3139typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY {
3140 U64 PhysicalIdentifier; /*0x00 */
3141 U16 MappingInformation; /*0x08 */
3142 U16 DeviceIndex; /*0x0A */
3143 U32 PhysicalBitsMapping; /*0x0C */
3144 U32 Reserved1; /*0x10 */
3145} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
3146 *PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
3147 Mpi2DriverMap0Entry_t, *pMpi2DriverMap0Entry_t;
3148
3149typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 {
3150 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
3151 MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /*0x08 */
3152} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
3153 *PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
3154 Mpi2DriverMappingPage0_t, *pMpi2DriverMappingPage0_t;
3155
3156#define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00)
3157
3158/*values for Driver Persistent Mapping Page 0 MappingInformation field */
3159#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0)
3160#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4)
3161#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F)
3162
3163
3164/****************************************************************************
3165* Ethernet Config Pages
3166****************************************************************************/
3167
3168/*Ethernet Page 0 */
3169
3170/*IP address (union of IPv4 and IPv6) */
3171typedef union _MPI2_ETHERNET_IP_ADDR {
3172 U32 IPv4Addr;
3173 U32 IPv6Addr[4];
3174} MPI2_ETHERNET_IP_ADDR, *PTR_MPI2_ETHERNET_IP_ADDR,
3175 Mpi2EthernetIpAddr_t, *pMpi2EthernetIpAddr_t;
3176
3177#define MPI2_ETHERNET_HOST_NAME_LENGTH (32)
3178
3179typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0 {
3180 MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
3181 U8 NumInterfaces; /*0x08 */
3182 U8 Reserved0; /*0x09 */
3183 U16 Reserved1; /*0x0A */
3184 U32 Status; /*0x0C */
3185 U8 MediaState; /*0x10 */
3186 U8 Reserved2; /*0x11 */
3187 U16 Reserved3; /*0x12 */
3188 U8 MacAddress[6]; /*0x14 */
3189 U8 Reserved4; /*0x1A */
3190 U8 Reserved5; /*0x1B */
3191 MPI2_ETHERNET_IP_ADDR IpAddress; /*0x1C */
3192 MPI2_ETHERNET_IP_ADDR SubnetMask; /*0x2C */
3193 MPI2_ETHERNET_IP_ADDR GatewayIpAddress;/*0x3C */
3194 MPI2_ETHERNET_IP_ADDR DNS1IpAddress; /*0x4C */
3195 MPI2_ETHERNET_IP_ADDR DNS2IpAddress; /*0x5C */
3196 MPI2_ETHERNET_IP_ADDR DhcpIpAddress; /*0x6C */
3197 U8
3198 HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/*0x7C */
3199} MPI2_CONFIG_PAGE_ETHERNET_0,
3200 *PTR_MPI2_CONFIG_PAGE_ETHERNET_0,
3201 Mpi2EthernetPage0_t, *pMpi2EthernetPage0_t;
3202
3203#define MPI2_ETHERNETPAGE0_PAGEVERSION (0x00)
3204
3205/*values for Ethernet Page 0 Status field */
3206#define MPI2_ETHPG0_STATUS_IPV6_CAPABLE (0x80000000)
3207#define MPI2_ETHPG0_STATUS_IPV4_CAPABLE (0x40000000)
3208#define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED (0x20000000)
3209#define MPI2_ETHPG0_STATUS_DEFAULT_IF (0x00000100)
3210#define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED (0x00000080)
3211#define MPI2_ETHPG0_STATUS_TELNET_ENABLED (0x00000040)
3212#define MPI2_ETHPG0_STATUS_SSH2_ENABLED (0x00000020)
3213#define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED (0x00000010)
3214#define MPI2_ETHPG0_STATUS_IPV6_ENABLED (0x00000008)
3215#define MPI2_ETHPG0_STATUS_IPV4_ENABLED (0x00000004)
3216#define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES (0x00000002)
3217#define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED (0x00000001)
3218
3219/*values for Ethernet Page 0 MediaState field */
3220#define MPI2_ETHPG0_MS_DUPLEX_MASK (0x80)
3221#define MPI2_ETHPG0_MS_HALF_DUPLEX (0x00)
3222#define MPI2_ETHPG0_MS_FULL_DUPLEX (0x80)
3223
3224#define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK (0x07)
3225#define MPI2_ETHPG0_MS_NOT_CONNECTED (0x00)
3226#define MPI2_ETHPG0_MS_10MBIT (0x01)
3227#define MPI2_ETHPG0_MS_100MBIT (0x02)
3228#define MPI2_ETHPG0_MS_1GBIT (0x03)
3229
3230
3231/*Ethernet Page 1 */
3232
3233typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 {
3234 MPI2_CONFIG_EXTENDED_PAGE_HEADER
3235 Header; /*0x00 */
3236 U32
3237 Reserved0; /*0x08 */
3238 U32
3239 Flags; /*0x0C */
3240 U8
3241 MediaState; /*0x10 */
3242 U8
3243 Reserved1; /*0x11 */
3244 U16
3245 Reserved2; /*0x12 */
3246 U8
3247 MacAddress[6]; /*0x14 */
3248 U8
3249 Reserved3; /*0x1A */
3250 U8
3251 Reserved4; /*0x1B */
3252 MPI2_ETHERNET_IP_ADDR
3253 StaticIpAddress; /*0x1C */
3254 MPI2_ETHERNET_IP_ADDR
3255 StaticSubnetMask; /*0x2C */
3256 MPI2_ETHERNET_IP_ADDR
3257 StaticGatewayIpAddress; /*0x3C */
3258 MPI2_ETHERNET_IP_ADDR
3259 StaticDNS1IpAddress; /*0x4C */
3260 MPI2_ETHERNET_IP_ADDR
3261 StaticDNS2IpAddress; /*0x5C */
3262 U32
3263 Reserved5; /*0x6C */
3264 U32
3265 Reserved6; /*0x70 */
3266 U32
3267 Reserved7; /*0x74 */
3268 U32
3269 Reserved8; /*0x78 */
3270 U8
3271 HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/*0x7C */
3272} MPI2_CONFIG_PAGE_ETHERNET_1,
3273 *PTR_MPI2_CONFIG_PAGE_ETHERNET_1,
3274 Mpi2EthernetPage1_t, *pMpi2EthernetPage1_t;
3275
3276#define MPI2_ETHERNETPAGE1_PAGEVERSION (0x00)
3277
3278/*values for Ethernet Page 1 Flags field */
3279#define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF (0x00000100)
3280#define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD (0x00000080)
3281#define MPI2_ETHPG1_FLAG_ENABLE_TELNET (0x00000040)
3282#define MPI2_ETHPG1_FLAG_ENABLE_SSH2 (0x00000020)
3283#define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT (0x00000010)
3284#define MPI2_ETHPG1_FLAG_ENABLE_IPV6 (0x00000008)
3285#define MPI2_ETHPG1_FLAG_ENABLE_IPV4 (0x00000004)
3286#define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES (0x00000002)
3287#define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF (0x00000001)
3288
3289/*values for Ethernet Page 1 MediaState field */
3290#define MPI2_ETHPG1_MS_DUPLEX_MASK (0x80)
3291#define MPI2_ETHPG1_MS_HALF_DUPLEX (0x00)
3292#define MPI2_ETHPG1_MS_FULL_DUPLEX (0x80)
3293
3294#define MPI2_ETHPG1_MS_DATA_RATE_MASK (0x07)
3295#define MPI2_ETHPG1_MS_DATA_RATE_AUTO (0x00)
3296#define MPI2_ETHPG1_MS_DATA_RATE_10MBIT (0x01)
3297#define MPI2_ETHPG1_MS_DATA_RATE_100MBIT (0x02)
3298#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03)
3299
3300
3301/****************************************************************************
3302* Extended Manufacturing Config Pages
3303****************************************************************************/
3304
3305/*
3306 *Generic structure to use for product-specific extended manufacturing pages
3307 *(currently Extended Manufacturing Page 40 through Extended Manufacturing
3308 *Page 60).
3309 */
3310
3311typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
3312 MPI2_CONFIG_EXTENDED_PAGE_HEADER
3313 Header; /*0x00 */
3314 U32
3315 ProductSpecificInfo; /*0x08 */
3316} MPI2_CONFIG_PAGE_EXT_MAN_PS,
3317 *PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
3318 Mpi2ExtManufacturingPagePS_t,
3319 *pMpi2ExtManufacturingPagePS_t;
3320
3321/*PageVersion should be provided by product-specific code */
3322
3323#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_init.h b/drivers/scsi/mpt3sas/mpi/mpi2_init.h
new file mode 100644
index 000000000000..a079e5242474
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_init.h
@@ -0,0 +1,560 @@
1/*
2 * Copyright (c) 2000-2012 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.14
10 *
11 * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
12 * prefix are for use only on MPI v2.5 products, and must not be used
13 * with MPI v2.0 products. Unless otherwise noted, names beginning with
14 * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
15 *
16 * Version History
17 * ---------------
18 *
19 * Date Version Description
20 * -------- -------- ------------------------------------------------------
21 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
22 * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t.
23 * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines.
24 * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention.
25 * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
26 * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t.
27 * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO
28 * Control field Task Attribute flags.
29 * Moved LUN field defines to mpi2.h becasue they are
30 * common to many structures.
31 * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to
32 * Query Asynchronous Event.
33 * Defined two new bits in the SlotStatus field of the SCSI
34 * Enclosure Processor Request and Reply.
35 * 10-28-09 02.00.08 Added defines for decoding the ResponseInfo bytes for
36 * both SCSI IO Error Reply and SCSI Task Management Reply.
37 * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
38 * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
39 * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it.
40 * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request.
41 * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
42 * 11-18-11 02.00.12 Incorporating additions for MPI v2.5.
43 * 02-06-12 02.00.13 Added alternate defines for Task Priority / Command
44 * Priority to match SAM-4.
45 * Added EEDPErrorOffset to MPI2_SCSI_IO_REPLY.
46 * 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION.
47 * --------------------------------------------------------------------------
48 */
49
50#ifndef MPI2_INIT_H
51#define MPI2_INIT_H
52
53/*****************************************************************************
54*
55* SCSI Initiator Messages
56*
57*****************************************************************************/
58
59/****************************************************************************
60* SCSI IO messages and associated structures
61****************************************************************************/
62
63typedef struct _MPI2_SCSI_IO_CDB_EEDP32 {
64 U8 CDB[20]; /*0x00 */
65 U32 PrimaryReferenceTag; /*0x14 */
66 U16 PrimaryApplicationTag; /*0x18 */
67 U16 PrimaryApplicationTagMask; /*0x1A */
68 U32 TransferLength; /*0x1C */
69} MPI2_SCSI_IO_CDB_EEDP32, *PTR_MPI2_SCSI_IO_CDB_EEDP32,
70 Mpi2ScsiIoCdbEedp32_t, *pMpi2ScsiIoCdbEedp32_t;
71
72/*MPI v2.0 CDB field */
73typedef union _MPI2_SCSI_IO_CDB_UNION {
74 U8 CDB32[32];
75 MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
76 MPI2_SGE_SIMPLE_UNION SGE;
77} MPI2_SCSI_IO_CDB_UNION, *PTR_MPI2_SCSI_IO_CDB_UNION,
78 Mpi2ScsiIoCdb_t, *pMpi2ScsiIoCdb_t;
79
80/*MPI v2.0 SCSI IO Request Message */
81typedef struct _MPI2_SCSI_IO_REQUEST {
82 U16 DevHandle; /*0x00 */
83 U8 ChainOffset; /*0x02 */
84 U8 Function; /*0x03 */
85 U16 Reserved1; /*0x04 */
86 U8 Reserved2; /*0x06 */
87 U8 MsgFlags; /*0x07 */
88 U8 VP_ID; /*0x08 */
89 U8 VF_ID; /*0x09 */
90 U16 Reserved3; /*0x0A */
91 U32 SenseBufferLowAddress; /*0x0C */
92 U16 SGLFlags; /*0x10 */
93 U8 SenseBufferLength; /*0x12 */
94 U8 Reserved4; /*0x13 */
95 U8 SGLOffset0; /*0x14 */
96 U8 SGLOffset1; /*0x15 */
97 U8 SGLOffset2; /*0x16 */
98 U8 SGLOffset3; /*0x17 */
99 U32 SkipCount; /*0x18 */
100 U32 DataLength; /*0x1C */
101 U32 BidirectionalDataLength; /*0x20 */
102 U16 IoFlags; /*0x24 */
103 U16 EEDPFlags; /*0x26 */
104 U32 EEDPBlockSize; /*0x28 */
105 U32 SecondaryReferenceTag; /*0x2C */
106 U16 SecondaryApplicationTag; /*0x30 */
107 U16 ApplicationTagTranslationMask; /*0x32 */
108 U8 LUN[8]; /*0x34 */
109 U32 Control; /*0x3C */
110 MPI2_SCSI_IO_CDB_UNION CDB; /*0x40 */
111
112#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /*typically this is left undefined */
113 MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion;
114#endif
115
116 MPI2_SGE_IO_UNION SGL; /*0x60 */
117
118} MPI2_SCSI_IO_REQUEST, *PTR_MPI2_SCSI_IO_REQUEST,
119 Mpi2SCSIIORequest_t, *pMpi2SCSIIORequest_t;
120
121/*SCSI IO MsgFlags bits */
122
123/*MsgFlags for SenseBufferAddressSpace */
124#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C)
125#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00)
126#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04)
127#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08)
128#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C)
129
130/*SCSI IO SGLFlags bits */
131
132/*base values for Data Location Address Space */
133#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C)
134#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00)
135#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04)
136#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08)
137#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C)
138
139/*base values for Type */
140#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03)
141#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00)
142#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01)
143#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02)
144
145/*shift values for each sub-field */
146#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12)
147#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8)
148#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4)
149#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0)
150
151/*number of SGLOffset fields */
152#define MPI2_SCSIIO_NUM_SGLOFFSETS (4)
153
154/*SCSI IO IoFlags bits */
155
156/*Large CDB Address Space */
157#define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000)
158#define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000)
159#define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000)
160#define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000)
161#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000)
162
163#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000)
164#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800)
165#define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400)
166#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200)
167#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF)
168
169/*SCSI IO EEDPFlags bits */
170
171#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
172#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000)
173#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000)
174#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000)
175
176#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400)
177#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200)
178#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
179
180#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008)
181
182#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007)
183#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000)
184#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001)
185#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002)
186#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003)
187#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
188#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006)
189#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007)
190
191/*SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */
192
193/*SCSI IO Control bits */
194#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000)
195#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26)
196
197#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000)
198#define MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION (24)
199#define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000)
200#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000)
201#define MPI2_SCSIIO_CONTROL_READ (0x02000000)
202#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000)
203
204#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800)
205#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11)
206/*alternate name for the previous field; called Command Priority in SAM-4 */
207#define MPI2_SCSIIO_CONTROL_CMDPRI_MASK (0x00007800)
208#define MPI2_SCSIIO_CONTROL_CMDPRI_SHIFT (11)
209
210#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700)
211#define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000)
212#define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100)
213#define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200)
214#define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400)
215
216#define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0)
217#define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000)
218#define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040)
219#define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080)
220
221/*MPI v2.5 CDB field */
222typedef union _MPI25_SCSI_IO_CDB_UNION {
223 U8 CDB32[32];
224 MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
225 MPI2_IEEE_SGE_SIMPLE64 SGE;
226} MPI25_SCSI_IO_CDB_UNION, *PTR_MPI25_SCSI_IO_CDB_UNION,
227 Mpi25ScsiIoCdb_t, *pMpi25ScsiIoCdb_t;
228
229/*MPI v2.5 SCSI IO Request Message */
230typedef struct _MPI25_SCSI_IO_REQUEST {
231 U16 DevHandle; /*0x00 */
232 U8 ChainOffset; /*0x02 */
233 U8 Function; /*0x03 */
234 U16 Reserved1; /*0x04 */
235 U8 Reserved2; /*0x06 */
236 U8 MsgFlags; /*0x07 */
237 U8 VP_ID; /*0x08 */
238 U8 VF_ID; /*0x09 */
239 U16 Reserved3; /*0x0A */
240 U32 SenseBufferLowAddress; /*0x0C */
241 U8 DMAFlags; /*0x10 */
242 U8 Reserved5; /*0x11 */
243 U8 SenseBufferLength; /*0x12 */
244 U8 Reserved4; /*0x13 */
245 U8 SGLOffset0; /*0x14 */
246 U8 SGLOffset1; /*0x15 */
247 U8 SGLOffset2; /*0x16 */
248 U8 SGLOffset3; /*0x17 */
249 U32 SkipCount; /*0x18 */
250 U32 DataLength; /*0x1C */
251 U32 BidirectionalDataLength; /*0x20 */
252 U16 IoFlags; /*0x24 */
253 U16 EEDPFlags; /*0x26 */
254 U16 EEDPBlockSize; /*0x28 */
255 U16 Reserved6; /*0x2A */
256 U32 SecondaryReferenceTag; /*0x2C */
257 U16 SecondaryApplicationTag; /*0x30 */
258 U16 ApplicationTagTranslationMask; /*0x32 */
259 U8 LUN[8]; /*0x34 */
260 U32 Control; /*0x3C */
261 MPI25_SCSI_IO_CDB_UNION CDB; /*0x40 */
262
263#ifdef MPI25_SCSI_IO_VENDOR_UNIQUE_REGION /*typically this is left undefined */
264 MPI25_SCSI_IO_VENDOR_UNIQUE VendorRegion;
265#endif
266
267 MPI25_SGE_IO_UNION SGL; /*0x60 */
268
269} MPI25_SCSI_IO_REQUEST, *PTR_MPI25_SCSI_IO_REQUEST,
270 Mpi25SCSIIORequest_t, *pMpi25SCSIIORequest_t;
271
272/*use MPI2_SCSIIO_MSGFLAGS_ defines for the MsgFlags field */
273
274/*Defines for the DMAFlags field
275 * Each setting affects 4 SGLS, from SGL0 to SGL3.
276 * D = Data
277 * C = Cache DIF
278 * I = Interleaved
279 * H = Host DIF
280 */
281#define MPI25_SCSIIO_DMAFLAGS_OP_MASK (0x0F)
282#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_D (0x00)
283#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_C (0x01)
284#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_I (0x02)
285#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_C (0x03)
286#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_I (0x04)
287#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_I_I (0x05)
288#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_C (0x06)
289#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_I (0x07)
290#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_I_I (0x08)
291#define MPI25_SCSIIO_DMAFLAGS_OP_D_I_I_I (0x09)
292#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_D (0x0A)
293#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_C (0x0B)
294#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_I (0x0C)
295#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_C (0x0D)
296#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_I (0x0E)
297#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_I_I (0x0F)
298
299/*number of SGLOffset fields */
300#define MPI25_SCSIIO_NUM_SGLOFFSETS (4)
301
302/*defines for the IoFlags field */
303#define MPI25_SCSIIO_IOFLAGS_IO_PATH_MASK (0xC000)
304#define MPI25_SCSIIO_IOFLAGS_NORMAL_PATH (0x0000)
305#define MPI25_SCSIIO_IOFLAGS_FAST_PATH (0x4000)
306
307#define MPI25_SCSIIO_IOFLAGS_LARGE_CDB (0x1000)
308#define MPI25_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800)
309#define MPI25_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF)
310
311/*MPI v2.5 defines for the EEDPFlags bits */
312/*use MPI2_SCSIIO_EEDPFLAGS_ defines for the other EEDPFlags bits */
313#define MPI25_SCSIIO_EEDPFLAGS_ESCAPE_MODE_MASK (0x00C0)
314#define MPI25_SCSIIO_EEDPFLAGS_COMPATIBLE_MODE (0x0000)
315#define MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE (0x0040)
316#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE (0x0080)
317#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_REFTAG_DISABLE_MODE (0x00C0)
318
319#define MPI25_SCSIIO_EEDPFLAGS_HOST_GUARD_METHOD_MASK (0x0030)
320#define MPI25_SCSIIO_EEDPFLAGS_T10_CRC_HOST_GUARD (0x0000)
321#define MPI25_SCSIIO_EEDPFLAGS_IP_CHKSUM_HOST_GUARD (0x0010)
322
323/*use MPI2_LUN_ defines from mpi2.h for the LUN field */
324
325/*use MPI2_SCSIIO_CONTROL_ defines for the Control field */
326
327/*NOTE: The SCSI IO Reply is nearly the same for MPI 2.0 and MPI 2.5, so
328 * MPI2_SCSI_IO_REPLY is used for both.
329 */
330
331/*SCSI IO Error Reply Message */
332typedef struct _MPI2_SCSI_IO_REPLY {
333 U16 DevHandle; /*0x00 */
334 U8 MsgLength; /*0x02 */
335 U8 Function; /*0x03 */
336 U16 Reserved1; /*0x04 */
337 U8 Reserved2; /*0x06 */
338 U8 MsgFlags; /*0x07 */
339 U8 VP_ID; /*0x08 */
340 U8 VF_ID; /*0x09 */
341 U16 Reserved3; /*0x0A */
342 U8 SCSIStatus; /*0x0C */
343 U8 SCSIState; /*0x0D */
344 U16 IOCStatus; /*0x0E */
345 U32 IOCLogInfo; /*0x10 */
346 U32 TransferCount; /*0x14 */
347 U32 SenseCount; /*0x18 */
348 U32 ResponseInfo; /*0x1C */
349 U16 TaskTag; /*0x20 */
350 U16 Reserved4; /*0x22 */
351 U32 BidirectionalTransferCount; /*0x24 */
352 U32 EEDPErrorOffset; /*0x28 *//*MPI 2.5 only; Reserved in MPI 2.0*/
353 U32 Reserved6; /*0x2C */
354} MPI2_SCSI_IO_REPLY, *PTR_MPI2_SCSI_IO_REPLY,
355 Mpi2SCSIIOReply_t, *pMpi2SCSIIOReply_t;
356
357/*SCSI IO Reply SCSIStatus values (SAM-4 status codes) */
358
359#define MPI2_SCSI_STATUS_GOOD (0x00)
360#define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02)
361#define MPI2_SCSI_STATUS_CONDITION_MET (0x04)
362#define MPI2_SCSI_STATUS_BUSY (0x08)
363#define MPI2_SCSI_STATUS_INTERMEDIATE (0x10)
364#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14)
365#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18)
366#define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /*obsolete */
367#define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28)
368#define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30)
369#define MPI2_SCSI_STATUS_TASK_ABORTED (0x40)
370
371/*SCSI IO Reply SCSIState flags */
372
373#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10)
374#define MPI2_SCSI_STATE_TERMINATED (0x08)
375#define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04)
376#define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02)
377#define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01)
378
379/*masks and shifts for the ResponseInfo field */
380
381#define MPI2_SCSI_RI_MASK_REASONCODE (0x000000FF)
382#define MPI2_SCSI_RI_SHIFT_REASONCODE (0)
383
384#define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF)
385
386/****************************************************************************
387* SCSI Task Management messages
388****************************************************************************/
389
390/*SCSI Task Management Request Message */
391typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST {
392 U16 DevHandle; /*0x00 */
393 U8 ChainOffset; /*0x02 */
394 U8 Function; /*0x03 */
395 U8 Reserved1; /*0x04 */
396 U8 TaskType; /*0x05 */
397 U8 Reserved2; /*0x06 */
398 U8 MsgFlags; /*0x07 */
399 U8 VP_ID; /*0x08 */
400 U8 VF_ID; /*0x09 */
401 U16 Reserved3; /*0x0A */
402 U8 LUN[8]; /*0x0C */
403 U32 Reserved4[7]; /*0x14 */
404 U16 TaskMID; /*0x30 */
405 U16 Reserved5; /*0x32 */
406} MPI2_SCSI_TASK_MANAGE_REQUEST,
407 *PTR_MPI2_SCSI_TASK_MANAGE_REQUEST,
408 Mpi2SCSITaskManagementRequest_t,
409 *pMpi2SCSITaskManagementRequest_t;
410
411/*TaskType values */
412
413#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01)
414#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02)
415#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03)
416#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
417#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
418#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
419#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08)
420#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09)
421#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT (0x0A)
422
423/*obsolete TaskType name */
424#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION \
425 (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT)
426
427/*MsgFlags bits */
428
429#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18)
430#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00)
431#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08)
432#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10)
433
434#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01)
435
436/*SCSI Task Management Reply Message */
437typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY {
438 U16 DevHandle; /*0x00 */
439 U8 MsgLength; /*0x02 */
440 U8 Function; /*0x03 */
441 U8 ResponseCode; /*0x04 */
442 U8 TaskType; /*0x05 */
443 U8 Reserved1; /*0x06 */
444 U8 MsgFlags; /*0x07 */
445 U8 VP_ID; /*0x08 */
446 U8 VF_ID; /*0x09 */
447 U16 Reserved2; /*0x0A */
448 U16 Reserved3; /*0x0C */
449 U16 IOCStatus; /*0x0E */
450 U32 IOCLogInfo; /*0x10 */
451 U32 TerminationCount; /*0x14 */
452 U32 ResponseInfo; /*0x18 */
453} MPI2_SCSI_TASK_MANAGE_REPLY,
454 *PTR_MPI2_SCSI_TASK_MANAGE_REPLY,
455 Mpi2SCSITaskManagementReply_t, *pMpi2SCSIManagementReply_t;
456
457/*ResponseCode values */
458
459#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00)
460#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02)
461#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04)
462#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05)
463#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08)
464#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09)
465#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG (0x0A)
466#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80)
467
468/*masks and shifts for the ResponseInfo field */
469
470#define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE (0x000000FF)
471#define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE (0)
472#define MPI2_SCSITASKMGMT_RI_MASK_ARI2 (0x0000FF00)
473#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2 (8)
474#define MPI2_SCSITASKMGMT_RI_MASK_ARI1 (0x00FF0000)
475#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1 (16)
476#define MPI2_SCSITASKMGMT_RI_MASK_ARI0 (0xFF000000)
477#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0 (24)
478
479/****************************************************************************
480* SCSI Enclosure Processor messages
481****************************************************************************/
482
483/*SCSI Enclosure Processor Request Message */
484typedef struct _MPI2_SEP_REQUEST {
485 U16 DevHandle; /*0x00 */
486 U8 ChainOffset; /*0x02 */
487 U8 Function; /*0x03 */
488 U8 Action; /*0x04 */
489 U8 Flags; /*0x05 */
490 U8 Reserved1; /*0x06 */
491 U8 MsgFlags; /*0x07 */
492 U8 VP_ID; /*0x08 */
493 U8 VF_ID; /*0x09 */
494 U16 Reserved2; /*0x0A */
495 U32 SlotStatus; /*0x0C */
496 U32 Reserved3; /*0x10 */
497 U32 Reserved4; /*0x14 */
498 U32 Reserved5; /*0x18 */
499 U16 Slot; /*0x1C */
500 U16 EnclosureHandle; /*0x1E */
501} MPI2_SEP_REQUEST, *PTR_MPI2_SEP_REQUEST,
502 Mpi2SepRequest_t, *pMpi2SepRequest_t;
503
504/*Action defines */
505#define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00)
506#define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01)
507
508/*Flags defines */
509#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00)
510#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01)
511
512/*SlotStatus defines */
513#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000)
514#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
515#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
516#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100)
517#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080)
518#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040)
519#define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010)
520#define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008)
521#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004)
522#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002)
523#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001)
524
525/*SCSI Enclosure Processor Reply Message */
526typedef struct _MPI2_SEP_REPLY {
527 U16 DevHandle; /*0x00 */
528 U8 MsgLength; /*0x02 */
529 U8 Function; /*0x03 */
530 U8 Action; /*0x04 */
531 U8 Flags; /*0x05 */
532 U8 Reserved1; /*0x06 */
533 U8 MsgFlags; /*0x07 */
534 U8 VP_ID; /*0x08 */
535 U8 VF_ID; /*0x09 */
536 U16 Reserved2; /*0x0A */
537 U16 Reserved3; /*0x0C */
538 U16 IOCStatus; /*0x0E */
539 U32 IOCLogInfo; /*0x10 */
540 U32 SlotStatus; /*0x14 */
541 U32 Reserved4; /*0x18 */
542 U16 Slot; /*0x1C */
543 U16 EnclosureHandle; /*0x1E */
544} MPI2_SEP_REPLY, *PTR_MPI2_SEP_REPLY,
545 Mpi2SepReply_t, *pMpi2SepReply_t;
546
547/*SlotStatus defines */
548#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000)
549#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
550#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
551#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100)
552#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080)
553#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040)
554#define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010)
555#define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008)
556#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004)
557#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002)
558#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001)
559
560#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
new file mode 100644
index 000000000000..0de425d8fd70
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
@@ -0,0 +1,1665 @@
1/*
2 * Copyright (c) 2000-2012 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.21
10 *
11 * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
12 * prefix are for use only on MPI v2.5 products, and must not be used
13 * with MPI v2.0 products. Unless otherwise noted, names beginning with
14 * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
15 *
16 * Version History
17 * ---------------
18 *
19 * Date Version Description
20 * -------- -------- ------------------------------------------------------
21 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
22 * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to
23 * MaxTargets.
24 * Added TotalImageSize field to FWDownload Request.
25 * Added reserved words to FWUpload Request.
26 * 06-26-07 02.00.02 Added IR Configuration Change List Event.
27 * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit
28 * request and replaced it with
29 * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
30 * Replaced the MinReplyQueueDepth field of the IOCFacts
31 * reply with MaxReplyDescriptorPostQueueDepth.
32 * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
33 * depth for the Reply Descriptor Post Queue.
34 * Added SASAddress field to Initiator Device Table
35 * Overflow Event data.
36 * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
37 * for SAS Initiator Device Status Change Event data.
38 * Modified Reason Code defines for SAS Topology Change
39 * List Event data, including adding a bit for PHY Vacant
40 * status, and adding a mask for the Reason Code.
41 * Added define for
42 * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
43 * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
44 * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of
45 * the IOCFacts Reply.
46 * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
47 * Moved MPI2_VERSION_UNION to mpi2.h.
48 * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
49 * instead of enables, and added SASBroadcastPrimitiveMasks
50 * field.
51 * Added Log Entry Added Event and related structure.
52 * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
53 * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
54 * Added MaxVolumes and MaxPersistentEntries fields to
55 * IOCFacts reply.
56 * Added ProtocalFlags and IOCCapabilities fields to
57 * MPI2_FW_IMAGE_HEADER.
58 * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
59 * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
60 * a U16 (from a U32).
61 * Removed extra 's' from EventMasks name.
62 * 06-27-08 02.00.08 Fixed an offset in a comment.
63 * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
64 * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
65 * renamed MinReplyFrameSize to ReplyFrameSize.
66 * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
67 * Added two new RAIDOperation values for Integrated RAID
68 * Operations Status Event data.
69 * Added four new IR Configuration Change List Event data
70 * ReasonCode values.
71 * Added two new ReasonCode defines for SAS Device Status
72 * Change Event data.
73 * Added three new DiscoveryStatus bits for the SAS
74 * Discovery event data.
75 * Added Multiplexing Status Change bit to the PhyStatus
76 * field of the SAS Topology Change List event data.
77 * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
78 * BootFlags are now product-specific.
79 * Added defines for the indivdual signature bytes
80 * for MPI2_INIT_IMAGE_FOOTER.
81 * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
82 * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
83 * define.
84 * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
85 * define.
86 * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
87 * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
88 * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
89 * Added two new reason codes for SAS Device Status Change
90 * Event.
91 * Added new event: SAS PHY Counter.
92 * 07-30-09 02.00.12 Added GPIO Interrupt event define and structure.
93 * Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
94 * Added new product id family for 2208.
95 * 10-28-09 02.00.13 Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST.
96 * Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY.
97 * Added MinDevHandle field to MPI2_IOC_FACTS_REPLY.
98 * Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY.
99 * Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define.
100 * Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define.
101 * Added Host Based Discovery Phy Event data.
102 * Added defines for ProductID Product field
103 * (MPI2_FW_HEADER_PID_).
104 * Modified values for SAS ProductID Family
105 * (MPI2_FW_HEADER_PID_FAMILY_).
106 * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines.
107 * Added PowerManagementControl Request structures and
108 * defines.
109 * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete.
110 * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
111 * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
112 * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added
113 * SASNotifyPrimitiveMasks field to
114 * MPI2_EVENT_NOTIFICATION_REQUEST.
115 * Added Temperature Threshold Event.
116 * Added Host Message Event.
117 * Added Send Host Message request and reply.
118 * 05-25-11 02.00.18 For Extended Image Header, added
119 * MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and
120 * MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines.
121 * Deprecated MPI2_EXT_IMAGE_TYPE_MAX define.
122 * 08-24-11 02.00.19 Added PhysicalPort field to
123 * MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure.
124 * Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete.
125 * 11-18-11 02.00.20 Incorporating additions for MPI v2.5.
126 * 03-29-12 02.00.21 Added a product specific range to event values.
127 * --------------------------------------------------------------------------
128 */
129
130#ifndef MPI2_IOC_H
131#define MPI2_IOC_H
132
133/*****************************************************************************
134*
135* IOC Messages
136*
137*****************************************************************************/
138
139/****************************************************************************
140* IOCInit message
141****************************************************************************/
142
143/*IOCInit Request message */
144typedef struct _MPI2_IOC_INIT_REQUEST {
145 U8 WhoInit; /*0x00 */
146 U8 Reserved1; /*0x01 */
147 U8 ChainOffset; /*0x02 */
148 U8 Function; /*0x03 */
149 U16 Reserved2; /*0x04 */
150 U8 Reserved3; /*0x06 */
151 U8 MsgFlags; /*0x07 */
152 U8 VP_ID; /*0x08 */
153 U8 VF_ID; /*0x09 */
154 U16 Reserved4; /*0x0A */
155 U16 MsgVersion; /*0x0C */
156 U16 HeaderVersion; /*0x0E */
157 U32 Reserved5; /*0x10 */
158 U16 Reserved6; /*0x14 */
159 U8 Reserved7; /*0x16 */
160 U8 HostMSIxVectors; /*0x17 */
161 U16 Reserved8; /*0x18 */
162 U16 SystemRequestFrameSize; /*0x1A */
163 U16 ReplyDescriptorPostQueueDepth; /*0x1C */
164 U16 ReplyFreeQueueDepth; /*0x1E */
165 U32 SenseBufferAddressHigh; /*0x20 */
166 U32 SystemReplyAddressHigh; /*0x24 */
167 U64 SystemRequestFrameBaseAddress; /*0x28 */
168 U64 ReplyDescriptorPostQueueAddress; /*0x30 */
169 U64 ReplyFreeQueueAddress; /*0x38 */
170 U64 TimeStamp; /*0x40 */
171} MPI2_IOC_INIT_REQUEST, *PTR_MPI2_IOC_INIT_REQUEST,
172 Mpi2IOCInitRequest_t, *pMpi2IOCInitRequest_t;
173
174/*WhoInit values */
175#define MPI2_WHOINIT_NOT_INITIALIZED (0x00)
176#define MPI2_WHOINIT_SYSTEM_BIOS (0x01)
177#define MPI2_WHOINIT_ROM_BIOS (0x02)
178#define MPI2_WHOINIT_PCI_PEER (0x03)
179#define MPI2_WHOINIT_HOST_DRIVER (0x04)
180#define MPI2_WHOINIT_MANUFACTURER (0x05)
181
182/*MsgVersion */
183#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00)
184#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8)
185#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF)
186#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0)
187
188/*HeaderVersion */
189#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00)
190#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8)
191#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF)
192#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0)
193
194/*minimum depth for the Reply Descriptor Post Queue */
195#define MPI2_RDPQ_DEPTH_MIN (16)
196
197/*IOCInit Reply message */
198typedef struct _MPI2_IOC_INIT_REPLY {
199 U8 WhoInit; /*0x00 */
200 U8 Reserved1; /*0x01 */
201 U8 MsgLength; /*0x02 */
202 U8 Function; /*0x03 */
203 U16 Reserved2; /*0x04 */
204 U8 Reserved3; /*0x06 */
205 U8 MsgFlags; /*0x07 */
206 U8 VP_ID; /*0x08 */
207 U8 VF_ID; /*0x09 */
208 U16 Reserved4; /*0x0A */
209 U16 Reserved5; /*0x0C */
210 U16 IOCStatus; /*0x0E */
211 U32 IOCLogInfo; /*0x10 */
212} MPI2_IOC_INIT_REPLY, *PTR_MPI2_IOC_INIT_REPLY,
213 Mpi2IOCInitReply_t, *pMpi2IOCInitReply_t;
214
215/****************************************************************************
216* IOCFacts message
217****************************************************************************/
218
219/*IOCFacts Request message */
220typedef struct _MPI2_IOC_FACTS_REQUEST {
221 U16 Reserved1; /*0x00 */
222 U8 ChainOffset; /*0x02 */
223 U8 Function; /*0x03 */
224 U16 Reserved2; /*0x04 */
225 U8 Reserved3; /*0x06 */
226 U8 MsgFlags; /*0x07 */
227 U8 VP_ID; /*0x08 */
228 U8 VF_ID; /*0x09 */
229 U16 Reserved4; /*0x0A */
230} MPI2_IOC_FACTS_REQUEST, *PTR_MPI2_IOC_FACTS_REQUEST,
231 Mpi2IOCFactsRequest_t, *pMpi2IOCFactsRequest_t;
232
233/*IOCFacts Reply message */
234typedef struct _MPI2_IOC_FACTS_REPLY {
235 U16 MsgVersion; /*0x00 */
236 U8 MsgLength; /*0x02 */
237 U8 Function; /*0x03 */
238 U16 HeaderVersion; /*0x04 */
239 U8 IOCNumber; /*0x06 */
240 U8 MsgFlags; /*0x07 */
241 U8 VP_ID; /*0x08 */
242 U8 VF_ID; /*0x09 */
243 U16 Reserved1; /*0x0A */
244 U16 IOCExceptions; /*0x0C */
245 U16 IOCStatus; /*0x0E */
246 U32 IOCLogInfo; /*0x10 */
247 U8 MaxChainDepth; /*0x14 */
248 U8 WhoInit; /*0x15 */
249 U8 NumberOfPorts; /*0x16 */
250 U8 MaxMSIxVectors; /*0x17 */
251 U16 RequestCredit; /*0x18 */
252 U16 ProductID; /*0x1A */
253 U32 IOCCapabilities; /*0x1C */
254 MPI2_VERSION_UNION FWVersion; /*0x20 */
255 U16 IOCRequestFrameSize; /*0x24 */
256 U16 IOCMaxChainSegmentSize; /*0x26 */
257 U16 MaxInitiators; /*0x28 */
258 U16 MaxTargets; /*0x2A */
259 U16 MaxSasExpanders; /*0x2C */
260 U16 MaxEnclosures; /*0x2E */
261 U16 ProtocolFlags; /*0x30 */
262 U16 HighPriorityCredit; /*0x32 */
263 U16 MaxReplyDescriptorPostQueueDepth; /*0x34 */
264 U8 ReplyFrameSize; /*0x36 */
265 U8 MaxVolumes; /*0x37 */
266 U16 MaxDevHandle; /*0x38 */
267 U16 MaxPersistentEntries; /*0x3A */
268 U16 MinDevHandle; /*0x3C */
269 U16 Reserved4; /*0x3E */
270} MPI2_IOC_FACTS_REPLY, *PTR_MPI2_IOC_FACTS_REPLY,
271 Mpi2IOCFactsReply_t, *pMpi2IOCFactsReply_t;
272
273/*MsgVersion */
274#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00)
275#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8)
276#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF)
277#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0)
278
279/*HeaderVersion */
280#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00)
281#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8)
282#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF)
283#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0)
284
285/*IOCExceptions */
286#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100)
287
288#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0)
289#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000)
290#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020)
291#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040)
292#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060)
293
294#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010)
295#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008)
296#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
297#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
298#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001)
299
300/*defines for WhoInit field are after the IOCInit Request */
301
302/*ProductID field uses MPI2_FW_HEADER_PID_ */
303
304/*IOCCapabilities */
305#define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE (0x00020000)
306#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000)
307#define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX (0x00008000)
308#define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR (0x00004000)
309#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000)
310#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000)
311#define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800)
312#define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100)
313#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080)
314#define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040)
315#define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020)
316#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
317#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
318#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
319
320/*ProtocolFlags */
321#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001)
322#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002)
323
324/****************************************************************************
325* PortFacts message
326****************************************************************************/
327
328/*PortFacts Request message */
329typedef struct _MPI2_PORT_FACTS_REQUEST {
330 U16 Reserved1; /*0x00 */
331 U8 ChainOffset; /*0x02 */
332 U8 Function; /*0x03 */
333 U16 Reserved2; /*0x04 */
334 U8 PortNumber; /*0x06 */
335 U8 MsgFlags; /*0x07 */
336 U8 VP_ID; /*0x08 */
337 U8 VF_ID; /*0x09 */
338 U16 Reserved3; /*0x0A */
339} MPI2_PORT_FACTS_REQUEST, *PTR_MPI2_PORT_FACTS_REQUEST,
340 Mpi2PortFactsRequest_t, *pMpi2PortFactsRequest_t;
341
342/*PortFacts Reply message */
343typedef struct _MPI2_PORT_FACTS_REPLY {
344 U16 Reserved1; /*0x00 */
345 U8 MsgLength; /*0x02 */
346 U8 Function; /*0x03 */
347 U16 Reserved2; /*0x04 */
348 U8 PortNumber; /*0x06 */
349 U8 MsgFlags; /*0x07 */
350 U8 VP_ID; /*0x08 */
351 U8 VF_ID; /*0x09 */
352 U16 Reserved3; /*0x0A */
353 U16 Reserved4; /*0x0C */
354 U16 IOCStatus; /*0x0E */
355 U32 IOCLogInfo; /*0x10 */
356 U8 Reserved5; /*0x14 */
357 U8 PortType; /*0x15 */
358 U16 Reserved6; /*0x16 */
359 U16 MaxPostedCmdBuffers; /*0x18 */
360 U16 Reserved7; /*0x1A */
361} MPI2_PORT_FACTS_REPLY, *PTR_MPI2_PORT_FACTS_REPLY,
362 Mpi2PortFactsReply_t, *pMpi2PortFactsReply_t;
363
364/*PortType values */
365#define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00)
366#define MPI2_PORTFACTS_PORTTYPE_FC (0x10)
367#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20)
368#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30)
369#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31)
370
371/****************************************************************************
372* PortEnable message
373****************************************************************************/
374
375/*PortEnable Request message */
376typedef struct _MPI2_PORT_ENABLE_REQUEST {
377 U16 Reserved1; /*0x00 */
378 U8 ChainOffset; /*0x02 */
379 U8 Function; /*0x03 */
380 U8 Reserved2; /*0x04 */
381 U8 PortFlags; /*0x05 */
382 U8 Reserved3; /*0x06 */
383 U8 MsgFlags; /*0x07 */
384 U8 VP_ID; /*0x08 */
385 U8 VF_ID; /*0x09 */
386 U16 Reserved4; /*0x0A */
387} MPI2_PORT_ENABLE_REQUEST, *PTR_MPI2_PORT_ENABLE_REQUEST,
388 Mpi2PortEnableRequest_t, *pMpi2PortEnableRequest_t;
389
390/*PortEnable Reply message */
391typedef struct _MPI2_PORT_ENABLE_REPLY {
392 U16 Reserved1; /*0x00 */
393 U8 MsgLength; /*0x02 */
394 U8 Function; /*0x03 */
395 U8 Reserved2; /*0x04 */
396 U8 PortFlags; /*0x05 */
397 U8 Reserved3; /*0x06 */
398 U8 MsgFlags; /*0x07 */
399 U8 VP_ID; /*0x08 */
400 U8 VF_ID; /*0x09 */
401 U16 Reserved4; /*0x0A */
402 U16 Reserved5; /*0x0C */
403 U16 IOCStatus; /*0x0E */
404 U32 IOCLogInfo; /*0x10 */
405} MPI2_PORT_ENABLE_REPLY, *PTR_MPI2_PORT_ENABLE_REPLY,
406 Mpi2PortEnableReply_t, *pMpi2PortEnableReply_t;
407
408/****************************************************************************
409* EventNotification message
410****************************************************************************/
411
412/*EventNotification Request message */
413#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4)
414
415typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST {
416 U16 Reserved1; /*0x00 */
417 U8 ChainOffset; /*0x02 */
418 U8 Function; /*0x03 */
419 U16 Reserved2; /*0x04 */
420 U8 Reserved3; /*0x06 */
421 U8 MsgFlags; /*0x07 */
422 U8 VP_ID; /*0x08 */
423 U8 VF_ID; /*0x09 */
424 U16 Reserved4; /*0x0A */
425 U32 Reserved5; /*0x0C */
426 U32 Reserved6; /*0x10 */
427 U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; /*0x14 */
428 U16 SASBroadcastPrimitiveMasks; /*0x24 */
429 U16 SASNotifyPrimitiveMasks; /*0x26 */
430 U32 Reserved8; /*0x28 */
431} MPI2_EVENT_NOTIFICATION_REQUEST,
432 *PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
433 Mpi2EventNotificationRequest_t,
434 *pMpi2EventNotificationRequest_t;
435
436/*EventNotification Reply message */
437typedef struct _MPI2_EVENT_NOTIFICATION_REPLY {
438 U16 EventDataLength; /*0x00 */
439 U8 MsgLength; /*0x02 */
440 U8 Function; /*0x03 */
441 U16 Reserved1; /*0x04 */
442 U8 AckRequired; /*0x06 */
443 U8 MsgFlags; /*0x07 */
444 U8 VP_ID; /*0x08 */
445 U8 VF_ID; /*0x09 */
446 U16 Reserved2; /*0x0A */
447 U16 Reserved3; /*0x0C */
448 U16 IOCStatus; /*0x0E */
449 U32 IOCLogInfo; /*0x10 */
450 U16 Event; /*0x14 */
451 U16 Reserved4; /*0x16 */
452 U32 EventContext; /*0x18 */
453 U32 EventData[1]; /*0x1C */
454} MPI2_EVENT_NOTIFICATION_REPLY, *PTR_MPI2_EVENT_NOTIFICATION_REPLY,
455 Mpi2EventNotificationReply_t,
456 *pMpi2EventNotificationReply_t;
457
458/*AckRequired */
459#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00)
460#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01)
461
462/*Event */
463#define MPI2_EVENT_LOG_DATA (0x0001)
464#define MPI2_EVENT_STATE_CHANGE (0x0002)
465#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005)
466#define MPI2_EVENT_EVENT_CHANGE (0x000A)
467#define MPI2_EVENT_TASK_SET_FULL (0x000E) /*obsolete */
468#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F)
469#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014)
470#define MPI2_EVENT_SAS_DISCOVERY (0x0016)
471#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017)
472#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018)
473#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019)
474#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C)
475#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D)
476#define MPI2_EVENT_IR_VOLUME (0x001E)
477#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F)
478#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020)
479#define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021)
480#define MPI2_EVENT_SAS_PHY_COUNTER (0x0022)
481#define MPI2_EVENT_GPIO_INTERRUPT (0x0023)
482#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024)
483#define MPI2_EVENT_SAS_QUIESCE (0x0025)
484#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE (0x0026)
485#define MPI2_EVENT_TEMP_THRESHOLD (0x0027)
486#define MPI2_EVENT_HOST_MESSAGE (0x0028)
487#define MPI2_EVENT_POWER_PERFORMANCE_CHANGE (0x0029)
488#define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E)
489#define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F)
490
491/*Log Entry Added Event data */
492
493/*the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */
494#define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C)
495
496typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED {
497 U64 TimeStamp; /*0x00 */
498 U32 Reserved1; /*0x08 */
499 U16 LogSequence; /*0x0C */
500 U16 LogEntryQualifier; /*0x0E */
501 U8 VP_ID; /*0x10 */
502 U8 VF_ID; /*0x11 */
503 U16 Reserved2; /*0x12 */
504 U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH]; /*0x14 */
505} MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
506 *PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
507 Mpi2EventDataLogEntryAdded_t,
508 *pMpi2EventDataLogEntryAdded_t;
509
510/*GPIO Interrupt Event data */
511
512typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT {
513 U8 GPIONum; /*0x00 */
514 U8 Reserved1; /*0x01 */
515 U16 Reserved2; /*0x02 */
516} MPI2_EVENT_DATA_GPIO_INTERRUPT,
517 *PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT,
518 Mpi2EventDataGpioInterrupt_t,
519 *pMpi2EventDataGpioInterrupt_t;
520
521/*Temperature Threshold Event data */
522
523typedef struct _MPI2_EVENT_DATA_TEMPERATURE {
524 U16 Status; /*0x00 */
525 U8 SensorNum; /*0x02 */
526 U8 Reserved1; /*0x03 */
527 U16 CurrentTemperature; /*0x04 */
528 U16 Reserved2; /*0x06 */
529 U32 Reserved3; /*0x08 */
530 U32 Reserved4; /*0x0C */
531} MPI2_EVENT_DATA_TEMPERATURE,
532 *PTR_MPI2_EVENT_DATA_TEMPERATURE,
533 Mpi2EventDataTemperature_t, *pMpi2EventDataTemperature_t;
534
535/*Temperature Threshold Event data Status bits */
536#define MPI2_EVENT_TEMPERATURE3_EXCEEDED (0x0008)
537#define MPI2_EVENT_TEMPERATURE2_EXCEEDED (0x0004)
538#define MPI2_EVENT_TEMPERATURE1_EXCEEDED (0x0002)
539#define MPI2_EVENT_TEMPERATURE0_EXCEEDED (0x0001)
540
541/*Host Message Event data */
542
543typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE {
544 U8 SourceVF_ID; /*0x00 */
545 U8 Reserved1; /*0x01 */
546 U16 Reserved2; /*0x02 */
547 U32 Reserved3; /*0x04 */
548 U32 HostData[1]; /*0x08 */
549} MPI2_EVENT_DATA_HOST_MESSAGE, *PTR_MPI2_EVENT_DATA_HOST_MESSAGE,
550 Mpi2EventDataHostMessage_t, *pMpi2EventDataHostMessage_t;
551
552/*Power Performance Change Event */
553
554typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE {
555 U8 CurrentPowerMode; /*0x00 */
556 U8 PreviousPowerMode; /*0x01 */
557 U16 Reserved1; /*0x02 */
558} MPI2_EVENT_DATA_POWER_PERF_CHANGE,
559 *PTR_MPI2_EVENT_DATA_POWER_PERF_CHANGE,
560 Mpi2EventDataPowerPerfChange_t,
561 *pMpi2EventDataPowerPerfChange_t;
562
563/*defines for CurrentPowerMode and PreviousPowerMode fields */
564#define MPI2_EVENT_PM_INIT_MASK (0xC0)
565#define MPI2_EVENT_PM_INIT_UNAVAILABLE (0x00)
566#define MPI2_EVENT_PM_INIT_HOST (0x40)
567#define MPI2_EVENT_PM_INIT_IO_UNIT (0x80)
568#define MPI2_EVENT_PM_INIT_PCIE_DPA (0xC0)
569
570#define MPI2_EVENT_PM_MODE_MASK (0x07)
571#define MPI2_EVENT_PM_MODE_UNAVAILABLE (0x00)
572#define MPI2_EVENT_PM_MODE_UNKNOWN (0x01)
573#define MPI2_EVENT_PM_MODE_FULL_POWER (0x04)
574#define MPI2_EVENT_PM_MODE_REDUCED_POWER (0x05)
575#define MPI2_EVENT_PM_MODE_STANDBY (0x06)
576
577/*Hard Reset Received Event data */
578
579typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED {
580 U8 Reserved1; /*0x00 */
581 U8 Port; /*0x01 */
582 U16 Reserved2; /*0x02 */
583} MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
584 *PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
585 Mpi2EventDataHardResetReceived_t,
586 *pMpi2EventDataHardResetReceived_t;
587
588/*Task Set Full Event data */
589/* this event is obsolete */
590
591typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL {
592 U16 DevHandle; /*0x00 */
593 U16 CurrentDepth; /*0x02 */
594} MPI2_EVENT_DATA_TASK_SET_FULL, *PTR_MPI2_EVENT_DATA_TASK_SET_FULL,
595 Mpi2EventDataTaskSetFull_t, *pMpi2EventDataTaskSetFull_t;
596
597/*SAS Device Status Change Event data */
598
599typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE {
600 U16 TaskTag; /*0x00 */
601 U8 ReasonCode; /*0x02 */
602 U8 PhysicalPort; /*0x03 */
603 U8 ASC; /*0x04 */
604 U8 ASCQ; /*0x05 */
605 U16 DevHandle; /*0x06 */
606 U32 Reserved2; /*0x08 */
607 U64 SASAddress; /*0x0C */
608 U8 LUN[8]; /*0x14 */
609} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
610 *PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
611 Mpi2EventDataSasDeviceStatusChange_t,
612 *pMpi2EventDataSasDeviceStatusChange_t;
613
614/*SAS Device Status Change Event data ReasonCode values */
615#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
616#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
617#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
618#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09)
619#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A)
620#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
621#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
622#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
623#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E)
624#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F)
625#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10)
626#define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY (0x11)
627#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY (0x12)
628
629/*Integrated RAID Operation Status Event data */
630
631typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS {
632 U16 VolDevHandle; /*0x00 */
633 U16 Reserved1; /*0x02 */
634 U8 RAIDOperation; /*0x04 */
635 U8 PercentComplete; /*0x05 */
636 U16 Reserved2; /*0x06 */
637 U32 Resereved3; /*0x08 */
638} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
639 *PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
640 Mpi2EventDataIrOperationStatus_t,
641 *pMpi2EventDataIrOperationStatus_t;
642
643/*Integrated RAID Operation Status Event data RAIDOperation values */
644#define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00)
645#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01)
646#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02)
647#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03)
648#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04)
649
650/*Integrated RAID Volume Event data */
651
652typedef struct _MPI2_EVENT_DATA_IR_VOLUME {
653 U16 VolDevHandle; /*0x00 */
654 U8 ReasonCode; /*0x02 */
655 U8 Reserved1; /*0x03 */
656 U32 NewValue; /*0x04 */
657 U32 PreviousValue; /*0x08 */
658} MPI2_EVENT_DATA_IR_VOLUME, *PTR_MPI2_EVENT_DATA_IR_VOLUME,
659 Mpi2EventDataIrVolume_t, *pMpi2EventDataIrVolume_t;
660
661/*Integrated RAID Volume Event data ReasonCode values */
662#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01)
663#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02)
664#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03)
665
666/*Integrated RAID Physical Disk Event data */
667
668typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK {
669 U16 Reserved1; /*0x00 */
670 U8 ReasonCode; /*0x02 */
671 U8 PhysDiskNum; /*0x03 */
672 U16 PhysDiskDevHandle; /*0x04 */
673 U16 Reserved2; /*0x06 */
674 U16 Slot; /*0x08 */
675 U16 EnclosureHandle; /*0x0A */
676 U32 NewValue; /*0x0C */
677 U32 PreviousValue; /*0x10 */
678} MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
679 *PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
680 Mpi2EventDataIrPhysicalDisk_t,
681 *pMpi2EventDataIrPhysicalDisk_t;
682
683/*Integrated RAID Physical Disk Event data ReasonCode values */
684#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01)
685#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02)
686#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03)
687
688/*Integrated RAID Configuration Change List Event data */
689
690/*
691 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
692 *one and check NumElements at runtime.
693 */
694#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
695#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1)
696#endif
697
698typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT {
699 U16 ElementFlags; /*0x00 */
700 U16 VolDevHandle; /*0x02 */
701 U8 ReasonCode; /*0x04 */
702 U8 PhysDiskNum; /*0x05 */
703 U16 PhysDiskDevHandle; /*0x06 */
704} MPI2_EVENT_IR_CONFIG_ELEMENT, *PTR_MPI2_EVENT_IR_CONFIG_ELEMENT,
705 Mpi2EventIrConfigElement_t, *pMpi2EventIrConfigElement_t;
706
707/*IR Configuration Change List Event data ElementFlags values */
708#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F)
709#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000)
710#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001)
711#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002)
712
713/*IR Configuration Change List Event data ReasonCode values */
714#define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01)
715#define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02)
716#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03)
717#define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04)
718#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05)
719#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06)
720#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07)
721#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08)
722#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09)
723
724typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST {
725 U8 NumElements; /*0x00 */
726 U8 Reserved1; /*0x01 */
727 U8 Reserved2; /*0x02 */
728 U8 ConfigNum; /*0x03 */
729 U32 Flags; /*0x04 */
730 MPI2_EVENT_IR_CONFIG_ELEMENT
731 ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT];/*0x08 */
732} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
733 *PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
734 Mpi2EventDataIrConfigChangeList_t,
735 *pMpi2EventDataIrConfigChangeList_t;
736
737/*IR Configuration Change List Event data Flags values */
738#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001)
739
740/*SAS Discovery Event data */
741
742typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY {
743 U8 Flags; /*0x00 */
744 U8 ReasonCode; /*0x01 */
745 U8 PhysicalPort; /*0x02 */
746 U8 Reserved1; /*0x03 */
747 U32 DiscoveryStatus; /*0x04 */
748} MPI2_EVENT_DATA_SAS_DISCOVERY,
749 *PTR_MPI2_EVENT_DATA_SAS_DISCOVERY,
750 Mpi2EventDataSasDiscovery_t, *pMpi2EventDataSasDiscovery_t;
751
752/*SAS Discovery Event data Flags values */
753#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02)
754#define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01)
755
756/*SAS Discovery Event data ReasonCode values */
757#define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01)
758#define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02)
759
760/*SAS Discovery Event data DiscoveryStatus values */
761#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
762#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000)
763#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000)
764#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
765#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000)
766#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
767#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
768#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000)
769#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
770#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800)
771#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400)
772#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200)
773#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100)
774#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080)
775#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040)
776#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020)
777#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010)
778#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004)
779#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002)
780#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001)
781
782/*SAS Broadcast Primitive Event data */
783
784typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE {
785 U8 PhyNum; /*0x00 */
786 U8 Port; /*0x01 */
787 U8 PortWidth; /*0x02 */
788 U8 Primitive; /*0x03 */
789} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
790 *PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
791 Mpi2EventDataSasBroadcastPrimitive_t,
792 *pMpi2EventDataSasBroadcastPrimitive_t;
793
794/*defines for the Primitive field */
795#define MPI2_EVENT_PRIMITIVE_CHANGE (0x01)
796#define MPI2_EVENT_PRIMITIVE_SES (0x02)
797#define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03)
798#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04)
799#define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05)
800#define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06)
801#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07)
802#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08)
803
804/*SAS Notify Primitive Event data */
805
806typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE {
807 U8 PhyNum; /*0x00 */
808 U8 Port; /*0x01 */
809 U8 Reserved1; /*0x02 */
810 U8 Primitive; /*0x03 */
811} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
812 *PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
813 Mpi2EventDataSasNotifyPrimitive_t,
814 *pMpi2EventDataSasNotifyPrimitive_t;
815
816/*defines for the Primitive field */
817#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP (0x01)
818#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED (0x02)
819#define MPI2_EVENT_NOTIFY_RESERVED1 (0x03)
820#define MPI2_EVENT_NOTIFY_RESERVED2 (0x04)
821
822/*SAS Initiator Device Status Change Event data */
823
824typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE {
825 U8 ReasonCode; /*0x00 */
826 U8 PhysicalPort; /*0x01 */
827 U16 DevHandle; /*0x02 */
828 U64 SASAddress; /*0x04 */
829} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
830 *PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
831 Mpi2EventDataSasInitDevStatusChange_t,
832 *pMpi2EventDataSasInitDevStatusChange_t;
833
834/*SAS Initiator Device Status Change event ReasonCode values */
835#define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01)
836#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02)
837
838/*SAS Initiator Device Table Overflow Event data */
839
840typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW {
841 U16 MaxInit; /*0x00 */
842 U16 CurrentInit; /*0x02 */
843 U64 SASAddress; /*0x04 */
844} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
845 *PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
846 Mpi2EventDataSasInitTableOverflow_t,
847 *pMpi2EventDataSasInitTableOverflow_t;
848
849/*SAS Topology Change List Event data */
850
851/*
852 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
853 *one and check NumEntries at runtime.
854 */
855#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
856#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1)
857#endif
858
859typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY {
860 U16 AttachedDevHandle; /*0x00 */
861 U8 LinkRate; /*0x02 */
862 U8 PhyStatus; /*0x03 */
863} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, *PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY,
864 Mpi2EventSasTopoPhyEntry_t, *pMpi2EventSasTopoPhyEntry_t;
865
866typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST {
867 U16 EnclosureHandle; /*0x00 */
868 U16 ExpanderDevHandle; /*0x02 */
869 U8 NumPhys; /*0x04 */
870 U8 Reserved1; /*0x05 */
871 U16 Reserved2; /*0x06 */
872 U8 NumEntries; /*0x08 */
873 U8 StartPhyNum; /*0x09 */
874 U8 ExpStatus; /*0x0A */
875 U8 PhysicalPort; /*0x0B */
876 MPI2_EVENT_SAS_TOPO_PHY_ENTRY
877 PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /*0x0C */
878} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
879 *PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
880 Mpi2EventDataSasTopologyChangeList_t,
881 *pMpi2EventDataSasTopologyChangeList_t;
882
883/*values for the ExpStatus field */
884#define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00)
885#define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01)
886#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02)
887#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03)
888#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04)
889
890/*defines for the LinkRate field */
891#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0)
892#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4)
893#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F)
894#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0)
895
896#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00)
897#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01)
898#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02)
899#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03)
900#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04)
901#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05)
902#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06)
903#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08)
904#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09)
905#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A)
906#define MPI25_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B)
907
908/*values for the PhyStatus field */
909#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80)
910#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10)
911/*values for the PhyStatus ReasonCode sub-field */
912#define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F)
913#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01)
914#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02)
915#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03)
916#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04)
917#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05)
918
919/*SAS Enclosure Device Status Change Event data */
920
921typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE {
922 U16 EnclosureHandle; /*0x00 */
923 U8 ReasonCode; /*0x02 */
924 U8 PhysicalPort; /*0x03 */
925 U64 EnclosureLogicalID; /*0x04 */
926 U16 NumSlots; /*0x0C */
927 U16 StartSlot; /*0x0E */
928 U32 PhyBits; /*0x10 */
929} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
930 *PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
931 Mpi2EventDataSasEnclDevStatusChange_t,
932 *pMpi2EventDataSasEnclDevStatusChange_t;
933
934/*SAS Enclosure Device Status Change event ReasonCode values */
935#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01)
936#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02)
937
938/*SAS PHY Counter Event data */
939
940typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER {
941 U64 TimeStamp; /*0x00 */
942 U32 Reserved1; /*0x08 */
943 U8 PhyEventCode; /*0x0C */
944 U8 PhyNum; /*0x0D */
945 U16 Reserved2; /*0x0E */
946 U32 PhyEventInfo; /*0x10 */
947 U8 CounterType; /*0x14 */
948 U8 ThresholdWindow; /*0x15 */
949 U8 TimeUnits; /*0x16 */
950 U8 Reserved3; /*0x17 */
951 U32 EventThreshold; /*0x18 */
952 U16 ThresholdFlags; /*0x1C */
953 U16 Reserved4; /*0x1E */
954} MPI2_EVENT_DATA_SAS_PHY_COUNTER,
955 *PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER,
956 Mpi2EventDataSasPhyCounter_t,
957 *pMpi2EventDataSasPhyCounter_t;
958
959/*use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h
960 *for the PhyEventCode field */
961
962/*use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h
963 *for the CounterType field */
964
965/*use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h
966 *for the TimeUnits field */
967
968/*use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h
969 *for the ThresholdFlags field */
970
971/*SAS Quiesce Event data */
972
973typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE {
974 U8 ReasonCode; /*0x00 */
975 U8 Reserved1; /*0x01 */
976 U16 Reserved2; /*0x02 */
977 U32 Reserved3; /*0x04 */
978} MPI2_EVENT_DATA_SAS_QUIESCE,
979 *PTR_MPI2_EVENT_DATA_SAS_QUIESCE,
980 Mpi2EventDataSasQuiesce_t, *pMpi2EventDataSasQuiesce_t;
981
982/*SAS Quiesce Event data ReasonCode values */
983#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED (0x01)
984#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED (0x02)
985
986/*Host Based Discovery Phy Event data */
987
988typedef struct _MPI2_EVENT_HBD_PHY_SAS {
989 U8 Flags; /*0x00 */
990 U8 NegotiatedLinkRate; /*0x01 */
991 U8 PhyNum; /*0x02 */
992 U8 PhysicalPort; /*0x03 */
993 U32 Reserved1; /*0x04 */
994 U8 InitialFrame[28]; /*0x08 */
995} MPI2_EVENT_HBD_PHY_SAS, *PTR_MPI2_EVENT_HBD_PHY_SAS,
996 Mpi2EventHbdPhySas_t, *pMpi2EventHbdPhySas_t;
997
998/*values for the Flags field */
999#define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID (0x02)
1000#define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME (0x01)
1001
1002/*use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h
1003 *for the NegotiatedLinkRate field */
1004
1005typedef union _MPI2_EVENT_HBD_DESCRIPTOR {
1006 MPI2_EVENT_HBD_PHY_SAS Sas;
1007} MPI2_EVENT_HBD_DESCRIPTOR, *PTR_MPI2_EVENT_HBD_DESCRIPTOR,
1008 Mpi2EventHbdDescriptor_t, *pMpi2EventHbdDescriptor_t;
1009
1010typedef struct _MPI2_EVENT_DATA_HBD_PHY {
1011 U8 DescriptorType; /*0x00 */
1012 U8 Reserved1; /*0x01 */
1013 U16 Reserved2; /*0x02 */
1014 U32 Reserved3; /*0x04 */
1015 MPI2_EVENT_HBD_DESCRIPTOR Descriptor; /*0x08 */
1016} MPI2_EVENT_DATA_HBD_PHY, *PTR_MPI2_EVENT_DATA_HBD_PHY,
1017 Mpi2EventDataHbdPhy_t,
1018 *pMpi2EventDataMpi2EventDataHbdPhy_t;
1019
1020/*values for the DescriptorType field */
1021#define MPI2_EVENT_HBD_DT_SAS (0x01)
1022
1023/****************************************************************************
1024* EventAck message
1025****************************************************************************/
1026
1027/*EventAck Request message */
1028typedef struct _MPI2_EVENT_ACK_REQUEST {
1029 U16 Reserved1; /*0x00 */
1030 U8 ChainOffset; /*0x02 */
1031 U8 Function; /*0x03 */
1032 U16 Reserved2; /*0x04 */
1033 U8 Reserved3; /*0x06 */
1034 U8 MsgFlags; /*0x07 */
1035 U8 VP_ID; /*0x08 */
1036 U8 VF_ID; /*0x09 */
1037 U16 Reserved4; /*0x0A */
1038 U16 Event; /*0x0C */
1039 U16 Reserved5; /*0x0E */
1040 U32 EventContext; /*0x10 */
1041} MPI2_EVENT_ACK_REQUEST, *PTR_MPI2_EVENT_ACK_REQUEST,
1042 Mpi2EventAckRequest_t, *pMpi2EventAckRequest_t;
1043
1044/*EventAck Reply message */
1045typedef struct _MPI2_EVENT_ACK_REPLY {
1046 U16 Reserved1; /*0x00 */
1047 U8 MsgLength; /*0x02 */
1048 U8 Function; /*0x03 */
1049 U16 Reserved2; /*0x04 */
1050 U8 Reserved3; /*0x06 */
1051 U8 MsgFlags; /*0x07 */
1052 U8 VP_ID; /*0x08 */
1053 U8 VF_ID; /*0x09 */
1054 U16 Reserved4; /*0x0A */
1055 U16 Reserved5; /*0x0C */
1056 U16 IOCStatus; /*0x0E */
1057 U32 IOCLogInfo; /*0x10 */
1058} MPI2_EVENT_ACK_REPLY, *PTR_MPI2_EVENT_ACK_REPLY,
1059 Mpi2EventAckReply_t, *pMpi2EventAckReply_t;
1060
1061/****************************************************************************
1062* SendHostMessage message
1063****************************************************************************/
1064
1065/*SendHostMessage Request message */
1066typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST {
1067 U16 HostDataLength; /*0x00 */
1068 U8 ChainOffset; /*0x02 */
1069 U8 Function; /*0x03 */
1070 U16 Reserved1; /*0x04 */
1071 U8 Reserved2; /*0x06 */
1072 U8 MsgFlags; /*0x07 */
1073 U8 VP_ID; /*0x08 */
1074 U8 VF_ID; /*0x09 */
1075 U16 Reserved3; /*0x0A */
1076 U8 Reserved4; /*0x0C */
1077 U8 DestVF_ID; /*0x0D */
1078 U16 Reserved5; /*0x0E */
1079 U32 Reserved6; /*0x10 */
1080 U32 Reserved7; /*0x14 */
1081 U32 Reserved8; /*0x18 */
1082 U32 Reserved9; /*0x1C */
1083 U32 Reserved10; /*0x20 */
1084 U32 HostData[1]; /*0x24 */
1085} MPI2_SEND_HOST_MESSAGE_REQUEST,
1086 *PTR_MPI2_SEND_HOST_MESSAGE_REQUEST,
1087 Mpi2SendHostMessageRequest_t,
1088 *pMpi2SendHostMessageRequest_t;
1089
1090/*SendHostMessage Reply message */
1091typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY {
1092 U16 HostDataLength; /*0x00 */
1093 U8 MsgLength; /*0x02 */
1094 U8 Function; /*0x03 */
1095 U16 Reserved1; /*0x04 */
1096 U8 Reserved2; /*0x06 */
1097 U8 MsgFlags; /*0x07 */
1098 U8 VP_ID; /*0x08 */
1099 U8 VF_ID; /*0x09 */
1100 U16 Reserved3; /*0x0A */
1101 U16 Reserved4; /*0x0C */
1102 U16 IOCStatus; /*0x0E */
1103 U32 IOCLogInfo; /*0x10 */
1104} MPI2_SEND_HOST_MESSAGE_REPLY, *PTR_MPI2_SEND_HOST_MESSAGE_REPLY,
1105 Mpi2SendHostMessageReply_t, *pMpi2SendHostMessageReply_t;
1106
1107/****************************************************************************
1108* FWDownload message
1109****************************************************************************/
1110
1111/*MPI v2.0 FWDownload Request message */
1112typedef struct _MPI2_FW_DOWNLOAD_REQUEST {
1113 U8 ImageType; /*0x00 */
1114 U8 Reserved1; /*0x01 */
1115 U8 ChainOffset; /*0x02 */
1116 U8 Function; /*0x03 */
1117 U16 Reserved2; /*0x04 */
1118 U8 Reserved3; /*0x06 */
1119 U8 MsgFlags; /*0x07 */
1120 U8 VP_ID; /*0x08 */
1121 U8 VF_ID; /*0x09 */
1122 U16 Reserved4; /*0x0A */
1123 U32 TotalImageSize; /*0x0C */
1124 U32 Reserved5; /*0x10 */
1125 MPI2_MPI_SGE_UNION SGL; /*0x14 */
1126} MPI2_FW_DOWNLOAD_REQUEST, *PTR_MPI2_FW_DOWNLOAD_REQUEST,
1127 Mpi2FWDownloadRequest, *pMpi2FWDownloadRequest;
1128
1129#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01)
1130
1131#define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01)
1132#define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02)
1133#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06)
1134#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07)
1135#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08)
1136#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09)
1137#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A)
1138#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
1139#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
1140
1141/*MPI v2.0 FWDownload TransactionContext Element */
1142typedef struct _MPI2_FW_DOWNLOAD_TCSGE {
1143 U8 Reserved1; /*0x00 */
1144 U8 ContextSize; /*0x01 */
1145 U8 DetailsLength; /*0x02 */
1146 U8 Flags; /*0x03 */
1147 U32 Reserved2; /*0x04 */
1148 U32 ImageOffset; /*0x08 */
1149 U32 ImageSize; /*0x0C */
1150} MPI2_FW_DOWNLOAD_TCSGE, *PTR_MPI2_FW_DOWNLOAD_TCSGE,
1151 Mpi2FWDownloadTCSGE_t, *pMpi2FWDownloadTCSGE_t;
1152
1153/*MPI v2.5 FWDownload Request message */
1154typedef struct _MPI25_FW_DOWNLOAD_REQUEST {
1155 U8 ImageType; /*0x00 */
1156 U8 Reserved1; /*0x01 */
1157 U8 ChainOffset; /*0x02 */
1158 U8 Function; /*0x03 */
1159 U16 Reserved2; /*0x04 */
1160 U8 Reserved3; /*0x06 */
1161 U8 MsgFlags; /*0x07 */
1162 U8 VP_ID; /*0x08 */
1163 U8 VF_ID; /*0x09 */
1164 U16 Reserved4; /*0x0A */
1165 U32 TotalImageSize; /*0x0C */
1166 U32 Reserved5; /*0x10 */
1167 U32 Reserved6; /*0x14 */
1168 U32 ImageOffset; /*0x18 */
1169 U32 ImageSize; /*0x1C */
1170 MPI25_SGE_IO_UNION SGL; /*0x20 */
1171} MPI25_FW_DOWNLOAD_REQUEST, *PTR_MPI25_FW_DOWNLOAD_REQUEST,
1172 Mpi25FWDownloadRequest, *pMpi25FWDownloadRequest;
1173
1174/*FWDownload Reply message */
1175typedef struct _MPI2_FW_DOWNLOAD_REPLY {
1176 U8 ImageType; /*0x00 */
1177 U8 Reserved1; /*0x01 */
1178 U8 MsgLength; /*0x02 */
1179 U8 Function; /*0x03 */
1180 U16 Reserved2; /*0x04 */
1181 U8 Reserved3; /*0x06 */
1182 U8 MsgFlags; /*0x07 */
1183 U8 VP_ID; /*0x08 */
1184 U8 VF_ID; /*0x09 */
1185 U16 Reserved4; /*0x0A */
1186 U16 Reserved5; /*0x0C */
1187 U16 IOCStatus; /*0x0E */
1188 U32 IOCLogInfo; /*0x10 */
1189} MPI2_FW_DOWNLOAD_REPLY, *PTR_MPI2_FW_DOWNLOAD_REPLY,
1190 Mpi2FWDownloadReply_t, *pMpi2FWDownloadReply_t;
1191
1192/****************************************************************************
1193* FWUpload message
1194****************************************************************************/
1195
1196/*MPI v2.0 FWUpload Request message */
1197typedef struct _MPI2_FW_UPLOAD_REQUEST {
1198 U8 ImageType; /*0x00 */
1199 U8 Reserved1; /*0x01 */
1200 U8 ChainOffset; /*0x02 */
1201 U8 Function; /*0x03 */
1202 U16 Reserved2; /*0x04 */
1203 U8 Reserved3; /*0x06 */
1204 U8 MsgFlags; /*0x07 */
1205 U8 VP_ID; /*0x08 */
1206 U8 VF_ID; /*0x09 */
1207 U16 Reserved4; /*0x0A */
1208 U32 Reserved5; /*0x0C */
1209 U32 Reserved6; /*0x10 */
1210 MPI2_MPI_SGE_UNION SGL; /*0x14 */
1211} MPI2_FW_UPLOAD_REQUEST, *PTR_MPI2_FW_UPLOAD_REQUEST,
1212 Mpi2FWUploadRequest_t, *pMpi2FWUploadRequest_t;
1213
1214#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00)
1215#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01)
1216#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02)
1217#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05)
1218#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06)
1219#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07)
1220#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08)
1221#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09)
1222#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A)
1223#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
1224
1225/*MPI v2.0 FWUpload TransactionContext Element */
1226typedef struct _MPI2_FW_UPLOAD_TCSGE {
1227 U8 Reserved1; /*0x00 */
1228 U8 ContextSize; /*0x01 */
1229 U8 DetailsLength; /*0x02 */
1230 U8 Flags; /*0x03 */
1231 U32 Reserved2; /*0x04 */
1232 U32 ImageOffset; /*0x08 */
1233 U32 ImageSize; /*0x0C */
1234} MPI2_FW_UPLOAD_TCSGE, *PTR_MPI2_FW_UPLOAD_TCSGE,
1235 Mpi2FWUploadTCSGE_t, *pMpi2FWUploadTCSGE_t;
1236
1237/*MPI v2.5 FWUpload Request message */
1238typedef struct _MPI25_FW_UPLOAD_REQUEST {
1239 U8 ImageType; /*0x00 */
1240 U8 Reserved1; /*0x01 */
1241 U8 ChainOffset; /*0x02 */
1242 U8 Function; /*0x03 */
1243 U16 Reserved2; /*0x04 */
1244 U8 Reserved3; /*0x06 */
1245 U8 MsgFlags; /*0x07 */
1246 U8 VP_ID; /*0x08 */
1247 U8 VF_ID; /*0x09 */
1248 U16 Reserved4; /*0x0A */
1249 U32 Reserved5; /*0x0C */
1250 U32 Reserved6; /*0x10 */
1251 U32 Reserved7; /*0x14 */
1252 U32 ImageOffset; /*0x18 */
1253 U32 ImageSize; /*0x1C */
1254 MPI25_SGE_IO_UNION SGL; /*0x20 */
1255} MPI25_FW_UPLOAD_REQUEST, *PTR_MPI25_FW_UPLOAD_REQUEST,
1256 Mpi25FWUploadRequest_t, *pMpi25FWUploadRequest_t;
1257
1258/*FWUpload Reply message */
1259typedef struct _MPI2_FW_UPLOAD_REPLY {
1260 U8 ImageType; /*0x00 */
1261 U8 Reserved1; /*0x01 */
1262 U8 MsgLength; /*0x02 */
1263 U8 Function; /*0x03 */
1264 U16 Reserved2; /*0x04 */
1265 U8 Reserved3; /*0x06 */
1266 U8 MsgFlags; /*0x07 */
1267 U8 VP_ID; /*0x08 */
1268 U8 VF_ID; /*0x09 */
1269 U16 Reserved4; /*0x0A */
1270 U16 Reserved5; /*0x0C */
1271 U16 IOCStatus; /*0x0E */
1272 U32 IOCLogInfo; /*0x10 */
1273 U32 ActualImageSize; /*0x14 */
1274} MPI2_FW_UPLOAD_REPLY, *PTR_MPI2_FW_UPLOAD_REPLY,
1275 Mpi2FWUploadReply_t, *pMPi2FWUploadReply_t;
1276
1277/*FW Image Header */
1278typedef struct _MPI2_FW_IMAGE_HEADER {
1279 U32 Signature; /*0x00 */
1280 U32 Signature0; /*0x04 */
1281 U32 Signature1; /*0x08 */
1282 U32 Signature2; /*0x0C */
1283 MPI2_VERSION_UNION MPIVersion; /*0x10 */
1284 MPI2_VERSION_UNION FWVersion; /*0x14 */
1285 MPI2_VERSION_UNION NVDATAVersion; /*0x18 */
1286 MPI2_VERSION_UNION PackageVersion; /*0x1C */
1287 U16 VendorID; /*0x20 */
1288 U16 ProductID; /*0x22 */
1289 U16 ProtocolFlags; /*0x24 */
1290 U16 Reserved26; /*0x26 */
1291 U32 IOCCapabilities; /*0x28 */
1292 U32 ImageSize; /*0x2C */
1293 U32 NextImageHeaderOffset; /*0x30 */
1294 U32 Checksum; /*0x34 */
1295 U32 Reserved38; /*0x38 */
1296 U32 Reserved3C; /*0x3C */
1297 U32 Reserved40; /*0x40 */
1298 U32 Reserved44; /*0x44 */
1299 U32 Reserved48; /*0x48 */
1300 U32 Reserved4C; /*0x4C */
1301 U32 Reserved50; /*0x50 */
1302 U32 Reserved54; /*0x54 */
1303 U32 Reserved58; /*0x58 */
1304 U32 Reserved5C; /*0x5C */
1305 U32 Reserved60; /*0x60 */
1306 U32 FirmwareVersionNameWhat; /*0x64 */
1307 U8 FirmwareVersionName[32]; /*0x68 */
1308 U32 VendorNameWhat; /*0x88 */
1309 U8 VendorName[32]; /*0x8C */
1310 U32 PackageNameWhat; /*0x88 */
1311 U8 PackageName[32]; /*0x8C */
1312 U32 ReservedD0; /*0xD0 */
1313 U32 ReservedD4; /*0xD4 */
1314 U32 ReservedD8; /*0xD8 */
1315 U32 ReservedDC; /*0xDC */
1316 U32 ReservedE0; /*0xE0 */
1317 U32 ReservedE4; /*0xE4 */
1318 U32 ReservedE8; /*0xE8 */
1319 U32 ReservedEC; /*0xEC */
1320 U32 ReservedF0; /*0xF0 */
1321 U32 ReservedF4; /*0xF4 */
1322 U32 ReservedF8; /*0xF8 */
1323 U32 ReservedFC; /*0xFC */
1324} MPI2_FW_IMAGE_HEADER, *PTR_MPI2_FW_IMAGE_HEADER,
1325 Mpi2FWImageHeader_t, *pMpi2FWImageHeader_t;
1326
1327/*Signature field */
1328#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00)
1329#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000)
1330#define MPI2_FW_HEADER_SIGNATURE (0xEA000000)
1331
1332/*Signature0 field */
1333#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04)
1334#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A)
1335
1336/*Signature1 field */
1337#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08)
1338#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5)
1339
1340/*Signature2 field */
1341#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C)
1342#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA)
1343
1344/*defines for using the ProductID field */
1345#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000)
1346#define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000)
1347
1348#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00)
1349#define MPI2_FW_HEADER_PID_PROD_A (0x0000)
1350#define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200)
1351#define MPI2_FW_HEADER_PID_PROD_IR_SCSI (0x0700)
1352
1353#define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF)
1354/*SAS ProductID Family bits */
1355#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013)
1356#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014)
1357#define MPI25_FW_HEADER_PID_FAMILY_3108_SAS (0x0021)
1358
1359/*use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
1360
1361/*use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */
1362
1363#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C)
1364#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30)
1365#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64)
1366
1367#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840)
1368
1369#define MPI2_FW_HEADER_SIZE (0x100)
1370
1371/*Extended Image Header */
1372typedef struct _MPI2_EXT_IMAGE_HEADER {
1373 U8 ImageType; /*0x00 */
1374 U8 Reserved1; /*0x01 */
1375 U16 Reserved2; /*0x02 */
1376 U32 Checksum; /*0x04 */
1377 U32 ImageSize; /*0x08 */
1378 U32 NextImageHeaderOffset; /*0x0C */
1379 U32 PackageVersion; /*0x10 */
1380 U32 Reserved3; /*0x14 */
1381 U32 Reserved4; /*0x18 */
1382 U32 Reserved5; /*0x1C */
1383 U8 IdentifyString[32]; /*0x20 */
1384} MPI2_EXT_IMAGE_HEADER, *PTR_MPI2_EXT_IMAGE_HEADER,
1385 Mpi2ExtImageHeader_t, *pMpi2ExtImageHeader_t;
1386
1387/*useful offsets */
1388#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00)
1389#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08)
1390#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C)
1391
1392#define MPI2_EXT_IMAGE_HEADER_SIZE (0x40)
1393
1394/*defines for the ImageType field */
1395#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00)
1396#define MPI2_EXT_IMAGE_TYPE_FW (0x01)
1397#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03)
1398#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04)
1399#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05)
1400#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06)
1401#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07)
1402#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08)
1403#define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80)
1404#define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF)
1405
1406#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC)
1407
1408/*FLASH Layout Extended Image Data */
1409
1410/*
1411 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1412 *one and check RegionsPerLayout at runtime.
1413 */
1414#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
1415#define MPI2_FLASH_NUMBER_OF_REGIONS (1)
1416#endif
1417
1418/*
1419 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1420 *one and check NumberOfLayouts at runtime.
1421 */
1422#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
1423#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1)
1424#endif
1425
1426typedef struct _MPI2_FLASH_REGION {
1427 U8 RegionType; /*0x00 */
1428 U8 Reserved1; /*0x01 */
1429 U16 Reserved2; /*0x02 */
1430 U32 RegionOffset; /*0x04 */
1431 U32 RegionSize; /*0x08 */
1432 U32 Reserved3; /*0x0C */
1433} MPI2_FLASH_REGION, *PTR_MPI2_FLASH_REGION,
1434 Mpi2FlashRegion_t, *pMpi2FlashRegion_t;
1435
1436typedef struct _MPI2_FLASH_LAYOUT {
1437 U32 FlashSize; /*0x00 */
1438 U32 Reserved1; /*0x04 */
1439 U32 Reserved2; /*0x08 */
1440 U32 Reserved3; /*0x0C */
1441 MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS]; /*0x10 */
1442} MPI2_FLASH_LAYOUT, *PTR_MPI2_FLASH_LAYOUT,
1443 Mpi2FlashLayout_t, *pMpi2FlashLayout_t;
1444
1445typedef struct _MPI2_FLASH_LAYOUT_DATA {
1446 U8 ImageRevision; /*0x00 */
1447 U8 Reserved1; /*0x01 */
1448 U8 SizeOfRegion; /*0x02 */
1449 U8 Reserved2; /*0x03 */
1450 U16 NumberOfLayouts; /*0x04 */
1451 U16 RegionsPerLayout; /*0x06 */
1452 U16 MinimumSectorAlignment; /*0x08 */
1453 U16 Reserved3; /*0x0A */
1454 U32 Reserved4; /*0x0C */
1455 MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS]; /*0x10 */
1456} MPI2_FLASH_LAYOUT_DATA, *PTR_MPI2_FLASH_LAYOUT_DATA,
1457 Mpi2FlashLayoutData_t, *pMpi2FlashLayoutData_t;
1458
1459/*defines for the RegionType field */
1460#define MPI2_FLASH_REGION_UNUSED (0x00)
1461#define MPI2_FLASH_REGION_FIRMWARE (0x01)
1462#define MPI2_FLASH_REGION_BIOS (0x02)
1463#define MPI2_FLASH_REGION_NVDATA (0x03)
1464#define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05)
1465#define MPI2_FLASH_REGION_MFG_INFORMATION (0x06)
1466#define MPI2_FLASH_REGION_CONFIG_1 (0x07)
1467#define MPI2_FLASH_REGION_CONFIG_2 (0x08)
1468#define MPI2_FLASH_REGION_MEGARAID (0x09)
1469#define MPI2_FLASH_REGION_INIT (0x0A)
1470
1471/*ImageRevision */
1472#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00)
1473
1474/*Supported Devices Extended Image Data */
1475
1476/*
1477 *Host code (drivers, BIOS, utilities, etc.) should leave this define set to
1478 *one and check NumberOfDevices at runtime.
1479 */
1480#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
1481#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1)
1482#endif
1483
1484typedef struct _MPI2_SUPPORTED_DEVICE {
1485 U16 DeviceID; /*0x00 */
1486 U16 VendorID; /*0x02 */
1487 U16 DeviceIDMask; /*0x04 */
1488 U16 Reserved1; /*0x06 */
1489 U8 LowPCIRev; /*0x08 */
1490 U8 HighPCIRev; /*0x09 */
1491 U16 Reserved2; /*0x0A */
1492 U32 Reserved3; /*0x0C */
1493} MPI2_SUPPORTED_DEVICE, *PTR_MPI2_SUPPORTED_DEVICE,
1494 Mpi2SupportedDevice_t, *pMpi2SupportedDevice_t;
1495
1496typedef struct _MPI2_SUPPORTED_DEVICES_DATA {
1497 U8 ImageRevision; /*0x00 */
1498 U8 Reserved1; /*0x01 */
1499 U8 NumberOfDevices; /*0x02 */
1500 U8 Reserved2; /*0x03 */
1501 U32 Reserved3; /*0x04 */
1502 MPI2_SUPPORTED_DEVICE
1503 SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES];/*0x08 */
1504} MPI2_SUPPORTED_DEVICES_DATA, *PTR_MPI2_SUPPORTED_DEVICES_DATA,
1505 Mpi2SupportedDevicesData_t, *pMpi2SupportedDevicesData_t;
1506
1507/*ImageRevision */
1508#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00)
1509
1510/*Init Extended Image Data */
1511
1512typedef struct _MPI2_INIT_IMAGE_FOOTER {
1513 U32 BootFlags; /*0x00 */
1514 U32 ImageSize; /*0x04 */
1515 U32 Signature0; /*0x08 */
1516 U32 Signature1; /*0x0C */
1517 U32 Signature2; /*0x10 */
1518 U32 ResetVector; /*0x14 */
1519} MPI2_INIT_IMAGE_FOOTER, *PTR_MPI2_INIT_IMAGE_FOOTER,
1520 Mpi2InitImageFooter_t, *pMpi2InitImageFooter_t;
1521
1522/*defines for the BootFlags field */
1523#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00)
1524
1525/*defines for the ImageSize field */
1526#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04)
1527
1528/*defines for the Signature0 field */
1529#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08)
1530#define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA)
1531
1532/*defines for the Signature1 field */
1533#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C)
1534#define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5)
1535
1536/*defines for the Signature2 field */
1537#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10)
1538#define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A)
1539
1540/*Signature fields as individual bytes */
1541#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA)
1542#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A)
1543#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5)
1544#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A)
1545
1546#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5)
1547#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA)
1548#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A)
1549#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5)
1550
1551#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A)
1552#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5)
1553#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA)
1554#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A)
1555
1556/*defines for the ResetVector field */
1557#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14)
1558
1559/****************************************************************************
1560* PowerManagementControl message
1561****************************************************************************/
1562
1563/*PowerManagementControl Request message */
1564typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST {
1565 U8 Feature; /*0x00 */
1566 U8 Reserved1; /*0x01 */
1567 U8 ChainOffset; /*0x02 */
1568 U8 Function; /*0x03 */
1569 U16 Reserved2; /*0x04 */
1570 U8 Reserved3; /*0x06 */
1571 U8 MsgFlags; /*0x07 */
1572 U8 VP_ID; /*0x08 */
1573 U8 VF_ID; /*0x09 */
1574 U16 Reserved4; /*0x0A */
1575 U8 Parameter1; /*0x0C */
1576 U8 Parameter2; /*0x0D */
1577 U8 Parameter3; /*0x0E */
1578 U8 Parameter4; /*0x0F */
1579 U32 Reserved5; /*0x10 */
1580 U32 Reserved6; /*0x14 */
1581} MPI2_PWR_MGMT_CONTROL_REQUEST, *PTR_MPI2_PWR_MGMT_CONTROL_REQUEST,
1582 Mpi2PwrMgmtControlRequest_t, *pMpi2PwrMgmtControlRequest_t;
1583
1584/*defines for the Feature field */
1585#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01)
1586#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02)
1587#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) /*obsolete */
1588#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04)
1589#define MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE (0x05)
1590#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80)
1591#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF)
1592
1593/*parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */
1594/*Parameter1 contains a PHY number */
1595/*Parameter2 indicates power condition action using these defines */
1596#define MPI2_PM_CONTROL_PARAM2_PARTIAL (0x01)
1597#define MPI2_PM_CONTROL_PARAM2_SLUMBER (0x02)
1598#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT (0x03)
1599/*Parameter3 and Parameter4 are reserved */
1600
1601/*parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION
1602 * Feature */
1603/*Parameter1 contains SAS port width modulation group number */
1604/*Parameter2 indicates IOC action using these defines */
1605#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP (0x01)
1606#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION (0x02)
1607#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP (0x03)
1608/*Parameter3 indicates desired modulation level using these defines */
1609#define MPI2_PM_CONTROL_PARAM3_25_PERCENT (0x00)
1610#define MPI2_PM_CONTROL_PARAM3_50_PERCENT (0x01)
1611#define MPI2_PM_CONTROL_PARAM3_75_PERCENT (0x02)
1612#define MPI2_PM_CONTROL_PARAM3_100_PERCENT (0x03)
1613/*Parameter4 is reserved */
1614
1615/*this next set (_PCIE_LINK) is obsolete */
1616/*parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */
1617/*Parameter1 indicates desired PCIe link speed using these defines */
1618#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) /*obsolete */
1619#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) /*obsolete */
1620#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) /*obsolete */
1621/*Parameter2 indicates desired PCIe link width using these defines */
1622#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) /*obsolete */
1623#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) /*obsolete */
1624#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) /*obsolete */
1625#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) /*obsolete */
1626/*Parameter3 and Parameter4 are reserved */
1627
1628/*parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */
1629/*Parameter1 indicates desired IOC hardware clock speed using these defines */
1630#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED (0x01)
1631#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED (0x02)
1632#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED (0x04)
1633#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED (0x08)
1634/*Parameter2, Parameter3, and Parameter4 are reserved */
1635
1636/*parameter usage for the MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE Feature*/
1637/*Parameter1 indicates host action regarding global power management mode */
1638#define MPI2_PM_CONTROL_PARAM1_TAKE_CONTROL (0x01)
1639#define MPI2_PM_CONTROL_PARAM1_CHANGE_GLOBAL_MODE (0x02)
1640#define MPI2_PM_CONTROL_PARAM1_RELEASE_CONTROL (0x03)
1641/*Parameter2 indicates the requested global power management mode */
1642#define MPI2_PM_CONTROL_PARAM2_FULL_PWR_PERF (0x01)
1643#define MPI2_PM_CONTROL_PARAM2_REDUCED_PWR_PERF (0x08)
1644#define MPI2_PM_CONTROL_PARAM2_STANDBY (0x40)
1645/*Parameter3 and Parameter4 are reserved */
1646
1647/*PowerManagementControl Reply message */
1648typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY {
1649 U8 Feature; /*0x00 */
1650 U8 Reserved1; /*0x01 */
1651 U8 MsgLength; /*0x02 */
1652 U8 Function; /*0x03 */
1653 U16 Reserved2; /*0x04 */
1654 U8 Reserved3; /*0x06 */
1655 U8 MsgFlags; /*0x07 */
1656 U8 VP_ID; /*0x08 */
1657 U8 VF_ID; /*0x09 */
1658 U16 Reserved4; /*0x0A */
1659 U16 Reserved5; /*0x0C */
1660 U16 IOCStatus; /*0x0E */
1661 U32 IOCLogInfo; /*0x10 */
1662} MPI2_PWR_MGMT_CONTROL_REPLY, *PTR_MPI2_PWR_MGMT_CONTROL_REPLY,
1663 Mpi2PwrMgmtControlReply_t, *pMpi2PwrMgmtControlReply_t;
1664
1665#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_raid.h b/drivers/scsi/mpt3sas/mpi/mpi2_raid.h
new file mode 100644
index 000000000000..d1d9866cf300
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_raid.h
@@ -0,0 +1,346 @@
1/*
2 * Copyright (c) 2000-2012 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.08
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 * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of
24 * VolumeCreationFlags and marked the old one as obsolete.
25 * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
26 * 08-24-10 02.00.06 Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with
27 * related structures and defines.
28 * Added product-specific range to RAID Action values.
29 * 11-18-11 02.00.07 Incorporating additions for MPI v2.5.
30 * 02-06-12 02.00.08 Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN.
31 * --------------------------------------------------------------------------
32 */
33
34#ifndef MPI2_RAID_H
35#define MPI2_RAID_H
36
37/*****************************************************************************
38*
39* Integrated RAID Messages
40*
41*****************************************************************************/
42
43/****************************************************************************
44* RAID Action messages
45****************************************************************************/
46
47/*ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
48#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000)
49#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001)
50
51/*use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for
52 *MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
53
54/*ActionDataWord defines for use with
55 *MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
56#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001)
57
58/*ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
59typedef struct _MPI2_RAID_ACTION_RATE_DATA {
60 U8 RateToChange; /*0x00 */
61 U8 RateOrMode; /*0x01 */
62 U16 DataScrubDuration; /*0x02 */
63} MPI2_RAID_ACTION_RATE_DATA, *PTR_MPI2_RAID_ACTION_RATE_DATA,
64 Mpi2RaidActionRateData_t, *pMpi2RaidActionRateData_t;
65
66#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00)
67#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01)
68#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02)
69
70/*ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
71typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION {
72 U8 RAIDFunction; /*0x00 */
73 U8 Flags; /*0x01 */
74 U16 Reserved1; /*0x02 */
75} MPI2_RAID_ACTION_START_RAID_FUNCTION,
76 *PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
77 Mpi2RaidActionStartRaidFunction_t,
78 *pMpi2RaidActionStartRaidFunction_t;
79
80/*defines for the RAIDFunction field */
81#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00)
82#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
83#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02)
84
85/*defines for the Flags field */
86#define MPI2_RAID_ACTION_START_NEW (0x00)
87#define MPI2_RAID_ACTION_START_RESUME (0x01)
88
89/*ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
90typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION {
91 U8 RAIDFunction; /*0x00 */
92 U8 Flags; /*0x01 */
93 U16 Reserved1; /*0x02 */
94} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
95 *PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
96 Mpi2RaidActionStopRaidFunction_t,
97 *pMpi2RaidActionStopRaidFunction_t;
98
99/*defines for the RAIDFunction field */
100#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00)
101#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01)
102#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02)
103
104/*defines for the Flags field */
105#define MPI2_RAID_ACTION_STOP_ABORT (0x00)
106#define MPI2_RAID_ACTION_STOP_PAUSE (0x01)
107
108/*ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
109typedef struct _MPI2_RAID_ACTION_HOT_SPARE {
110 U8 HotSparePool; /*0x00 */
111 U8 Reserved1; /*0x01 */
112 U16 DevHandle; /*0x02 */
113} MPI2_RAID_ACTION_HOT_SPARE, *PTR_MPI2_RAID_ACTION_HOT_SPARE,
114 Mpi2RaidActionHotSpare_t, *pMpi2RaidActionHotSpare_t;
115
116/*ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
117typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE {
118 U8 Flags; /*0x00 */
119 U8 DeviceFirmwareUpdateModeTimeout; /*0x01 */
120 U16 Reserved1; /*0x02 */
121} MPI2_RAID_ACTION_FW_UPDATE_MODE,
122 *PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
123 Mpi2RaidActionFwUpdateMode_t,
124 *pMpi2RaidActionFwUpdateMode_t;
125
126/*ActionDataWord defines for use with
127 *MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
128#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00)
129#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01)
130
131typedef union _MPI2_RAID_ACTION_DATA {
132 U32 Word;
133 MPI2_RAID_ACTION_RATE_DATA Rates;
134 MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction;
135 MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction;
136 MPI2_RAID_ACTION_HOT_SPARE HotSpare;
137 MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode;
138} MPI2_RAID_ACTION_DATA, *PTR_MPI2_RAID_ACTION_DATA,
139 Mpi2RaidActionData_t, *pMpi2RaidActionData_t;
140
141/*RAID Action Request Message */
142typedef struct _MPI2_RAID_ACTION_REQUEST {
143 U8 Action; /*0x00 */
144 U8 Reserved1; /*0x01 */
145 U8 ChainOffset; /*0x02 */
146 U8 Function; /*0x03 */
147 U16 VolDevHandle; /*0x04 */
148 U8 PhysDiskNum; /*0x06 */
149 U8 MsgFlags; /*0x07 */
150 U8 VP_ID; /*0x08 */
151 U8 VF_ID; /*0x09 */
152 U16 Reserved2; /*0x0A */
153 U32 Reserved3; /*0x0C */
154 MPI2_RAID_ACTION_DATA ActionDataWord; /*0x10 */
155 MPI2_SGE_SIMPLE_UNION ActionDataSGE; /*0x14 */
156} MPI2_RAID_ACTION_REQUEST, *PTR_MPI2_RAID_ACTION_REQUEST,
157 Mpi2RaidActionRequest_t, *pMpi2RaidActionRequest_t;
158
159/*RAID Action request Action values */
160
161#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01)
162#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02)
163#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03)
164#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04)
165#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05)
166#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A)
167#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B)
168#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F)
169#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11)
170#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15)
171#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17)
172#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18)
173#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19)
174#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C)
175#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D)
176#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E)
177#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20)
178#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21)
179#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22)
180#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK (0x23)
181#define MPI2_RAID_ACTION_PHYSDISK_HIDDEN (0x24)
182#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC (0x80)
183#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC (0xFF)
184
185/*RAID Volume Creation Structure */
186
187/*
188 *The following define can be customized for the targeted product.
189 */
190#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
191#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1)
192#endif
193
194typedef struct _MPI2_RAID_VOLUME_PHYSDISK {
195 U8 RAIDSetNum; /*0x00 */
196 U8 PhysDiskMap; /*0x01 */
197 U16 PhysDiskDevHandle; /*0x02 */
198} MPI2_RAID_VOLUME_PHYSDISK, *PTR_MPI2_RAID_VOLUME_PHYSDISK,
199 Mpi2RaidVolumePhysDisk_t, *pMpi2RaidVolumePhysDisk_t;
200
201/*defines for the PhysDiskMap field */
202#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01)
203#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02)
204
205typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT {
206 U8 NumPhysDisks; /*0x00 */
207 U8 VolumeType; /*0x01 */
208 U16 Reserved1; /*0x02 */
209 U32 VolumeCreationFlags; /*0x04 */
210 U32 VolumeSettings; /*0x08 */
211 U8 Reserved2; /*0x0C */
212 U8 ResyncRate; /*0x0D */
213 U16 DataScrubDuration; /*0x0E */
214 U64 VolumeMaxLBA; /*0x10 */
215 U32 StripeSize; /*0x18 */
216 U8 Name[16]; /*0x1C */
217 MPI2_RAID_VOLUME_PHYSDISK
218 PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS]; /*0x2C */
219} MPI2_RAID_VOLUME_CREATION_STRUCT,
220 *PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
221 Mpi2RaidVolumeCreationStruct_t,
222 *pMpi2RaidVolumeCreationStruct_t;
223
224/*use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
225
226/*defines for the VolumeCreationFlags field */
227#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS (0x80000000)
228#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x00000004)
229#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x00000002)
230#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x00000001)
231/*The following is an obsolete define.
232 *It must be shifted left 24 bits in order to set the proper bit.
233 */
234#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
235
236/*RAID Online Capacity Expansion Structure */
237
238typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION {
239 U32 Flags; /*0x00 */
240 U16 DevHandle0; /*0x04 */
241 U16 Reserved1; /*0x06 */
242 U16 DevHandle1; /*0x08 */
243 U16 Reserved2; /*0x0A */
244} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
245 *PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
246 Mpi2RaidOnlineCapacityExpansion_t,
247 *pMpi2RaidOnlineCapacityExpansion_t;
248
249/*RAID Compatibility Input Structure */
250
251typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT {
252 U16 SourceDevHandle; /*0x00 */
253 U16 CandidateDevHandle; /*0x02 */
254 U32 Flags; /*0x04 */
255 U32 Reserved1; /*0x08 */
256 U32 Reserved2; /*0x0C */
257} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
258 *PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
259 Mpi2RaidCompatibilityInputStruct_t,
260 *pMpi2RaidCompatibilityInputStruct_t;
261
262/*defines for RAID Compatibility Structure Flags field */
263#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG (0x00000002)
264#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG (0x00000001)
265
266/*RAID Volume Indicator Structure */
267
268typedef struct _MPI2_RAID_VOL_INDICATOR {
269 U64 TotalBlocks; /*0x00 */
270 U64 BlocksRemaining; /*0x08 */
271 U32 Flags; /*0x10 */
272} MPI2_RAID_VOL_INDICATOR, *PTR_MPI2_RAID_VOL_INDICATOR,
273 Mpi2RaidVolIndicator_t, *pMpi2RaidVolIndicator_t;
274
275/*defines for RAID Volume Indicator Flags field */
276#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F)
277#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000)
278#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
279#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002)
280#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003)
281#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004)
282
283/*RAID Compatibility Result Structure */
284
285typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT {
286 U8 State; /*0x00 */
287 U8 Reserved1; /*0x01 */
288 U16 Reserved2; /*0x02 */
289 U32 GenericAttributes; /*0x04 */
290 U32 OEMSpecificAttributes; /*0x08 */
291 U32 Reserved3; /*0x0C */
292 U32 Reserved4; /*0x10 */
293} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
294 *PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
295 Mpi2RaidCompatibilityResultStruct_t,
296 *pMpi2RaidCompatibilityResultStruct_t;
297
298/*defines for RAID Compatibility Result Structure State field */
299#define MPI2_RAID_COMPAT_STATE_COMPATIBLE (0x00)
300#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE (0x01)
301
302/*defines for RAID Compatibility Result Structure GenericAttributes field */
303#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR (0x00000010)
304
305#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK (0x0000000C)
306#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE (0x00000008)
307#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE (0x00000004)
308
309#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK (0x00000003)
310#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL (0x00000002)
311#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL (0x00000001)
312
313/*RAID Action Reply ActionData union */
314typedef union _MPI2_RAID_ACTION_REPLY_DATA {
315 U32 Word[5];
316 MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
317 U16 VolDevHandle;
318 U8 VolumeState;
319 U8 PhysDiskNum;
320 MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult;
321} MPI2_RAID_ACTION_REPLY_DATA, *PTR_MPI2_RAID_ACTION_REPLY_DATA,
322 Mpi2RaidActionReplyData_t, *pMpi2RaidActionReplyData_t;
323
324/*use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for
325 *MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
326
327/*RAID Action Reply Message */
328typedef struct _MPI2_RAID_ACTION_REPLY {
329 U8 Action; /*0x00 */
330 U8 Reserved1; /*0x01 */
331 U8 MsgLength; /*0x02 */
332 U8 Function; /*0x03 */
333 U16 VolDevHandle; /*0x04 */
334 U8 PhysDiskNum; /*0x06 */
335 U8 MsgFlags; /*0x07 */
336 U8 VP_ID; /*0x08 */
337 U8 VF_ID; /*0x09 */
338 U16 Reserved2; /*0x0A */
339 U16 Reserved3; /*0x0C */
340 U16 IOCStatus; /*0x0E */
341 U32 IOCLogInfo; /*0x10 */
342 MPI2_RAID_ACTION_REPLY_DATA ActionData; /*0x14 */
343} MPI2_RAID_ACTION_REPLY, *PTR_MPI2_RAID_ACTION_REPLY,
344 Mpi2RaidActionReply_t, *pMpi2RaidActionReply_t;
345
346#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_sas.h b/drivers/scsi/mpt3sas/mpi/mpi2_sas.h
new file mode 100644
index 000000000000..b4e7084aba31
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_sas.h
@@ -0,0 +1,295 @@
1/*
2 * Copyright (c) 2000-2012 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_sas.h Version: 02.00.07
10 *
11 * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
12 * prefix are for use only on MPI v2.5 products, and must not be used
13 * with MPI v2.0 products. Unless otherwise noted, names beginning with
14 * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
15 *
16 * Version History
17 * ---------------
18 *
19 * Date Version Description
20 * -------- -------- ------------------------------------------------------
21 * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
22 * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit
23 * Control Request.
24 * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control
25 * Request.
26 * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
27 * to MPI2_SGE_IO_UNION since it supports chained SGLs.
28 * 05-12-10 02.00.04 Modified some comments.
29 * 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control.
30 * 11-18-11 02.00.06 Incorporating additions for MPI v2.5.
31 * 07-10-12 02.00.07 Added MPI2_SATA_PT_SGE_UNION for use in the SATA
32 * Passthrough Request message.
33 * --------------------------------------------------------------------------
34 */
35
36#ifndef MPI2_SAS_H
37#define MPI2_SAS_H
38
39/*
40 *Values for SASStatus.
41 */
42#define MPI2_SASSTATUS_SUCCESS (0x00)
43#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01)
44#define MPI2_SASSTATUS_INVALID_FRAME (0x02)
45#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03)
46#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04)
47#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05)
48#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06)
49#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07)
50#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08)
51#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09)
52#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A)
53#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B)
54#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C)
55#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D)
56#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E)
57#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F)
58#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10)
59#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11)
60#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12)
61#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13)
62#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14)
63
64/*
65 *Values for the SAS DeviceInfo field used in SAS Device Status Change Event
66 *data and SAS Configuration pages.
67 */
68#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000)
69#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
70#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
71#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
72#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400)
73#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200)
74#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100)
75#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080)
76#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040)
77#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020)
78#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010)
79#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008)
80
81#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
82#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000)
83#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001)
84#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
85#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
86
87/*****************************************************************************
88*
89* SAS Messages
90*
91*****************************************************************************/
92
93/****************************************************************************
94* SMP Passthrough messages
95****************************************************************************/
96
97/*SMP Passthrough Request Message */
98typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST {
99 U8 PassthroughFlags; /*0x00 */
100 U8 PhysicalPort; /*0x01 */
101 U8 ChainOffset; /*0x02 */
102 U8 Function; /*0x03 */
103 U16 RequestDataLength; /*0x04 */
104 U8 SGLFlags; /*0x06*//*MPI v2.0 only. Reserved on MPI v2.5*/
105 U8 MsgFlags; /*0x07 */
106 U8 VP_ID; /*0x08 */
107 U8 VF_ID; /*0x09 */
108 U16 Reserved1; /*0x0A */
109 U32 Reserved2; /*0x0C */
110 U64 SASAddress; /*0x10 */
111 U32 Reserved3; /*0x18 */
112 U32 Reserved4; /*0x1C */
113 MPI2_SIMPLE_SGE_UNION SGL;/*0x20 */
114} MPI2_SMP_PASSTHROUGH_REQUEST, *PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
115 Mpi2SmpPassthroughRequest_t, *pMpi2SmpPassthroughRequest_t;
116
117/*values for PassthroughFlags field */
118#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
119
120/*MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
121
122/*SMP Passthrough Reply Message */
123typedef struct _MPI2_SMP_PASSTHROUGH_REPLY {
124 U8 PassthroughFlags; /*0x00 */
125 U8 PhysicalPort; /*0x01 */
126 U8 MsgLength; /*0x02 */
127 U8 Function; /*0x03 */
128 U16 ResponseDataLength; /*0x04 */
129 U8 SGLFlags; /*0x06 */
130 U8 MsgFlags; /*0x07 */
131 U8 VP_ID; /*0x08 */
132 U8 VF_ID; /*0x09 */
133 U16 Reserved1; /*0x0A */
134 U8 Reserved2; /*0x0C */
135 U8 SASStatus; /*0x0D */
136 U16 IOCStatus; /*0x0E */
137 U32 IOCLogInfo; /*0x10 */
138 U32 Reserved3; /*0x14 */
139 U8 ResponseData[4]; /*0x18 */
140} MPI2_SMP_PASSTHROUGH_REPLY, *PTR_MPI2_SMP_PASSTHROUGH_REPLY,
141 Mpi2SmpPassthroughReply_t, *pMpi2SmpPassthroughReply_t;
142
143/*values for PassthroughFlags field */
144#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
145
146/*values for SASStatus field are at the top of this file */
147
148/****************************************************************************
149* SATA Passthrough messages
150****************************************************************************/
151
152typedef union _MPI2_SATA_PT_SGE_UNION {
153 MPI2_SGE_SIMPLE_UNION MpiSimple; /*MPI v2.0 only */
154 MPI2_SGE_CHAIN_UNION MpiChain; /*MPI v2.0 only */
155 MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
156 MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; /*MPI v2.0 only */
157 MPI25_IEEE_SGE_CHAIN64 IeeeChain64; /*MPI v2.5 only */
158} MPI2_SATA_PT_SGE_UNION, *PTR_MPI2_SATA_PT_SGE_UNION,
159 Mpi2SataPTSGEUnion_t, *pMpi2SataPTSGEUnion_t;
160
161/*SATA Passthrough Request Message */
162typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST {
163 U16 DevHandle; /*0x00 */
164 U8 ChainOffset; /*0x02 */
165 U8 Function; /*0x03 */
166 U16 PassthroughFlags; /*0x04 */
167 U8 SGLFlags; /*0x06*//*MPI v2.0 only. Reserved on MPI v2.5*/
168 U8 MsgFlags; /*0x07 */
169 U8 VP_ID; /*0x08 */
170 U8 VF_ID; /*0x09 */
171 U16 Reserved1; /*0x0A */
172 U32 Reserved2; /*0x0C */
173 U32 Reserved3; /*0x10 */
174 U32 Reserved4; /*0x14 */
175 U32 DataLength; /*0x18 */
176 U8 CommandFIS[20]; /*0x1C */
177 MPI2_SATA_PT_SGE_UNION SGL;/*0x30*//*MPI v2.5: IEEE 64 elements only*/
178} MPI2_SATA_PASSTHROUGH_REQUEST, *PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
179 Mpi2SataPassthroughRequest_t,
180 *pMpi2SataPassthroughRequest_t;
181
182/*values for PassthroughFlags field */
183#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
184#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
185#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
186#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
187#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
188#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
189
190/*MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
191
192/*SATA Passthrough Reply Message */
193typedef struct _MPI2_SATA_PASSTHROUGH_REPLY {
194 U16 DevHandle; /*0x00 */
195 U8 MsgLength; /*0x02 */
196 U8 Function; /*0x03 */
197 U16 PassthroughFlags; /*0x04 */
198 U8 SGLFlags; /*0x06 */
199 U8 MsgFlags; /*0x07 */
200 U8 VP_ID; /*0x08 */
201 U8 VF_ID; /*0x09 */
202 U16 Reserved1; /*0x0A */
203 U8 Reserved2; /*0x0C */
204 U8 SASStatus; /*0x0D */
205 U16 IOCStatus; /*0x0E */
206 U32 IOCLogInfo; /*0x10 */
207 U8 StatusFIS[20]; /*0x14 */
208 U32 StatusControlRegisters; /*0x28 */
209 U32 TransferCount; /*0x2C */
210} MPI2_SATA_PASSTHROUGH_REPLY, *PTR_MPI2_SATA_PASSTHROUGH_REPLY,
211 Mpi2SataPassthroughReply_t, *pMpi2SataPassthroughReply_t;
212
213/*values for SASStatus field are at the top of this file */
214
215/****************************************************************************
216* SAS IO Unit Control messages
217****************************************************************************/
218
219/*SAS IO Unit Control Request Message */
220typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST {
221 U8 Operation; /*0x00 */
222 U8 Reserved1; /*0x01 */
223 U8 ChainOffset; /*0x02 */
224 U8 Function; /*0x03 */
225 U16 DevHandle; /*0x04 */
226 U8 IOCParameter; /*0x06 */
227 U8 MsgFlags; /*0x07 */
228 U8 VP_ID; /*0x08 */
229 U8 VF_ID; /*0x09 */
230 U16 Reserved3; /*0x0A */
231 U16 Reserved4; /*0x0C */
232 U8 PhyNum; /*0x0E */
233 U8 PrimFlags; /*0x0F */
234 U32 Primitive; /*0x10 */
235 U8 LookupMethod; /*0x14 */
236 U8 Reserved5; /*0x15 */
237 U16 SlotNumber; /*0x16 */
238 U64 LookupAddress; /*0x18 */
239 U32 IOCParameterValue; /*0x20 */
240 U32 Reserved7; /*0x24 */
241 U32 Reserved8; /*0x28 */
242} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
243 *PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
244 Mpi2SasIoUnitControlRequest_t,
245 *pMpi2SasIoUnitControlRequest_t;
246
247/*values for the Operation field */
248#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
249#define MPI2_SAS_OP_PHY_LINK_RESET (0x06)
250#define MPI2_SAS_OP_PHY_HARD_RESET (0x07)
251#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
252#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A)
253#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B)
254#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
255#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D)
256#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E)
257#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F)
258#define MPI25_SAS_OP_ENABLE_FP_DEVICE (0x10)
259#define MPI25_SAS_OP_DISABLE_FP_DEVICE (0x11)
260#define MPI25_SAS_OP_ENABLE_FP_ALL (0x12)
261#define MPI25_SAS_OP_DISABLE_FP_ALL (0x13)
262#define MPI2_SAS_OP_DEV_ENABLE_NCQ (0x14)
263#define MPI2_SAS_OP_DEV_DISABLE_NCQ (0x15)
264#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80)
265
266/*values for the PrimFlags field */
267#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08)
268#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02)
269#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01)
270
271/*values for the LookupMethod field */
272#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01)
273#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02)
274#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03)
275
276/*SAS IO Unit Control Reply Message */
277typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY {
278 U8 Operation; /*0x00 */
279 U8 Reserved1; /*0x01 */
280 U8 MsgLength; /*0x02 */
281 U8 Function; /*0x03 */
282 U16 DevHandle; /*0x04 */
283 U8 IOCParameter; /*0x06 */
284 U8 MsgFlags; /*0x07 */
285 U8 VP_ID; /*0x08 */
286 U8 VF_ID; /*0x09 */
287 U16 Reserved3; /*0x0A */
288 U16 Reserved4; /*0x0C */
289 U16 IOCStatus; /*0x0E */
290 U32 IOCLogInfo; /*0x10 */
291} MPI2_SAS_IOUNIT_CONTROL_REPLY,
292 *PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
293 Mpi2SasIoUnitControlReply_t, *pMpi2SasIoUnitControlReply_t;
294
295#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
new file mode 100644
index 000000000000..71453d11c1c1
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h
@@ -0,0 +1,437 @@
1/*
2 * Copyright (c) 2000-2012 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.09
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 * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool.
21 * 07-30-09 02.00.04 Added ExtendedType field to DiagnosticBufferPost request
22 * and reply messages.
23 * Added MPI2_DIAG_BUF_TYPE_EXTENDED.
24 * Incremented MPI2_DIAG_BUF_TYPE_COUNT.
25 * 05-12-10 02.00.05 Added Diagnostic Data Upload tool.
26 * 08-11-10 02.00.06 Added defines that were missing for Diagnostic Buffer
27 * Post Request.
28 * 05-25-11 02.00.07 Added Flags field and related defines to
29 * MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST.
30 * 11-18-11 02.00.08 Incorporating additions for MPI v2.5.
31 * 07-10-12 02.00.09 Add MPI v2.5 Toolbox Diagnostic CLI Tool Request
32 * message.
33 * --------------------------------------------------------------------------
34 */
35
36#ifndef MPI2_TOOL_H
37#define MPI2_TOOL_H
38
39/*****************************************************************************
40*
41* Toolbox Messages
42*
43*****************************************************************************/
44
45/*defines for the Tools */
46#define MPI2_TOOLBOX_CLEAN_TOOL (0x00)
47#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01)
48#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02)
49#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03)
50#define MPI2_TOOLBOX_BEACON_TOOL (0x05)
51#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06)
52
53/****************************************************************************
54* Toolbox reply
55****************************************************************************/
56
57typedef struct _MPI2_TOOLBOX_REPLY {
58 U8 Tool; /*0x00 */
59 U8 Reserved1; /*0x01 */
60 U8 MsgLength; /*0x02 */
61 U8 Function; /*0x03 */
62 U16 Reserved2; /*0x04 */
63 U8 Reserved3; /*0x06 */
64 U8 MsgFlags; /*0x07 */
65 U8 VP_ID; /*0x08 */
66 U8 VF_ID; /*0x09 */
67 U16 Reserved4; /*0x0A */
68 U16 Reserved5; /*0x0C */
69 U16 IOCStatus; /*0x0E */
70 U32 IOCLogInfo; /*0x10 */
71} MPI2_TOOLBOX_REPLY, *PTR_MPI2_TOOLBOX_REPLY,
72 Mpi2ToolboxReply_t, *pMpi2ToolboxReply_t;
73
74/****************************************************************************
75* Toolbox Clean Tool request
76****************************************************************************/
77
78typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST {
79 U8 Tool; /*0x00 */
80 U8 Reserved1; /*0x01 */
81 U8 ChainOffset; /*0x02 */
82 U8 Function; /*0x03 */
83 U16 Reserved2; /*0x04 */
84 U8 Reserved3; /*0x06 */
85 U8 MsgFlags; /*0x07 */
86 U8 VP_ID; /*0x08 */
87 U8 VF_ID; /*0x09 */
88 U16 Reserved4; /*0x0A */
89 U32 Flags; /*0x0C */
90} MPI2_TOOLBOX_CLEAN_REQUEST, *PTR_MPI2_TOOLBOX_CLEAN_REQUEST,
91 Mpi2ToolboxCleanRequest_t, *pMpi2ToolboxCleanRequest_t;
92
93/*values for the Flags field */
94#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000)
95#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000)
96#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000)
97#define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000)
98#define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000)
99#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000)
100#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000)
101#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004)
102#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002)
103#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001)
104
105/****************************************************************************
106* Toolbox Memory Move request
107****************************************************************************/
108
109typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST {
110 U8 Tool; /*0x00 */
111 U8 Reserved1; /*0x01 */
112 U8 ChainOffset; /*0x02 */
113 U8 Function; /*0x03 */
114 U16 Reserved2; /*0x04 */
115 U8 Reserved3; /*0x06 */
116 U8 MsgFlags; /*0x07 */
117 U8 VP_ID; /*0x08 */
118 U8 VF_ID; /*0x09 */
119 U16 Reserved4; /*0x0A */
120 MPI2_SGE_SIMPLE_UNION SGL; /*0x0C */
121} MPI2_TOOLBOX_MEM_MOVE_REQUEST, *PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST,
122 Mpi2ToolboxMemMoveRequest_t, *pMpi2ToolboxMemMoveRequest_t;
123
124/****************************************************************************
125* Toolbox Diagnostic Data Upload request
126****************************************************************************/
127
128typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST {
129 U8 Tool; /*0x00 */
130 U8 Reserved1; /*0x01 */
131 U8 ChainOffset; /*0x02 */
132 U8 Function; /*0x03 */
133 U16 Reserved2; /*0x04 */
134 U8 Reserved3; /*0x06 */
135 U8 MsgFlags; /*0x07 */
136 U8 VP_ID; /*0x08 */
137 U8 VF_ID; /*0x09 */
138 U16 Reserved4; /*0x0A */
139 U8 SGLFlags; /*0x0C */
140 U8 Reserved5; /*0x0D */
141 U16 Reserved6; /*0x0E */
142 U32 Flags; /*0x10 */
143 U32 DataLength; /*0x14 */
144 MPI2_SGE_SIMPLE_UNION SGL; /*0x18 */
145} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
146 *PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
147 Mpi2ToolboxDiagDataUploadRequest_t,
148 *pMpi2ToolboxDiagDataUploadRequest_t;
149
150/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
151
152typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER {
153 U32 DiagDataLength; /*00h */
154 U8 FormatCode; /*04h */
155 U8 Reserved1; /*05h */
156 U16 Reserved2; /*06h */
157} MPI2_DIAG_DATA_UPLOAD_HEADER, *PTR_MPI2_DIAG_DATA_UPLOAD_HEADER,
158 Mpi2DiagDataUploadHeader_t, *pMpi2DiagDataUploadHeader_t;
159
160/****************************************************************************
161* Toolbox ISTWI Read Write Tool
162****************************************************************************/
163
164/*Toolbox ISTWI Read Write Tool request message */
165typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST {
166 U8 Tool; /*0x00 */
167 U8 Reserved1; /*0x01 */
168 U8 ChainOffset; /*0x02 */
169 U8 Function; /*0x03 */
170 U16 Reserved2; /*0x04 */
171 U8 Reserved3; /*0x06 */
172 U8 MsgFlags; /*0x07 */
173 U8 VP_ID; /*0x08 */
174 U8 VF_ID; /*0x09 */
175 U16 Reserved4; /*0x0A */
176 U32 Reserved5; /*0x0C */
177 U32 Reserved6; /*0x10 */
178 U8 DevIndex; /*0x14 */
179 U8 Action; /*0x15 */
180 U8 SGLFlags; /*0x16 */
181 U8 Flags; /*0x17 */
182 U16 TxDataLength; /*0x18 */
183 U16 RxDataLength; /*0x1A */
184 U32 Reserved8; /*0x1C */
185 U32 Reserved9; /*0x20 */
186 U32 Reserved10; /*0x24 */
187 U32 Reserved11; /*0x28 */
188 U32 Reserved12; /*0x2C */
189 MPI2_SGE_SIMPLE_UNION SGL; /*0x30 */
190} MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
191 *PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
192 Mpi2ToolboxIstwiReadWriteRequest_t,
193 *pMpi2ToolboxIstwiReadWriteRequest_t;
194
195/*values for the Action field */
196#define MPI2_TOOL_ISTWI_ACTION_READ_DATA (0x01)
197#define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA (0x02)
198#define MPI2_TOOL_ISTWI_ACTION_SEQUENCE (0x03)
199#define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS (0x10)
200#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11)
201#define MPI2_TOOL_ISTWI_ACTION_RESET (0x12)
202
203/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
204
205/*values for the Flags field */
206#define MPI2_TOOL_ISTWI_FLAG_AUTO_RESERVE_RELEASE (0x80)
207#define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK (0x07)
208
209/*Toolbox ISTWI Read Write Tool reply message */
210typedef struct _MPI2_TOOLBOX_ISTWI_REPLY {
211 U8 Tool; /*0x00 */
212 U8 Reserved1; /*0x01 */
213 U8 MsgLength; /*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 U16 Reserved5; /*0x0C */
222 U16 IOCStatus; /*0x0E */
223 U32 IOCLogInfo; /*0x10 */
224 U8 DevIndex; /*0x14 */
225 U8 Action; /*0x15 */
226 U8 IstwiStatus; /*0x16 */
227 U8 Reserved6; /*0x17 */
228 U16 TxDataCount; /*0x18 */
229 U16 RxDataCount; /*0x1A */
230} MPI2_TOOLBOX_ISTWI_REPLY, *PTR_MPI2_TOOLBOX_ISTWI_REPLY,
231 Mpi2ToolboxIstwiReply_t, *pMpi2ToolboxIstwiReply_t;
232
233/****************************************************************************
234* Toolbox Beacon Tool request
235****************************************************************************/
236
237typedef struct _MPI2_TOOLBOX_BEACON_REQUEST {
238 U8 Tool; /*0x00 */
239 U8 Reserved1; /*0x01 */
240 U8 ChainOffset; /*0x02 */
241 U8 Function; /*0x03 */
242 U16 Reserved2; /*0x04 */
243 U8 Reserved3; /*0x06 */
244 U8 MsgFlags; /*0x07 */
245 U8 VP_ID; /*0x08 */
246 U8 VF_ID; /*0x09 */
247 U16 Reserved4; /*0x0A */
248 U8 Reserved5; /*0x0C */
249 U8 PhysicalPort; /*0x0D */
250 U8 Reserved6; /*0x0E */
251 U8 Flags; /*0x0F */
252} MPI2_TOOLBOX_BEACON_REQUEST, *PTR_MPI2_TOOLBOX_BEACON_REQUEST,
253 Mpi2ToolboxBeaconRequest_t, *pMpi2ToolboxBeaconRequest_t;
254
255/*values for the Flags field */
256#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00)
257#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01)
258
259/****************************************************************************
260* Toolbox Diagnostic CLI Tool
261****************************************************************************/
262
263#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH (0x5C)
264
265/*MPI v2.0 Toolbox Diagnostic CLI Tool request message */
266typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
267 U8 Tool; /*0x00 */
268 U8 Reserved1; /*0x01 */
269 U8 ChainOffset; /*0x02 */
270 U8 Function; /*0x03 */
271 U16 Reserved2; /*0x04 */
272 U8 Reserved3; /*0x06 */
273 U8 MsgFlags; /*0x07 */
274 U8 VP_ID; /*0x08 */
275 U8 VF_ID; /*0x09 */
276 U16 Reserved4; /*0x0A */
277 U8 SGLFlags; /*0x0C */
278 U8 Reserved5; /*0x0D */
279 U16 Reserved6; /*0x0E */
280 U32 DataLength; /*0x10 */
281 U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */
282 MPI2_SGE_SIMPLE_UNION SGL; /*0x70 */
283} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
284 *PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
285 Mpi2ToolboxDiagnosticCliRequest_t,
286 *pMpi2ToolboxDiagnosticCliRequest_t;
287
288/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
289
290/*MPI v2.5 Toolbox Diagnostic CLI Tool request message */
291typedef struct _MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST {
292 U8 Tool; /*0x00 */
293 U8 Reserved1; /*0x01 */
294 U8 ChainOffset; /*0x02 */
295 U8 Function; /*0x03 */
296 U16 Reserved2; /*0x04 */
297 U8 Reserved3; /*0x06 */
298 U8 MsgFlags; /*0x07 */
299 U8 VP_ID; /*0x08 */
300 U8 VF_ID; /*0x09 */
301 U16 Reserved4; /*0x0A */
302 U32 Reserved5; /*0x0C */
303 U32 DataLength; /*0x10 */
304 U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */
305 MPI25_SGE_IO_UNION SGL; /*0x70 */
306} MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
307 *PTR_MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
308 Mpi25ToolboxDiagnosticCliRequest_t,
309 *pMpi25ToolboxDiagnosticCliRequest_t;
310
311/*Toolbox Diagnostic CLI Tool reply message */
312typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY {
313 U8 Tool; /*0x00 */
314 U8 Reserved1; /*0x01 */
315 U8 MsgLength; /*0x02 */
316 U8 Function; /*0x03 */
317 U16 Reserved2; /*0x04 */
318 U8 Reserved3; /*0x06 */
319 U8 MsgFlags; /*0x07 */
320 U8 VP_ID; /*0x08 */
321 U8 VF_ID; /*0x09 */
322 U16 Reserved4; /*0x0A */
323 U16 Reserved5; /*0x0C */
324 U16 IOCStatus; /*0x0E */
325 U32 IOCLogInfo; /*0x10 */
326 U32 ReturnedDataLength; /*0x14 */
327} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY,
328 *PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY,
329 Mpi2ToolboxDiagnosticCliReply_t,
330 *pMpi2ToolboxDiagnosticCliReply_t;
331
332/*****************************************************************************
333*
334* Diagnostic Buffer Messages
335*
336*****************************************************************************/
337
338/****************************************************************************
339* Diagnostic Buffer Post request
340****************************************************************************/
341
342typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST {
343 U8 ExtendedType; /*0x00 */
344 U8 BufferType; /*0x01 */
345 U8 ChainOffset; /*0x02 */
346 U8 Function; /*0x03 */
347 U16 Reserved2; /*0x04 */
348 U8 Reserved3; /*0x06 */
349 U8 MsgFlags; /*0x07 */
350 U8 VP_ID; /*0x08 */
351 U8 VF_ID; /*0x09 */
352 U16 Reserved4; /*0x0A */
353 U64 BufferAddress; /*0x0C */
354 U32 BufferLength; /*0x14 */
355 U32 Reserved5; /*0x18 */
356 U32 Reserved6; /*0x1C */
357 U32 Flags; /*0x20 */
358 U32 ProductSpecific[23]; /*0x24 */
359} MPI2_DIAG_BUFFER_POST_REQUEST, *PTR_MPI2_DIAG_BUFFER_POST_REQUEST,
360 Mpi2DiagBufferPostRequest_t, *pMpi2DiagBufferPostRequest_t;
361
362/*values for the ExtendedType field */
363#define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION (0x02)
364
365/*values for the BufferType field */
366#define MPI2_DIAG_BUF_TYPE_TRACE (0x00)
367#define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01)
368#define MPI2_DIAG_BUF_TYPE_EXTENDED (0x02)
369/*count of the number of buffer types */
370#define MPI2_DIAG_BUF_TYPE_COUNT (0x03)
371
372/*values for the Flags field */
373#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL (0x00000002)
374#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE (0x00000001)
375
376/****************************************************************************
377* Diagnostic Buffer Post reply
378****************************************************************************/
379
380typedef struct _MPI2_DIAG_BUFFER_POST_REPLY {
381 U8 ExtendedType; /*0x00 */
382 U8 BufferType; /*0x01 */
383 U8 MsgLength; /*0x02 */
384 U8 Function; /*0x03 */
385 U16 Reserved2; /*0x04 */
386 U8 Reserved3; /*0x06 */
387 U8 MsgFlags; /*0x07 */
388 U8 VP_ID; /*0x08 */
389 U8 VF_ID; /*0x09 */
390 U16 Reserved4; /*0x0A */
391 U16 Reserved5; /*0x0C */
392 U16 IOCStatus; /*0x0E */
393 U32 IOCLogInfo; /*0x10 */
394 U32 TransferLength; /*0x14 */
395} MPI2_DIAG_BUFFER_POST_REPLY, *PTR_MPI2_DIAG_BUFFER_POST_REPLY,
396 Mpi2DiagBufferPostReply_t, *pMpi2DiagBufferPostReply_t;
397
398/****************************************************************************
399* Diagnostic Release request
400****************************************************************************/
401
402typedef struct _MPI2_DIAG_RELEASE_REQUEST {
403 U8 Reserved1; /*0x00 */
404 U8 BufferType; /*0x01 */
405 U8 ChainOffset; /*0x02 */
406 U8 Function; /*0x03 */
407 U16 Reserved2; /*0x04 */
408 U8 Reserved3; /*0x06 */
409 U8 MsgFlags; /*0x07 */
410 U8 VP_ID; /*0x08 */
411 U8 VF_ID; /*0x09 */
412 U16 Reserved4; /*0x0A */
413} MPI2_DIAG_RELEASE_REQUEST, *PTR_MPI2_DIAG_RELEASE_REQUEST,
414 Mpi2DiagReleaseRequest_t, *pMpi2DiagReleaseRequest_t;
415
416/****************************************************************************
417* Diagnostic Buffer Post reply
418****************************************************************************/
419
420typedef struct _MPI2_DIAG_RELEASE_REPLY {
421 U8 Reserved1; /*0x00 */
422 U8 BufferType; /*0x01 */
423 U8 MsgLength; /*0x02 */
424 U8 Function; /*0x03 */
425 U16 Reserved2; /*0x04 */
426 U8 Reserved3; /*0x06 */
427 U8 MsgFlags; /*0x07 */
428 U8 VP_ID; /*0x08 */
429 U8 VF_ID; /*0x09 */
430 U16 Reserved4; /*0x0A */
431 U16 Reserved5; /*0x0C */
432 U16 IOCStatus; /*0x0E */
433 U32 IOCLogInfo; /*0x10 */
434} MPI2_DIAG_RELEASE_REPLY, *PTR_MPI2_DIAG_RELEASE_REPLY,
435 Mpi2DiagReleaseReply_t, *pMpi2DiagReleaseReply_t;
436
437#endif
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_type.h b/drivers/scsi/mpt3sas/mpi/mpi2_type.h
new file mode 100644
index 000000000000..516f959573f5
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_type.h
@@ -0,0 +1,56 @@
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 * Define * if it hasn't already been defined. By default
25 * * is defined to be a near pointer. MPI2_POINTER can be defined as
26 * a far pointer by defining * as "far *" before this header file is
27 * included.
28 */
29
30/* the basic types may have already been included by mpi_type.h */
31#ifndef MPI_TYPE_H
32/*****************************************************************************
33*
34* Basic Types
35*
36*****************************************************************************/
37
38typedef u8 U8;
39typedef __le16 U16;
40typedef __le32 U32;
41typedef __le64 U64 __attribute__ ((aligned(4)));
42
43/*****************************************************************************
44*
45* Pointer Types
46*
47*****************************************************************************/
48
49typedef U8 *PU8;
50typedef U16 *PU16;
51typedef U32 *PU32;
52typedef U64 *PU64;
53
54#endif
55
56#endif
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
new file mode 100644
index 000000000000..04f8010f0770
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -0,0 +1,4840 @@
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/mpt3sas/mpt3sas_base.c
6 * Copyright (C) 2012 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/io.h>
59#include <linux/time.h>
60#include <linux/kthread.h>
61#include <linux/aer.h>
62
63
64#include "mpt3sas_base.h"
65
66static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
67
68
69#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
70
71 /* maximum controller queue depth */
72#define MAX_HBA_QUEUE_DEPTH 30000
73#define MAX_CHAIN_DEPTH 100000
74static int max_queue_depth = -1;
75module_param(max_queue_depth, int, 0);
76MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
77
78static int max_sgl_entries = -1;
79module_param(max_sgl_entries, int, 0);
80MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
81
82static int msix_disable = -1;
83module_param(msix_disable, int, 0);
84MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
85
86
87static int mpt3sas_fwfault_debug;
88MODULE_PARM_DESC(mpt3sas_fwfault_debug,
89 " enable detection of firmware fault and halt firmware - (default=0)");
90
91
92/**
93 * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
94 *
95 */
96static int
97_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
98{
99 int ret = param_set_int(val, kp);
100 struct MPT3SAS_ADAPTER *ioc;
101
102 if (ret)
103 return ret;
104
105 pr_info("setting fwfault_debug(%d)\n", mpt3sas_fwfault_debug);
106 list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
107 ioc->fwfault_debug = mpt3sas_fwfault_debug;
108 return 0;
109}
110module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug,
111 param_get_int, &mpt3sas_fwfault_debug, 0644);
112
113/**
114 * mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc
115 * @arg: input argument, used to derive ioc
116 *
117 * Return 0 if controller is removed from pci subsystem.
118 * Return -1 for other case.
119 */
120static int mpt3sas_remove_dead_ioc_func(void *arg)
121{
122 struct MPT3SAS_ADAPTER *ioc = (struct MPT3SAS_ADAPTER *)arg;
123 struct pci_dev *pdev;
124
125 if ((ioc == NULL))
126 return -1;
127
128 pdev = ioc->pdev;
129 if ((pdev == NULL))
130 return -1;
131 pci_stop_and_remove_bus_device(pdev);
132 return 0;
133}
134
135/**
136 * _base_fault_reset_work - workq handling ioc fault conditions
137 * @work: input argument, used to derive ioc
138 * Context: sleep.
139 *
140 * Return nothing.
141 */
142static void
143_base_fault_reset_work(struct work_struct *work)
144{
145 struct MPT3SAS_ADAPTER *ioc =
146 container_of(work, struct MPT3SAS_ADAPTER, fault_reset_work.work);
147 unsigned long flags;
148 u32 doorbell;
149 int rc;
150 struct task_struct *p;
151
152
153 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
154 if (ioc->shost_recovery)
155 goto rearm_timer;
156 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
157
158 doorbell = mpt3sas_base_get_iocstate(ioc, 0);
159 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) {
160 pr_err(MPT3SAS_FMT "SAS host is non-operational !!!!\n",
161 ioc->name);
162
163 /*
164 * Call _scsih_flush_pending_cmds callback so that we flush all
165 * pending commands back to OS. This call is required to aovid
166 * deadlock at block layer. Dead IOC will fail to do diag reset,
167 * and this call is safe since dead ioc will never return any
168 * command back from HW.
169 */
170 ioc->schedule_dead_ioc_flush_running_cmds(ioc);
171 /*
172 * Set remove_host flag early since kernel thread will
173 * take some time to execute.
174 */
175 ioc->remove_host = 1;
176 /*Remove the Dead Host */
177 p = kthread_run(mpt3sas_remove_dead_ioc_func, ioc,
178 "mpt3sas_dead_ioc_%d", ioc->id);
179 if (IS_ERR(p))
180 pr_err(MPT3SAS_FMT
181 "%s: Running mpt3sas_dead_ioc thread failed !!!!\n",
182 ioc->name, __func__);
183 else
184 pr_err(MPT3SAS_FMT
185 "%s: Running mpt3sas_dead_ioc thread success !!!!\n",
186 ioc->name, __func__);
187 return; /* don't rearm timer */
188 }
189
190 if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) {
191 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
192 FORCE_BIG_HAMMER);
193 pr_warn(MPT3SAS_FMT "%s: hard reset: %s\n", ioc->name,
194 __func__, (rc == 0) ? "success" : "failed");
195 doorbell = mpt3sas_base_get_iocstate(ioc, 0);
196 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
197 mpt3sas_base_fault_info(ioc, doorbell &
198 MPI2_DOORBELL_DATA_MASK);
199 if (rc && (doorbell & MPI2_IOC_STATE_MASK) !=
200 MPI2_IOC_STATE_OPERATIONAL)
201 return; /* don't rearm timer */
202 }
203
204 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
205 rearm_timer:
206 if (ioc->fault_reset_work_q)
207 queue_delayed_work(ioc->fault_reset_work_q,
208 &ioc->fault_reset_work,
209 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
210 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
211}
212
213/**
214 * mpt3sas_base_start_watchdog - start the fault_reset_work_q
215 * @ioc: per adapter object
216 * Context: sleep.
217 *
218 * Return nothing.
219 */
220void
221mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc)
222{
223 unsigned long flags;
224
225 if (ioc->fault_reset_work_q)
226 return;
227
228 /* initialize fault polling */
229
230 INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
231 snprintf(ioc->fault_reset_work_q_name,
232 sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
233 ioc->fault_reset_work_q =
234 create_singlethread_workqueue(ioc->fault_reset_work_q_name);
235 if (!ioc->fault_reset_work_q) {
236 pr_err(MPT3SAS_FMT "%s: failed (line=%d)\n",
237 ioc->name, __func__, __LINE__);
238 return;
239 }
240 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
241 if (ioc->fault_reset_work_q)
242 queue_delayed_work(ioc->fault_reset_work_q,
243 &ioc->fault_reset_work,
244 msecs_to_jiffies(FAULT_POLLING_INTERVAL));
245 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
246}
247
248/**
249 * mpt3sas_base_stop_watchdog - stop the fault_reset_work_q
250 * @ioc: per adapter object
251 * Context: sleep.
252 *
253 * Return nothing.
254 */
255void
256mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc)
257{
258 unsigned long flags;
259 struct workqueue_struct *wq;
260
261 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
262 wq = ioc->fault_reset_work_q;
263 ioc->fault_reset_work_q = NULL;
264 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
265 if (wq) {
266 if (!cancel_delayed_work(&ioc->fault_reset_work))
267 flush_workqueue(wq);
268 destroy_workqueue(wq);
269 }
270}
271
272/**
273 * mpt3sas_base_fault_info - verbose translation of firmware FAULT code
274 * @ioc: per adapter object
275 * @fault_code: fault code
276 *
277 * Return nothing.
278 */
279void
280mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code)
281{
282 pr_err(MPT3SAS_FMT "fault_state(0x%04x)!\n",
283 ioc->name, fault_code);
284}
285
286/**
287 * mpt3sas_halt_firmware - halt's mpt controller firmware
288 * @ioc: per adapter object
289 *
290 * For debugging timeout related issues. Writing 0xCOFFEE00
291 * to the doorbell register will halt controller firmware. With
292 * the purpose to stop both driver and firmware, the enduser can
293 * obtain a ring buffer from controller UART.
294 */
295void
296mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc)
297{
298 u32 doorbell;
299
300 if (!ioc->fwfault_debug)
301 return;
302
303 dump_stack();
304
305 doorbell = readl(&ioc->chip->Doorbell);
306 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
307 mpt3sas_base_fault_info(ioc , doorbell);
308 else {
309 writel(0xC0FFEE00, &ioc->chip->Doorbell);
310 pr_err(MPT3SAS_FMT "Firmware is halted due to command timeout\n",
311 ioc->name);
312 }
313
314 if (ioc->fwfault_debug == 2)
315 for (;;)
316 ;
317 else
318 panic("panic in %s\n", __func__);
319}
320
321#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
322/**
323 * _base_sas_ioc_info - verbose translation of the ioc status
324 * @ioc: per adapter object
325 * @mpi_reply: reply mf payload returned from firmware
326 * @request_hdr: request mf
327 *
328 * Return nothing.
329 */
330static void
331_base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
332 MPI2RequestHeader_t *request_hdr)
333{
334 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
335 MPI2_IOCSTATUS_MASK;
336 char *desc = NULL;
337 u16 frame_sz;
338 char *func_str = NULL;
339
340 /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
341 if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
342 request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
343 request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
344 return;
345
346 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
347 return;
348
349 switch (ioc_status) {
350
351/****************************************************************************
352* Common IOCStatus values for all replies
353****************************************************************************/
354
355 case MPI2_IOCSTATUS_INVALID_FUNCTION:
356 desc = "invalid function";
357 break;
358 case MPI2_IOCSTATUS_BUSY:
359 desc = "busy";
360 break;
361 case MPI2_IOCSTATUS_INVALID_SGL:
362 desc = "invalid sgl";
363 break;
364 case MPI2_IOCSTATUS_INTERNAL_ERROR:
365 desc = "internal error";
366 break;
367 case MPI2_IOCSTATUS_INVALID_VPID:
368 desc = "invalid vpid";
369 break;
370 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
371 desc = "insufficient resources";
372 break;
373 case MPI2_IOCSTATUS_INVALID_FIELD:
374 desc = "invalid field";
375 break;
376 case MPI2_IOCSTATUS_INVALID_STATE:
377 desc = "invalid state";
378 break;
379 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
380 desc = "op state not supported";
381 break;
382
383/****************************************************************************
384* Config IOCStatus values
385****************************************************************************/
386
387 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
388 desc = "config invalid action";
389 break;
390 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
391 desc = "config invalid type";
392 break;
393 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
394 desc = "config invalid page";
395 break;
396 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
397 desc = "config invalid data";
398 break;
399 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
400 desc = "config no defaults";
401 break;
402 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
403 desc = "config cant commit";
404 break;
405
406/****************************************************************************
407* SCSI IO Reply
408****************************************************************************/
409
410 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
411 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
412 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
413 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
414 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
415 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
416 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
417 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
418 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
419 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
420 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
421 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
422 break;
423
424/****************************************************************************
425* For use by SCSI Initiator and SCSI Target end-to-end data protection
426****************************************************************************/
427
428 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
429 desc = "eedp guard error";
430 break;
431 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
432 desc = "eedp ref tag error";
433 break;
434 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
435 desc = "eedp app tag error";
436 break;
437
438/****************************************************************************
439* SCSI Target values
440****************************************************************************/
441
442 case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
443 desc = "target invalid io index";
444 break;
445 case MPI2_IOCSTATUS_TARGET_ABORTED:
446 desc = "target aborted";
447 break;
448 case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
449 desc = "target no conn retryable";
450 break;
451 case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
452 desc = "target no connection";
453 break;
454 case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
455 desc = "target xfer count mismatch";
456 break;
457 case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
458 desc = "target data offset error";
459 break;
460 case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
461 desc = "target too much write data";
462 break;
463 case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
464 desc = "target iu too short";
465 break;
466 case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
467 desc = "target ack nak timeout";
468 break;
469 case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
470 desc = "target nak received";
471 break;
472
473/****************************************************************************
474* Serial Attached SCSI values
475****************************************************************************/
476
477 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
478 desc = "smp request failed";
479 break;
480 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
481 desc = "smp data overrun";
482 break;
483
484/****************************************************************************
485* Diagnostic Buffer Post / Diagnostic Release values
486****************************************************************************/
487
488 case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
489 desc = "diagnostic released";
490 break;
491 default:
492 break;
493 }
494
495 if (!desc)
496 return;
497
498 switch (request_hdr->Function) {
499 case MPI2_FUNCTION_CONFIG:
500 frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
501 func_str = "config_page";
502 break;
503 case MPI2_FUNCTION_SCSI_TASK_MGMT:
504 frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
505 func_str = "task_mgmt";
506 break;
507 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
508 frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
509 func_str = "sas_iounit_ctl";
510 break;
511 case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
512 frame_sz = sizeof(Mpi2SepRequest_t);
513 func_str = "enclosure";
514 break;
515 case MPI2_FUNCTION_IOC_INIT:
516 frame_sz = sizeof(Mpi2IOCInitRequest_t);
517 func_str = "ioc_init";
518 break;
519 case MPI2_FUNCTION_PORT_ENABLE:
520 frame_sz = sizeof(Mpi2PortEnableRequest_t);
521 func_str = "port_enable";
522 break;
523 case MPI2_FUNCTION_SMP_PASSTHROUGH:
524 frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
525 func_str = "smp_passthru";
526 break;
527 default:
528 frame_sz = 32;
529 func_str = "unknown";
530 break;
531 }
532
533 pr_warn(MPT3SAS_FMT "ioc_status: %s(0x%04x), request(0x%p),(%s)\n",
534 ioc->name, desc, ioc_status, request_hdr, func_str);
535
536 _debug_dump_mf(request_hdr, frame_sz/4);
537}
538
539/**
540 * _base_display_event_data - verbose translation of firmware asyn events
541 * @ioc: per adapter object
542 * @mpi_reply: reply mf payload returned from firmware
543 *
544 * Return nothing.
545 */
546static void
547_base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
548 Mpi2EventNotificationReply_t *mpi_reply)
549{
550 char *desc = NULL;
551 u16 event;
552
553 if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
554 return;
555
556 event = le16_to_cpu(mpi_reply->Event);
557
558 switch (event) {
559 case MPI2_EVENT_LOG_DATA:
560 desc = "Log Data";
561 break;
562 case MPI2_EVENT_STATE_CHANGE:
563 desc = "Status Change";
564 break;
565 case MPI2_EVENT_HARD_RESET_RECEIVED:
566 desc = "Hard Reset Received";
567 break;
568 case MPI2_EVENT_EVENT_CHANGE:
569 desc = "Event Change";
570 break;
571 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
572 desc = "Device Status Change";
573 break;
574 case MPI2_EVENT_IR_OPERATION_STATUS:
575 desc = "IR Operation Status";
576 break;
577 case MPI2_EVENT_SAS_DISCOVERY:
578 {
579 Mpi2EventDataSasDiscovery_t *event_data =
580 (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData;
581 pr_info(MPT3SAS_FMT "Discovery: (%s)", ioc->name,
582 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
583 "start" : "stop");
584 if (event_data->DiscoveryStatus)
585 pr_info("discovery_status(0x%08x)",
586 le32_to_cpu(event_data->DiscoveryStatus));
587 pr_info("\n");
588 return;
589 }
590 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
591 desc = "SAS Broadcast Primitive";
592 break;
593 case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
594 desc = "SAS Init Device Status Change";
595 break;
596 case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
597 desc = "SAS Init Table Overflow";
598 break;
599 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
600 desc = "SAS Topology Change List";
601 break;
602 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
603 desc = "SAS Enclosure Device Status Change";
604 break;
605 case MPI2_EVENT_IR_VOLUME:
606 desc = "IR Volume";
607 break;
608 case MPI2_EVENT_IR_PHYSICAL_DISK:
609 desc = "IR Physical Disk";
610 break;
611 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
612 desc = "IR Configuration Change List";
613 break;
614 case MPI2_EVENT_LOG_ENTRY_ADDED:
615 desc = "Log Entry Added";
616 break;
617 }
618
619 if (!desc)
620 return;
621
622 pr_info(MPT3SAS_FMT "%s\n", ioc->name, desc);
623}
624#endif
625
626/**
627 * _base_sas_log_info - verbose translation of firmware log info
628 * @ioc: per adapter object
629 * @log_info: log info
630 *
631 * Return nothing.
632 */
633static void
634_base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info)
635{
636 union loginfo_type {
637 u32 loginfo;
638 struct {
639 u32 subcode:16;
640 u32 code:8;
641 u32 originator:4;
642 u32 bus_type:4;
643 } dw;
644 };
645 union loginfo_type sas_loginfo;
646 char *originator_str = NULL;
647
648 sas_loginfo.loginfo = log_info;
649 if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
650 return;
651
652 /* each nexus loss loginfo */
653 if (log_info == 0x31170000)
654 return;
655
656 /* eat the loginfos associated with task aborts */
657 if (ioc->ignore_loginfos && (log_info == 0x30050000 || log_info ==
658 0x31140000 || log_info == 0x31130000))
659 return;
660
661 switch (sas_loginfo.dw.originator) {
662 case 0:
663 originator_str = "IOP";
664 break;
665 case 1:
666 originator_str = "PL";
667 break;
668 case 2:
669 originator_str = "IR";
670 break;
671 }
672
673 pr_warn(MPT3SAS_FMT
674 "log_info(0x%08x): originator(%s), code(0x%02x), sub_code(0x%04x)\n",
675 ioc->name, log_info,
676 originator_str, sas_loginfo.dw.code,
677 sas_loginfo.dw.subcode);
678}
679
680/**
681 * _base_display_reply_info -
682 * @ioc: per adapter object
683 * @smid: system request message index
684 * @msix_index: MSIX table index supplied by the OS
685 * @reply: reply message frame(lower 32bit addr)
686 *
687 * Return nothing.
688 */
689static void
690_base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
691 u32 reply)
692{
693 MPI2DefaultReply_t *mpi_reply;
694 u16 ioc_status;
695 u32 loginfo = 0;
696
697 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
698 if (unlikely(!mpi_reply)) {
699 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
700 ioc->name, __FILE__, __LINE__, __func__);
701 return;
702 }
703 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
704#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
705 if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
706 (ioc->logging_level & MPT_DEBUG_REPLY)) {
707 _base_sas_ioc_info(ioc , mpi_reply,
708 mpt3sas_base_get_msg_frame(ioc, smid));
709 }
710#endif
711 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
712 loginfo = le32_to_cpu(mpi_reply->IOCLogInfo);
713 _base_sas_log_info(ioc, loginfo);
714 }
715
716 if (ioc_status || loginfo) {
717 ioc_status &= MPI2_IOCSTATUS_MASK;
718 mpt3sas_trigger_mpi(ioc, ioc_status, loginfo);
719 }
720}
721
722/**
723 * mpt3sas_base_done - base internal command completion routine
724 * @ioc: per adapter object
725 * @smid: system request message index
726 * @msix_index: MSIX table index supplied by the OS
727 * @reply: reply message frame(lower 32bit addr)
728 *
729 * Return 1 meaning mf should be freed from _base_interrupt
730 * 0 means the mf is freed from this function.
731 */
732u8
733mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
734 u32 reply)
735{
736 MPI2DefaultReply_t *mpi_reply;
737
738 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
739 if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
740 return 1;
741
742 if (ioc->base_cmds.status == MPT3_CMD_NOT_USED)
743 return 1;
744
745 ioc->base_cmds.status |= MPT3_CMD_COMPLETE;
746 if (mpi_reply) {
747 ioc->base_cmds.status |= MPT3_CMD_REPLY_VALID;
748 memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
749 }
750 ioc->base_cmds.status &= ~MPT3_CMD_PENDING;
751
752 complete(&ioc->base_cmds.done);
753 return 1;
754}
755
756/**
757 * _base_async_event - main callback handler for firmware asyn events
758 * @ioc: per adapter object
759 * @msix_index: MSIX table index supplied by the OS
760 * @reply: reply message frame(lower 32bit addr)
761 *
762 * Return 1 meaning mf should be freed from _base_interrupt
763 * 0 means the mf is freed from this function.
764 */
765static u8
766_base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
767{
768 Mpi2EventNotificationReply_t *mpi_reply;
769 Mpi2EventAckRequest_t *ack_request;
770 u16 smid;
771
772 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
773 if (!mpi_reply)
774 return 1;
775 if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
776 return 1;
777#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
778 _base_display_event_data(ioc, mpi_reply);
779#endif
780 if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
781 goto out;
782 smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
783 if (!smid) {
784 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
785 ioc->name, __func__);
786 goto out;
787 }
788
789 ack_request = mpt3sas_base_get_msg_frame(ioc, smid);
790 memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
791 ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
792 ack_request->Event = mpi_reply->Event;
793 ack_request->EventContext = mpi_reply->EventContext;
794 ack_request->VF_ID = 0; /* TODO */
795 ack_request->VP_ID = 0;
796 mpt3sas_base_put_smid_default(ioc, smid);
797
798 out:
799
800 /* scsih callback handler */
801 mpt3sas_scsih_event_callback(ioc, msix_index, reply);
802
803 /* ctl callback handler */
804 mpt3sas_ctl_event_callback(ioc, msix_index, reply);
805
806 return 1;
807}
808
809/**
810 * _base_get_cb_idx - obtain the callback index
811 * @ioc: per adapter object
812 * @smid: system request message index
813 *
814 * Return callback index.
815 */
816static u8
817_base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
818{
819 int i;
820 u8 cb_idx;
821
822 if (smid < ioc->hi_priority_smid) {
823 i = smid - 1;
824 cb_idx = ioc->scsi_lookup[i].cb_idx;
825 } else if (smid < ioc->internal_smid) {
826 i = smid - ioc->hi_priority_smid;
827 cb_idx = ioc->hpr_lookup[i].cb_idx;
828 } else if (smid <= ioc->hba_queue_depth) {
829 i = smid - ioc->internal_smid;
830 cb_idx = ioc->internal_lookup[i].cb_idx;
831 } else
832 cb_idx = 0xFF;
833 return cb_idx;
834}
835
836/**
837 * _base_mask_interrupts - disable interrupts
838 * @ioc: per adapter object
839 *
840 * Disabling ResetIRQ, Reply and Doorbell Interrupts
841 *
842 * Return nothing.
843 */
844static void
845_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc)
846{
847 u32 him_register;
848
849 ioc->mask_interrupts = 1;
850 him_register = readl(&ioc->chip->HostInterruptMask);
851 him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
852 writel(him_register, &ioc->chip->HostInterruptMask);
853 readl(&ioc->chip->HostInterruptMask);
854}
855
856/**
857 * _base_unmask_interrupts - enable interrupts
858 * @ioc: per adapter object
859 *
860 * Enabling only Reply Interrupts
861 *
862 * Return nothing.
863 */
864static void
865_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc)
866{
867 u32 him_register;
868
869 him_register = readl(&ioc->chip->HostInterruptMask);
870 him_register &= ~MPI2_HIM_RIM;
871 writel(him_register, &ioc->chip->HostInterruptMask);
872 ioc->mask_interrupts = 0;
873}
874
875union reply_descriptor {
876 u64 word;
877 struct {
878 u32 low;
879 u32 high;
880 } u;
881};
882
883/**
884 * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
885 * @irq: irq number (not used)
886 * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
887 * @r: pt_regs pointer (not used)
888 *
889 * Return IRQ_HANDLE if processed, else IRQ_NONE.
890 */
891static irqreturn_t
892_base_interrupt(int irq, void *bus_id)
893{
894 struct adapter_reply_queue *reply_q = bus_id;
895 union reply_descriptor rd;
896 u32 completed_cmds;
897 u8 request_desript_type;
898 u16 smid;
899 u8 cb_idx;
900 u32 reply;
901 u8 msix_index = reply_q->msix_index;
902 struct MPT3SAS_ADAPTER *ioc = reply_q->ioc;
903 Mpi2ReplyDescriptorsUnion_t *rpf;
904 u8 rc;
905
906 if (ioc->mask_interrupts)
907 return IRQ_NONE;
908
909 if (!atomic_add_unless(&reply_q->busy, 1, 1))
910 return IRQ_NONE;
911
912 rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index];
913 request_desript_type = rpf->Default.ReplyFlags
914 & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
915 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) {
916 atomic_dec(&reply_q->busy);
917 return IRQ_NONE;
918 }
919
920 completed_cmds = 0;
921 cb_idx = 0xFF;
922 do {
923 rd.word = le64_to_cpu(rpf->Words);
924 if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
925 goto out;
926 reply = 0;
927 smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
928 if (request_desript_type ==
929 MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS ||
930 request_desript_type ==
931 MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
932 cb_idx = _base_get_cb_idx(ioc, smid);
933 if ((likely(cb_idx < MPT_MAX_CALLBACKS)) &&
934 (likely(mpt_callbacks[cb_idx] != NULL))) {
935 rc = mpt_callbacks[cb_idx](ioc, smid,
936 msix_index, 0);
937 if (rc)
938 mpt3sas_base_free_smid(ioc, smid);
939 }
940 } else if (request_desript_type ==
941 MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
942 reply = le32_to_cpu(
943 rpf->AddressReply.ReplyFrameAddress);
944 if (reply > ioc->reply_dma_max_address ||
945 reply < ioc->reply_dma_min_address)
946 reply = 0;
947 if (smid) {
948 cb_idx = _base_get_cb_idx(ioc, smid);
949 if ((likely(cb_idx < MPT_MAX_CALLBACKS)) &&
950 (likely(mpt_callbacks[cb_idx] != NULL))) {
951 rc = mpt_callbacks[cb_idx](ioc, smid,
952 msix_index, reply);
953 if (reply)
954 _base_display_reply_info(ioc,
955 smid, msix_index, reply);
956 if (rc)
957 mpt3sas_base_free_smid(ioc,
958 smid);
959 }
960 } else {
961 _base_async_event(ioc, msix_index, reply);
962 }
963
964 /* reply free queue handling */
965 if (reply) {
966 ioc->reply_free_host_index =
967 (ioc->reply_free_host_index ==
968 (ioc->reply_free_queue_depth - 1)) ?
969 0 : ioc->reply_free_host_index + 1;
970 ioc->reply_free[ioc->reply_free_host_index] =
971 cpu_to_le32(reply);
972 wmb();
973 writel(ioc->reply_free_host_index,
974 &ioc->chip->ReplyFreeHostIndex);
975 }
976 }
977
978 rpf->Words = cpu_to_le64(ULLONG_MAX);
979 reply_q->reply_post_host_index =
980 (reply_q->reply_post_host_index ==
981 (ioc->reply_post_queue_depth - 1)) ? 0 :
982 reply_q->reply_post_host_index + 1;
983 request_desript_type =
984 reply_q->reply_post_free[reply_q->reply_post_host_index].
985 Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
986 completed_cmds++;
987 if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
988 goto out;
989 if (!reply_q->reply_post_host_index)
990 rpf = reply_q->reply_post_free;
991 else
992 rpf++;
993 } while (1);
994
995 out:
996
997 if (!completed_cmds) {
998 atomic_dec(&reply_q->busy);
999 return IRQ_NONE;
1000 }
1001
1002 wmb();
1003 writel(reply_q->reply_post_host_index | (msix_index <<
1004 MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex);
1005 atomic_dec(&reply_q->busy);
1006 return IRQ_HANDLED;
1007}
1008
1009/**
1010 * _base_is_controller_msix_enabled - is controller support muli-reply queues
1011 * @ioc: per adapter object
1012 *
1013 */
1014static inline int
1015_base_is_controller_msix_enabled(struct MPT3SAS_ADAPTER *ioc)
1016{
1017 return (ioc->facts.IOCCapabilities &
1018 MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable;
1019}
1020
1021/**
1022 * mpt3sas_base_flush_reply_queues - flushing the MSIX reply queues
1023 * @ioc: per adapter object
1024 * Context: ISR conext
1025 *
1026 * Called when a Task Management request has completed. We want
1027 * to flush the other reply queues so all the outstanding IO has been
1028 * completed back to OS before we process the TM completetion.
1029 *
1030 * Return nothing.
1031 */
1032void
1033mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc)
1034{
1035 struct adapter_reply_queue *reply_q;
1036
1037 /* If MSIX capability is turned off
1038 * then multi-queues are not enabled
1039 */
1040 if (!_base_is_controller_msix_enabled(ioc))
1041 return;
1042
1043 list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
1044 if (ioc->shost_recovery)
1045 return;
1046 /* TMs are on msix_index == 0 */
1047 if (reply_q->msix_index == 0)
1048 continue;
1049 _base_interrupt(reply_q->vector, (void *)reply_q);
1050 }
1051}
1052
1053/**
1054 * mpt3sas_base_release_callback_handler - clear interrupt callback handler
1055 * @cb_idx: callback index
1056 *
1057 * Return nothing.
1058 */
1059void
1060mpt3sas_base_release_callback_handler(u8 cb_idx)
1061{
1062 mpt_callbacks[cb_idx] = NULL;
1063}
1064
1065/**
1066 * mpt3sas_base_register_callback_handler - obtain index for the interrupt callback handler
1067 * @cb_func: callback function
1068 *
1069 * Returns cb_func.
1070 */
1071u8
1072mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func)
1073{
1074 u8 cb_idx;
1075
1076 for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
1077 if (mpt_callbacks[cb_idx] == NULL)
1078 break;
1079
1080 mpt_callbacks[cb_idx] = cb_func;
1081 return cb_idx;
1082}
1083
1084/**
1085 * mpt3sas_base_initialize_callback_handler - initialize the interrupt callback handler
1086 *
1087 * Return nothing.
1088 */
1089void
1090mpt3sas_base_initialize_callback_handler(void)
1091{
1092 u8 cb_idx;
1093
1094 for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
1095 mpt3sas_base_release_callback_handler(cb_idx);
1096}
1097
1098
1099/**
1100 * _base_build_zero_len_sge - build zero length sg entry
1101 * @ioc: per adapter object
1102 * @paddr: virtual address for SGE
1103 *
1104 * Create a zero length scatter gather entry to insure the IOCs hardware has
1105 * something to use if the target device goes brain dead and tries
1106 * to send data even when none is asked for.
1107 *
1108 * Return nothing.
1109 */
1110static void
1111_base_build_zero_len_sge(struct MPT3SAS_ADAPTER *ioc, void *paddr)
1112{
1113 u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
1114 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
1115 MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
1116 MPI2_SGE_FLAGS_SHIFT);
1117 ioc->base_add_sg_single(paddr, flags_length, -1);
1118}
1119
1120/**
1121 * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
1122 * @paddr: virtual address for SGE
1123 * @flags_length: SGE flags and data transfer length
1124 * @dma_addr: Physical address
1125 *
1126 * Return nothing.
1127 */
1128static void
1129_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
1130{
1131 Mpi2SGESimple32_t *sgel = paddr;
1132
1133 flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
1134 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
1135 sgel->FlagsLength = cpu_to_le32(flags_length);
1136 sgel->Address = cpu_to_le32(dma_addr);
1137}
1138
1139
1140/**
1141 * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
1142 * @paddr: virtual address for SGE
1143 * @flags_length: SGE flags and data transfer length
1144 * @dma_addr: Physical address
1145 *
1146 * Return nothing.
1147 */
1148static void
1149_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
1150{
1151 Mpi2SGESimple64_t *sgel = paddr;
1152
1153 flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
1154 MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
1155 sgel->FlagsLength = cpu_to_le32(flags_length);
1156 sgel->Address = cpu_to_le64(dma_addr);
1157}
1158
1159/**
1160 * _base_get_chain_buffer_tracker - obtain chain tracker
1161 * @ioc: per adapter object
1162 * @smid: smid associated to an IO request
1163 *
1164 * Returns chain tracker(from ioc->free_chain_list)
1165 */
1166static struct chain_tracker *
1167_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1168{
1169 struct chain_tracker *chain_req;
1170 unsigned long flags;
1171
1172 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1173 if (list_empty(&ioc->free_chain_list)) {
1174 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1175 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1176 "chain buffers not available\n", ioc->name));
1177 return NULL;
1178 }
1179 chain_req = list_entry(ioc->free_chain_list.next,
1180 struct chain_tracker, tracker_list);
1181 list_del_init(&chain_req->tracker_list);
1182 list_add_tail(&chain_req->tracker_list,
1183 &ioc->scsi_lookup[smid - 1].chain_list);
1184 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1185 return chain_req;
1186}
1187
1188
1189/**
1190 * _base_build_sg - build generic sg
1191 * @ioc: per adapter object
1192 * @psge: virtual address for SGE
1193 * @data_out_dma: physical address for WRITES
1194 * @data_out_sz: data xfer size for WRITES
1195 * @data_in_dma: physical address for READS
1196 * @data_in_sz: data xfer size for READS
1197 *
1198 * Return nothing.
1199 */
1200static void
1201_base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge,
1202 dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma,
1203 size_t data_in_sz)
1204{
1205 u32 sgl_flags;
1206
1207 if (!data_out_sz && !data_in_sz) {
1208 _base_build_zero_len_sge(ioc, psge);
1209 return;
1210 }
1211
1212 if (data_out_sz && data_in_sz) {
1213 /* WRITE sgel first */
1214 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1215 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1216 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1217 ioc->base_add_sg_single(psge, sgl_flags |
1218 data_out_sz, data_out_dma);
1219
1220 /* incr sgel */
1221 psge += ioc->sge_size;
1222
1223 /* READ sgel last */
1224 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1225 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1226 MPI2_SGE_FLAGS_END_OF_LIST);
1227 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1228 ioc->base_add_sg_single(psge, sgl_flags |
1229 data_in_sz, data_in_dma);
1230 } else if (data_out_sz) /* WRITE */ {
1231 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1232 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1233 MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC);
1234 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1235 ioc->base_add_sg_single(psge, sgl_flags |
1236 data_out_sz, data_out_dma);
1237 } else if (data_in_sz) /* READ */ {
1238 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1239 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1240 MPI2_SGE_FLAGS_END_OF_LIST);
1241 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1242 ioc->base_add_sg_single(psge, sgl_flags |
1243 data_in_sz, data_in_dma);
1244 }
1245}
1246
1247/* IEEE format sgls */
1248
1249/**
1250 * _base_add_sg_single_ieee - add sg element for IEEE format
1251 * @paddr: virtual address for SGE
1252 * @flags: SGE flags
1253 * @chain_offset: number of 128 byte elements from start of segment
1254 * @length: data transfer length
1255 * @dma_addr: Physical address
1256 *
1257 * Return nothing.
1258 */
1259static void
1260_base_add_sg_single_ieee(void *paddr, u8 flags, u8 chain_offset, u32 length,
1261 dma_addr_t dma_addr)
1262{
1263 Mpi25IeeeSgeChain64_t *sgel = paddr;
1264
1265 sgel->Flags = flags;
1266 sgel->NextChainOffset = chain_offset;
1267 sgel->Length = cpu_to_le32(length);
1268 sgel->Address = cpu_to_le64(dma_addr);
1269}
1270
1271/**
1272 * _base_build_zero_len_sge_ieee - build zero length sg entry for IEEE format
1273 * @ioc: per adapter object
1274 * @paddr: virtual address for SGE
1275 *
1276 * Create a zero length scatter gather entry to insure the IOCs hardware has
1277 * something to use if the target device goes brain dead and tries
1278 * to send data even when none is asked for.
1279 *
1280 * Return nothing.
1281 */
1282static void
1283_base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
1284{
1285 u8 sgl_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
1286 MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
1287 MPI25_IEEE_SGE_FLAGS_END_OF_LIST);
1288 _base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1);
1289}
1290
1291/**
1292 * _base_build_sg_scmd_ieee - main sg creation routine for IEEE format
1293 * @ioc: per adapter object
1294 * @scmd: scsi command
1295 * @smid: system request message index
1296 * Context: none.
1297 *
1298 * The main routine that builds scatter gather table from a given
1299 * scsi request sent via the .queuecommand main handler.
1300 *
1301 * Returns 0 success, anything else error
1302 */
1303static int
1304_base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
1305 struct scsi_cmnd *scmd, u16 smid)
1306{
1307 Mpi2SCSIIORequest_t *mpi_request;
1308 dma_addr_t chain_dma;
1309 struct scatterlist *sg_scmd;
1310 void *sg_local, *chain;
1311 u32 chain_offset;
1312 u32 chain_length;
1313 u32 chain_flags;
1314 int sges_left;
1315 u32 sges_in_segment;
1316 u8 simple_sgl_flags;
1317 u8 simple_sgl_flags_last;
1318 u8 chain_sgl_flags;
1319 struct chain_tracker *chain_req;
1320
1321 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1322
1323 /* init scatter gather flags */
1324 simple_sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
1325 MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
1326 simple_sgl_flags_last = simple_sgl_flags |
1327 MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
1328 chain_sgl_flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
1329 MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
1330
1331 sg_scmd = scsi_sglist(scmd);
1332 sges_left = scsi_dma_map(scmd);
1333 if (!sges_left) {
1334 sdev_printk(KERN_ERR, scmd->device,
1335 "pci_map_sg failed: request for %d bytes!\n",
1336 scsi_bufflen(scmd));
1337 return -ENOMEM;
1338 }
1339
1340 sg_local = &mpi_request->SGL;
1341 sges_in_segment = (ioc->request_sz -
1342 offsetof(Mpi2SCSIIORequest_t, SGL))/ioc->sge_size_ieee;
1343 if (sges_left <= sges_in_segment)
1344 goto fill_in_last_segment;
1345
1346 mpi_request->ChainOffset = (sges_in_segment - 1 /* chain element */) +
1347 (offsetof(Mpi2SCSIIORequest_t, SGL)/ioc->sge_size_ieee);
1348
1349 /* fill in main message segment when there is a chain following */
1350 while (sges_in_segment > 1) {
1351 _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0,
1352 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1353 sg_scmd = sg_next(sg_scmd);
1354 sg_local += ioc->sge_size_ieee;
1355 sges_left--;
1356 sges_in_segment--;
1357 }
1358
1359 /* initializing the chain flags and pointers */
1360 chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
1361 chain_req = _base_get_chain_buffer_tracker(ioc, smid);
1362 if (!chain_req)
1363 return -1;
1364 chain = chain_req->chain_buffer;
1365 chain_dma = chain_req->chain_buffer_dma;
1366 do {
1367 sges_in_segment = (sges_left <=
1368 ioc->max_sges_in_chain_message) ? sges_left :
1369 ioc->max_sges_in_chain_message;
1370 chain_offset = (sges_left == sges_in_segment) ?
1371 0 : sges_in_segment;
1372 chain_length = sges_in_segment * ioc->sge_size_ieee;
1373 if (chain_offset)
1374 chain_length += ioc->sge_size_ieee;
1375 _base_add_sg_single_ieee(sg_local, chain_sgl_flags,
1376 chain_offset, chain_length, chain_dma);
1377
1378 sg_local = chain;
1379 if (!chain_offset)
1380 goto fill_in_last_segment;
1381
1382 /* fill in chain segments */
1383 while (sges_in_segment) {
1384 _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0,
1385 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1386 sg_scmd = sg_next(sg_scmd);
1387 sg_local += ioc->sge_size_ieee;
1388 sges_left--;
1389 sges_in_segment--;
1390 }
1391
1392 chain_req = _base_get_chain_buffer_tracker(ioc, smid);
1393 if (!chain_req)
1394 return -1;
1395 chain = chain_req->chain_buffer;
1396 chain_dma = chain_req->chain_buffer_dma;
1397 } while (1);
1398
1399
1400 fill_in_last_segment:
1401
1402 /* fill the last segment */
1403 while (sges_left) {
1404 if (sges_left == 1)
1405 _base_add_sg_single_ieee(sg_local,
1406 simple_sgl_flags_last, 0, sg_dma_len(sg_scmd),
1407 sg_dma_address(sg_scmd));
1408 else
1409 _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0,
1410 sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
1411 sg_scmd = sg_next(sg_scmd);
1412 sg_local += ioc->sge_size_ieee;
1413 sges_left--;
1414 }
1415
1416 return 0;
1417}
1418
1419/**
1420 * _base_build_sg_ieee - build generic sg for IEEE format
1421 * @ioc: per adapter object
1422 * @psge: virtual address for SGE
1423 * @data_out_dma: physical address for WRITES
1424 * @data_out_sz: data xfer size for WRITES
1425 * @data_in_dma: physical address for READS
1426 * @data_in_sz: data xfer size for READS
1427 *
1428 * Return nothing.
1429 */
1430static void
1431_base_build_sg_ieee(struct MPT3SAS_ADAPTER *ioc, void *psge,
1432 dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma,
1433 size_t data_in_sz)
1434{
1435 u8 sgl_flags;
1436
1437 if (!data_out_sz && !data_in_sz) {
1438 _base_build_zero_len_sge_ieee(ioc, psge);
1439 return;
1440 }
1441
1442 if (data_out_sz && data_in_sz) {
1443 /* WRITE sgel first */
1444 sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
1445 MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
1446 _base_add_sg_single_ieee(psge, sgl_flags, 0, data_out_sz,
1447 data_out_dma);
1448
1449 /* incr sgel */
1450 psge += ioc->sge_size_ieee;
1451
1452 /* READ sgel last */
1453 sgl_flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
1454 _base_add_sg_single_ieee(psge, sgl_flags, 0, data_in_sz,
1455 data_in_dma);
1456 } else if (data_out_sz) /* WRITE */ {
1457 sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
1458 MPI25_IEEE_SGE_FLAGS_END_OF_LIST |
1459 MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
1460 _base_add_sg_single_ieee(psge, sgl_flags, 0, data_out_sz,
1461 data_out_dma);
1462 } else if (data_in_sz) /* READ */ {
1463 sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
1464 MPI25_IEEE_SGE_FLAGS_END_OF_LIST |
1465 MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
1466 _base_add_sg_single_ieee(psge, sgl_flags, 0, data_in_sz,
1467 data_in_dma);
1468 }
1469}
1470
1471#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
1472
1473/**
1474 * _base_config_dma_addressing - set dma addressing
1475 * @ioc: per adapter object
1476 * @pdev: PCI device struct
1477 *
1478 * Returns 0 for success, non-zero for failure.
1479 */
1480static int
1481_base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
1482{
1483 struct sysinfo s;
1484 char *desc = NULL;
1485
1486 if (sizeof(dma_addr_t) > 4) {
1487 const uint64_t required_mask =
1488 dma_get_required_mask(&pdev->dev);
1489 if ((required_mask > DMA_BIT_MASK(32)) &&
1490 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
1491 !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
1492 ioc->base_add_sg_single = &_base_add_sg_single_64;
1493 ioc->sge_size = sizeof(Mpi2SGESimple64_t);
1494 desc = "64";
1495 goto out;
1496 }
1497 }
1498
1499 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1500 && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
1501 ioc->base_add_sg_single = &_base_add_sg_single_32;
1502 ioc->sge_size = sizeof(Mpi2SGESimple32_t);
1503 desc = "32";
1504 } else
1505 return -ENODEV;
1506
1507 out:
1508 si_meminfo(&s);
1509 pr_info(MPT3SAS_FMT
1510 "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n",
1511 ioc->name, desc, convert_to_kb(s.totalram));
1512
1513 return 0;
1514}
1515
1516/**
1517 * _base_check_enable_msix - checks MSIX capabable.
1518 * @ioc: per adapter object
1519 *
1520 * Check to see if card is capable of MSIX, and set number
1521 * of available msix vectors
1522 */
1523static int
1524_base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc)
1525{
1526 int base;
1527 u16 message_control;
1528
1529 base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
1530 if (!base) {
1531 dfailprintk(ioc, pr_info(MPT3SAS_FMT "msix not supported\n",
1532 ioc->name));
1533 return -EINVAL;
1534 }
1535
1536 /* get msix vector count */
1537
1538 pci_read_config_word(ioc->pdev, base + 2, &message_control);
1539 ioc->msix_vector_count = (message_control & 0x3FF) + 1;
1540 if (ioc->msix_vector_count > 8)
1541 ioc->msix_vector_count = 8;
1542 dinitprintk(ioc, pr_info(MPT3SAS_FMT
1543 "msix is supported, vector_count(%d)\n",
1544 ioc->name, ioc->msix_vector_count));
1545 return 0;
1546}
1547
1548/**
1549 * _base_free_irq - free irq
1550 * @ioc: per adapter object
1551 *
1552 * Freeing respective reply_queue from the list.
1553 */
1554static void
1555_base_free_irq(struct MPT3SAS_ADAPTER *ioc)
1556{
1557 struct adapter_reply_queue *reply_q, *next;
1558
1559 if (list_empty(&ioc->reply_queue_list))
1560 return;
1561
1562 list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
1563 list_del(&reply_q->list);
1564 synchronize_irq(reply_q->vector);
1565 free_irq(reply_q->vector, reply_q);
1566 kfree(reply_q);
1567 }
1568}
1569
1570/**
1571 * _base_request_irq - request irq
1572 * @ioc: per adapter object
1573 * @index: msix index into vector table
1574 * @vector: irq vector
1575 *
1576 * Inserting respective reply_queue into the list.
1577 */
1578static int
1579_base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector)
1580{
1581 struct adapter_reply_queue *reply_q;
1582 int r;
1583
1584 reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL);
1585 if (!reply_q) {
1586 pr_err(MPT3SAS_FMT "unable to allocate memory %d!\n",
1587 ioc->name, (int)sizeof(struct adapter_reply_queue));
1588 return -ENOMEM;
1589 }
1590 reply_q->ioc = ioc;
1591 reply_q->msix_index = index;
1592 reply_q->vector = vector;
1593 atomic_set(&reply_q->busy, 0);
1594 if (ioc->msix_enable)
1595 snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
1596 MPT3SAS_DRIVER_NAME, ioc->id, index);
1597 else
1598 snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
1599 MPT3SAS_DRIVER_NAME, ioc->id);
1600 r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name,
1601 reply_q);
1602 if (r) {
1603 pr_err(MPT3SAS_FMT "unable to allocate interrupt %d!\n",
1604 reply_q->name, vector);
1605 kfree(reply_q);
1606 return -EBUSY;
1607 }
1608
1609 INIT_LIST_HEAD(&reply_q->list);
1610 list_add_tail(&reply_q->list, &ioc->reply_queue_list);
1611 return 0;
1612}
1613
1614/**
1615 * _base_assign_reply_queues - assigning msix index for each cpu
1616 * @ioc: per adapter object
1617 *
1618 * The enduser would need to set the affinity via /proc/irq/#/smp_affinity
1619 *
1620 * It would nice if we could call irq_set_affinity, however it is not
1621 * an exported symbol
1622 */
1623static void
1624_base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
1625{
1626 struct adapter_reply_queue *reply_q;
1627 int cpu_id;
1628 int cpu_grouping, loop, grouping, grouping_mod;
1629 int reply_queue;
1630
1631 if (!_base_is_controller_msix_enabled(ioc))
1632 return;
1633
1634 memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
1635
1636 /* NUMA Hardware bug workaround - drop to less reply queues */
1637 if (ioc->reply_queue_count > ioc->facts.MaxMSIxVectors) {
1638 ioc->reply_queue_count = ioc->facts.MaxMSIxVectors;
1639 reply_queue = 0;
1640 list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
1641 reply_q->msix_index = reply_queue;
1642 if (++reply_queue == ioc->reply_queue_count)
1643 reply_queue = 0;
1644 }
1645 }
1646
1647 /* when there are more cpus than available msix vectors,
1648 * then group cpus togeather on same irq
1649 */
1650 if (ioc->cpu_count > ioc->msix_vector_count) {
1651 grouping = ioc->cpu_count / ioc->msix_vector_count;
1652 grouping_mod = ioc->cpu_count % ioc->msix_vector_count;
1653 if (grouping < 2 || (grouping == 2 && !grouping_mod))
1654 cpu_grouping = 2;
1655 else if (grouping < 4 || (grouping == 4 && !grouping_mod))
1656 cpu_grouping = 4;
1657 else if (grouping < 8 || (grouping == 8 && !grouping_mod))
1658 cpu_grouping = 8;
1659 else
1660 cpu_grouping = 16;
1661 } else
1662 cpu_grouping = 0;
1663
1664 loop = 0;
1665 reply_q = list_entry(ioc->reply_queue_list.next,
1666 struct adapter_reply_queue, list);
1667 for_each_online_cpu(cpu_id) {
1668 if (!cpu_grouping) {
1669 ioc->cpu_msix_table[cpu_id] = reply_q->msix_index;
1670 reply_q = list_entry(reply_q->list.next,
1671 struct adapter_reply_queue, list);
1672 } else {
1673 if (loop < cpu_grouping) {
1674 ioc->cpu_msix_table[cpu_id] =
1675 reply_q->msix_index;
1676 loop++;
1677 } else {
1678 reply_q = list_entry(reply_q->list.next,
1679 struct adapter_reply_queue, list);
1680 ioc->cpu_msix_table[cpu_id] =
1681 reply_q->msix_index;
1682 loop = 1;
1683 }
1684 }
1685 }
1686}
1687
1688/**
1689 * _base_disable_msix - disables msix
1690 * @ioc: per adapter object
1691 *
1692 */
1693static void
1694_base_disable_msix(struct MPT3SAS_ADAPTER *ioc)
1695{
1696 if (!ioc->msix_enable)
1697 return;
1698 pci_disable_msix(ioc->pdev);
1699 ioc->msix_enable = 0;
1700}
1701
1702/**
1703 * _base_enable_msix - enables msix, failback to io_apic
1704 * @ioc: per adapter object
1705 *
1706 */
1707static int
1708_base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
1709{
1710 struct msix_entry *entries, *a;
1711 int r;
1712 int i;
1713 u8 try_msix = 0;
1714
1715 INIT_LIST_HEAD(&ioc->reply_queue_list);
1716
1717 if (msix_disable == -1 || msix_disable == 0)
1718 try_msix = 1;
1719
1720 if (!try_msix)
1721 goto try_ioapic;
1722
1723 if (_base_check_enable_msix(ioc) != 0)
1724 goto try_ioapic;
1725
1726 ioc->reply_queue_count = min_t(int, ioc->cpu_count,
1727 ioc->msix_vector_count);
1728
1729 entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry),
1730 GFP_KERNEL);
1731 if (!entries) {
1732 dfailprintk(ioc, pr_info(MPT3SAS_FMT
1733 "kcalloc failed @ at %s:%d/%s() !!!\n",
1734 ioc->name, __FILE__, __LINE__, __func__));
1735 goto try_ioapic;
1736 }
1737
1738 for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++)
1739 a->entry = i;
1740
1741 r = pci_enable_msix(ioc->pdev, entries, ioc->reply_queue_count);
1742 if (r) {
1743 dfailprintk(ioc, pr_info(MPT3SAS_FMT
1744 "pci_enable_msix failed (r=%d) !!!\n",
1745 ioc->name, r));
1746 kfree(entries);
1747 goto try_ioapic;
1748 }
1749
1750 ioc->msix_enable = 1;
1751 for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) {
1752 r = _base_request_irq(ioc, i, a->vector);
1753 if (r) {
1754 _base_free_irq(ioc);
1755 _base_disable_msix(ioc);
1756 kfree(entries);
1757 goto try_ioapic;
1758 }
1759 }
1760
1761 kfree(entries);
1762 return 0;
1763
1764/* failback to io_apic interrupt routing */
1765 try_ioapic:
1766
1767 r = _base_request_irq(ioc, 0, ioc->pdev->irq);
1768
1769 return r;
1770}
1771
1772/**
1773 * mpt3sas_base_map_resources - map in controller resources (io/irq/memap)
1774 * @ioc: per adapter object
1775 *
1776 * Returns 0 for success, non-zero for failure.
1777 */
1778int
1779mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
1780{
1781 struct pci_dev *pdev = ioc->pdev;
1782 u32 memap_sz;
1783 u32 pio_sz;
1784 int i, r = 0;
1785 u64 pio_chip = 0;
1786 u64 chip_phys = 0;
1787 struct adapter_reply_queue *reply_q;
1788
1789 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n",
1790 ioc->name, __func__));
1791
1792 ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1793 if (pci_enable_device_mem(pdev)) {
1794 pr_warn(MPT3SAS_FMT "pci_enable_device_mem: failed\n",
1795 ioc->name);
1796 return -ENODEV;
1797 }
1798
1799
1800 if (pci_request_selected_regions(pdev, ioc->bars,
1801 MPT3SAS_DRIVER_NAME)) {
1802 pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n",
1803 ioc->name);
1804 r = -ENODEV;
1805 goto out_fail;
1806 }
1807
1808/* AER (Advanced Error Reporting) hooks */
1809 pci_enable_pcie_error_reporting(pdev);
1810
1811 pci_set_master(pdev);
1812
1813
1814 if (_base_config_dma_addressing(ioc, pdev) != 0) {
1815 pr_warn(MPT3SAS_FMT "no suitable DMA mask for %s\n",
1816 ioc->name, pci_name(pdev));
1817 r = -ENODEV;
1818 goto out_fail;
1819 }
1820
1821 for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) {
1822 if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
1823 if (pio_sz)
1824 continue;
1825 pio_chip = (u64)pci_resource_start(pdev, i);
1826 pio_sz = pci_resource_len(pdev, i);
1827 } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
1828 if (memap_sz)
1829 continue;
1830 ioc->chip_phys = pci_resource_start(pdev, i);
1831 chip_phys = (u64)ioc->chip_phys;
1832 memap_sz = pci_resource_len(pdev, i);
1833 ioc->chip = ioremap(ioc->chip_phys, memap_sz);
1834 if (ioc->chip == NULL) {
1835 pr_err(MPT3SAS_FMT "unable to map adapter memory!\n",
1836 ioc->name);
1837 r = -EINVAL;
1838 goto out_fail;
1839 }
1840 }
1841 }
1842
1843 _base_mask_interrupts(ioc);
1844 r = _base_enable_msix(ioc);
1845 if (r)
1846 goto out_fail;
1847
1848 list_for_each_entry(reply_q, &ioc->reply_queue_list, list)
1849 pr_info(MPT3SAS_FMT "%s: IRQ %d\n",
1850 reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
1851 "IO-APIC enabled"), reply_q->vector);
1852
1853 pr_info(MPT3SAS_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
1854 ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
1855 pr_info(MPT3SAS_FMT "ioport(0x%016llx), size(%d)\n",
1856 ioc->name, (unsigned long long)pio_chip, pio_sz);
1857
1858 /* Save PCI configuration state for recovery from PCI AER/EEH errors */
1859 pci_save_state(pdev);
1860 return 0;
1861
1862 out_fail:
1863 if (ioc->chip_phys)
1864 iounmap(ioc->chip);
1865 ioc->chip_phys = 0;
1866 pci_release_selected_regions(ioc->pdev, ioc->bars);
1867 pci_disable_pcie_error_reporting(pdev);
1868 pci_disable_device(pdev);
1869 return r;
1870}
1871
1872/**
1873 * mpt3sas_base_get_msg_frame - obtain request mf pointer
1874 * @ioc: per adapter object
1875 * @smid: system request message index(smid zero is invalid)
1876 *
1877 * Returns virt pointer to message frame.
1878 */
1879void *
1880mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1881{
1882 return (void *)(ioc->request + (smid * ioc->request_sz));
1883}
1884
1885/**
1886 * mpt3sas_base_get_sense_buffer - obtain a sense buffer virt addr
1887 * @ioc: per adapter object
1888 * @smid: system request message index
1889 *
1890 * Returns virt pointer to sense buffer.
1891 */
1892void *
1893mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1894{
1895 return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
1896}
1897
1898/**
1899 * mpt3sas_base_get_sense_buffer_dma - obtain a sense buffer dma addr
1900 * @ioc: per adapter object
1901 * @smid: system request message index
1902 *
1903 * Returns phys pointer to the low 32bit address of the sense buffer.
1904 */
1905__le32
1906mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1907{
1908 return cpu_to_le32(ioc->sense_dma + ((smid - 1) *
1909 SCSI_SENSE_BUFFERSIZE));
1910}
1911
1912/**
1913 * mpt3sas_base_get_reply_virt_addr - obtain reply frames virt address
1914 * @ioc: per adapter object
1915 * @phys_addr: lower 32 physical addr of the reply
1916 *
1917 * Converts 32bit lower physical addr into a virt address.
1918 */
1919void *
1920mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, u32 phys_addr)
1921{
1922 if (!phys_addr)
1923 return NULL;
1924 return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
1925}
1926
1927/**
1928 * mpt3sas_base_get_smid - obtain a free smid from internal queue
1929 * @ioc: per adapter object
1930 * @cb_idx: callback index
1931 *
1932 * Returns smid (zero is invalid)
1933 */
1934u16
1935mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx)
1936{
1937 unsigned long flags;
1938 struct request_tracker *request;
1939 u16 smid;
1940
1941 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1942 if (list_empty(&ioc->internal_free_list)) {
1943 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1944 pr_err(MPT3SAS_FMT "%s: smid not available\n",
1945 ioc->name, __func__);
1946 return 0;
1947 }
1948
1949 request = list_entry(ioc->internal_free_list.next,
1950 struct request_tracker, tracker_list);
1951 request->cb_idx = cb_idx;
1952 smid = request->smid;
1953 list_del(&request->tracker_list);
1954 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1955 return smid;
1956}
1957
1958/**
1959 * mpt3sas_base_get_smid_scsiio - obtain a free smid from scsiio queue
1960 * @ioc: per adapter object
1961 * @cb_idx: callback index
1962 * @scmd: pointer to scsi command object
1963 *
1964 * Returns smid (zero is invalid)
1965 */
1966u16
1967mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
1968 struct scsi_cmnd *scmd)
1969{
1970 unsigned long flags;
1971 struct scsiio_tracker *request;
1972 u16 smid;
1973
1974 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1975 if (list_empty(&ioc->free_list)) {
1976 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1977 pr_err(MPT3SAS_FMT "%s: smid not available\n",
1978 ioc->name, __func__);
1979 return 0;
1980 }
1981
1982 request = list_entry(ioc->free_list.next,
1983 struct scsiio_tracker, tracker_list);
1984 request->scmd = scmd;
1985 request->cb_idx = cb_idx;
1986 smid = request->smid;
1987 list_del(&request->tracker_list);
1988 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1989 return smid;
1990}
1991
1992/**
1993 * mpt3sas_base_get_smid_hpr - obtain a free smid from hi-priority queue
1994 * @ioc: per adapter object
1995 * @cb_idx: callback index
1996 *
1997 * Returns smid (zero is invalid)
1998 */
1999u16
2000mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx)
2001{
2002 unsigned long flags;
2003 struct request_tracker *request;
2004 u16 smid;
2005
2006 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2007 if (list_empty(&ioc->hpr_free_list)) {
2008 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2009 return 0;
2010 }
2011
2012 request = list_entry(ioc->hpr_free_list.next,
2013 struct request_tracker, tracker_list);
2014 request->cb_idx = cb_idx;
2015 smid = request->smid;
2016 list_del(&request->tracker_list);
2017 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2018 return smid;
2019}
2020
2021/**
2022 * mpt3sas_base_free_smid - put smid back on free_list
2023 * @ioc: per adapter object
2024 * @smid: system request message index
2025 *
2026 * Return nothing.
2027 */
2028void
2029mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
2030{
2031 unsigned long flags;
2032 int i;
2033 struct chain_tracker *chain_req, *next;
2034
2035 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2036 if (smid < ioc->hi_priority_smid) {
2037 /* scsiio queue */
2038 i = smid - 1;
2039 if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
2040 list_for_each_entry_safe(chain_req, next,
2041 &ioc->scsi_lookup[i].chain_list, tracker_list) {
2042 list_del_init(&chain_req->tracker_list);
2043 list_add(&chain_req->tracker_list,
2044 &ioc->free_chain_list);
2045 }
2046 }
2047 ioc->scsi_lookup[i].cb_idx = 0xFF;
2048 ioc->scsi_lookup[i].scmd = NULL;
2049 list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list);
2050 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2051
2052 /*
2053 * See _wait_for_commands_to_complete() call with regards
2054 * to this code.
2055 */
2056 if (ioc->shost_recovery && ioc->pending_io_count) {
2057 if (ioc->pending_io_count == 1)
2058 wake_up(&ioc->reset_wq);
2059 ioc->pending_io_count--;
2060 }
2061 return;
2062 } else if (smid < ioc->internal_smid) {
2063 /* hi-priority */
2064 i = smid - ioc->hi_priority_smid;
2065 ioc->hpr_lookup[i].cb_idx = 0xFF;
2066 list_add(&ioc->hpr_lookup[i].tracker_list, &ioc->hpr_free_list);
2067 } else if (smid <= ioc->hba_queue_depth) {
2068 /* internal queue */
2069 i = smid - ioc->internal_smid;
2070 ioc->internal_lookup[i].cb_idx = 0xFF;
2071 list_add(&ioc->internal_lookup[i].tracker_list,
2072 &ioc->internal_free_list);
2073 }
2074 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2075}
2076
2077/**
2078 * _base_writeq - 64 bit write to MMIO
2079 * @ioc: per adapter object
2080 * @b: data payload
2081 * @addr: address in MMIO space
2082 * @writeq_lock: spin lock
2083 *
2084 * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
2085 * care of 32 bit environment where its not quarenteed to send the entire word
2086 * in one transfer.
2087 */
2088#if defined(writeq) && defined(CONFIG_64BIT)
2089static inline void
2090_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
2091{
2092 writeq(cpu_to_le64(b), addr);
2093}
2094#else
2095static inline void
2096_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
2097{
2098 unsigned long flags;
2099 __u64 data_out = cpu_to_le64(b);
2100
2101 spin_lock_irqsave(writeq_lock, flags);
2102 writel((u32)(data_out), addr);
2103 writel((u32)(data_out >> 32), (addr + 4));
2104 spin_unlock_irqrestore(writeq_lock, flags);
2105}
2106#endif
2107
2108static inline u8
2109_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc)
2110{
2111 return ioc->cpu_msix_table[raw_smp_processor_id()];
2112}
2113
2114/**
2115 * mpt3sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
2116 * @ioc: per adapter object
2117 * @smid: system request message index
2118 * @handle: device handle
2119 *
2120 * Return nothing.
2121 */
2122void
2123mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle)
2124{
2125 Mpi2RequestDescriptorUnion_t descriptor;
2126 u64 *request = (u64 *)&descriptor;
2127
2128
2129 descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
2130 descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc);
2131 descriptor.SCSIIO.SMID = cpu_to_le16(smid);
2132 descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
2133 descriptor.SCSIIO.LMID = 0;
2134 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
2135 &ioc->scsi_lookup_lock);
2136}
2137
2138/**
2139 * mpt3sas_base_put_smid_fast_path - send fast path request to firmware
2140 * @ioc: per adapter object
2141 * @smid: system request message index
2142 * @handle: device handle
2143 *
2144 * Return nothing.
2145 */
2146void
2147mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
2148 u16 handle)
2149{
2150 Mpi2RequestDescriptorUnion_t descriptor;
2151 u64 *request = (u64 *)&descriptor;
2152
2153 descriptor.SCSIIO.RequestFlags =
2154 MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
2155 descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc);
2156 descriptor.SCSIIO.SMID = cpu_to_le16(smid);
2157 descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
2158 descriptor.SCSIIO.LMID = 0;
2159 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
2160 &ioc->scsi_lookup_lock);
2161}
2162
2163/**
2164 * mpt3sas_base_put_smid_hi_priority - send Task Managment request to firmware
2165 * @ioc: per adapter object
2166 * @smid: system request message index
2167 *
2168 * Return nothing.
2169 */
2170void
2171mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid)
2172{
2173 Mpi2RequestDescriptorUnion_t descriptor;
2174 u64 *request = (u64 *)&descriptor;
2175
2176 descriptor.HighPriority.RequestFlags =
2177 MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
2178 descriptor.HighPriority.MSIxIndex = 0;
2179 descriptor.HighPriority.SMID = cpu_to_le16(smid);
2180 descriptor.HighPriority.LMID = 0;
2181 descriptor.HighPriority.Reserved1 = 0;
2182 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
2183 &ioc->scsi_lookup_lock);
2184}
2185
2186/**
2187 * mpt3sas_base_put_smid_default - Default, primarily used for config pages
2188 * @ioc: per adapter object
2189 * @smid: system request message index
2190 *
2191 * Return nothing.
2192 */
2193void
2194mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
2195{
2196 Mpi2RequestDescriptorUnion_t descriptor;
2197 u64 *request = (u64 *)&descriptor;
2198
2199 descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
2200 descriptor.Default.MSIxIndex = _base_get_msix_index(ioc);
2201 descriptor.Default.SMID = cpu_to_le16(smid);
2202 descriptor.Default.LMID = 0;
2203 descriptor.Default.DescriptorTypeDependent = 0;
2204 _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
2205 &ioc->scsi_lookup_lock);
2206}
2207
2208
2209
2210/**
2211 * _base_display_ioc_capabilities - Disply IOC's capabilities.
2212 * @ioc: per adapter object
2213 *
2214 * Return nothing.
2215 */
2216static void
2217_base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc)
2218{
2219 int i = 0;
2220 char desc[16];
2221 u32 iounit_pg1_flags;
2222 u32 bios_version;
2223
2224 bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
2225 strncpy(desc, ioc->manu_pg0.ChipName, 16);
2226 pr_info(MPT3SAS_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "\
2227 "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
2228 ioc->name, desc,
2229 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
2230 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
2231 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
2232 ioc->facts.FWVersion.Word & 0x000000FF,
2233 ioc->pdev->revision,
2234 (bios_version & 0xFF000000) >> 24,
2235 (bios_version & 0x00FF0000) >> 16,
2236 (bios_version & 0x0000FF00) >> 8,
2237 bios_version & 0x000000FF);
2238
2239 pr_info(MPT3SAS_FMT "Protocol=(", ioc->name);
2240
2241 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
2242 pr_info("Initiator");
2243 i++;
2244 }
2245
2246 if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
2247 pr_info("%sTarget", i ? "," : "");
2248 i++;
2249 }
2250
2251 i = 0;
2252 pr_info("), ");
2253 pr_info("Capabilities=(");
2254
2255 if (ioc->facts.IOCCapabilities &
2256 MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
2257 pr_info("Raid");
2258 i++;
2259 }
2260
2261 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
2262 pr_info("%sTLR", i ? "," : "");
2263 i++;
2264 }
2265
2266 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
2267 pr_info("%sMulticast", i ? "," : "");
2268 i++;
2269 }
2270
2271 if (ioc->facts.IOCCapabilities &
2272 MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
2273 pr_info("%sBIDI Target", i ? "," : "");
2274 i++;
2275 }
2276
2277 if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
2278 pr_info("%sEEDP", i ? "," : "");
2279 i++;
2280 }
2281
2282 if (ioc->facts.IOCCapabilities &
2283 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
2284 pr_info("%sSnapshot Buffer", i ? "," : "");
2285 i++;
2286 }
2287
2288 if (ioc->facts.IOCCapabilities &
2289 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
2290 pr_info("%sDiag Trace Buffer", i ? "," : "");
2291 i++;
2292 }
2293
2294 if (ioc->facts.IOCCapabilities &
2295 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
2296 pr_info("%sDiag Extended Buffer", i ? "," : "");
2297 i++;
2298 }
2299
2300 if (ioc->facts.IOCCapabilities &
2301 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
2302 pr_info("%sTask Set Full", i ? "," : "");
2303 i++;
2304 }
2305
2306 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
2307 if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
2308 pr_info("%sNCQ", i ? "," : "");
2309 i++;
2310 }
2311
2312 pr_info(")\n");
2313}
2314
2315/**
2316 * mpt3sas_base_update_missing_delay - change the missing delay timers
2317 * @ioc: per adapter object
2318 * @device_missing_delay: amount of time till device is reported missing
2319 * @io_missing_delay: interval IO is returned when there is a missing device
2320 *
2321 * Return nothing.
2322 *
2323 * Passed on the command line, this function will modify the device missing
2324 * delay, as well as the io missing delay. This should be called at driver
2325 * load time.
2326 */
2327void
2328mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc,
2329 u16 device_missing_delay, u8 io_missing_delay)
2330{
2331 u16 dmd, dmd_new, dmd_orignal;
2332 u8 io_missing_delay_original;
2333 u16 sz;
2334 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
2335 Mpi2ConfigReply_t mpi_reply;
2336 u8 num_phys = 0;
2337 u16 ioc_status;
2338
2339 mpt3sas_config_get_number_hba_phys(ioc, &num_phys);
2340 if (!num_phys)
2341 return;
2342
2343 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
2344 sizeof(Mpi2SasIOUnit1PhyData_t));
2345 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
2346 if (!sas_iounit_pg1) {
2347 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
2348 ioc->name, __FILE__, __LINE__, __func__);
2349 goto out;
2350 }
2351 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
2352 sas_iounit_pg1, sz))) {
2353 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
2354 ioc->name, __FILE__, __LINE__, __func__);
2355 goto out;
2356 }
2357 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
2358 MPI2_IOCSTATUS_MASK;
2359 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
2360 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
2361 ioc->name, __FILE__, __LINE__, __func__);
2362 goto out;
2363 }
2364
2365 /* device missing delay */
2366 dmd = sas_iounit_pg1->ReportDeviceMissingDelay;
2367 if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
2368 dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
2369 else
2370 dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2371 dmd_orignal = dmd;
2372 if (device_missing_delay > 0x7F) {
2373 dmd = (device_missing_delay > 0x7F0) ? 0x7F0 :
2374 device_missing_delay;
2375 dmd = dmd / 16;
2376 dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16;
2377 } else
2378 dmd = device_missing_delay;
2379 sas_iounit_pg1->ReportDeviceMissingDelay = dmd;
2380
2381 /* io missing delay */
2382 io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay;
2383 sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay;
2384
2385 if (!mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
2386 sz)) {
2387 if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
2388 dmd_new = (dmd &
2389 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
2390 else
2391 dmd_new =
2392 dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2393 pr_info(MPT3SAS_FMT "device_missing_delay: old(%d), new(%d)\n",
2394 ioc->name, dmd_orignal, dmd_new);
2395 pr_info(MPT3SAS_FMT "ioc_missing_delay: old(%d), new(%d)\n",
2396 ioc->name, io_missing_delay_original,
2397 io_missing_delay);
2398 ioc->device_missing_delay = dmd_new;
2399 ioc->io_missing_delay = io_missing_delay;
2400 }
2401
2402out:
2403 kfree(sas_iounit_pg1);
2404}
2405/**
2406 * _base_static_config_pages - static start of day config pages
2407 * @ioc: per adapter object
2408 *
2409 * Return nothing.
2410 */
2411static void
2412_base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
2413{
2414 Mpi2ConfigReply_t mpi_reply;
2415 u32 iounit_pg1_flags;
2416
2417 mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
2418 if (ioc->ir_firmware)
2419 mpt3sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
2420 &ioc->manu_pg10);
2421
2422 /*
2423 * Ensure correct T10 PI operation if vendor left EEDPTagMode
2424 * flag unset in NVDATA.
2425 */
2426 mpt3sas_config_get_manufacturing_pg11(ioc, &mpi_reply, &ioc->manu_pg11);
2427 if (ioc->manu_pg11.EEDPTagMode == 0) {
2428 pr_err("%s: overriding NVDATA EEDPTagMode setting\n",
2429 ioc->name);
2430 ioc->manu_pg11.EEDPTagMode &= ~0x3;
2431 ioc->manu_pg11.EEDPTagMode |= 0x1;
2432 mpt3sas_config_set_manufacturing_pg11(ioc, &mpi_reply,
2433 &ioc->manu_pg11);
2434 }
2435
2436 mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
2437 mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
2438 mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
2439 mpt3sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
2440 mpt3sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
2441 _base_display_ioc_capabilities(ioc);
2442
2443 /*
2444 * Enable task_set_full handling in iounit_pg1 when the
2445 * facts capabilities indicate that its supported.
2446 */
2447 iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
2448 if ((ioc->facts.IOCCapabilities &
2449 MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
2450 iounit_pg1_flags &=
2451 ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
2452 else
2453 iounit_pg1_flags |=
2454 MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
2455 ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
2456 mpt3sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
2457}
2458
2459/**
2460 * _base_release_memory_pools - release memory
2461 * @ioc: per adapter object
2462 *
2463 * Free memory allocated from _base_allocate_memory_pools.
2464 *
2465 * Return nothing.
2466 */
2467static void
2468_base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
2469{
2470 int i;
2471
2472 dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
2473 __func__));
2474
2475 if (ioc->request) {
2476 pci_free_consistent(ioc->pdev, ioc->request_dma_sz,
2477 ioc->request, ioc->request_dma);
2478 dexitprintk(ioc, pr_info(MPT3SAS_FMT
2479 "request_pool(0x%p): free\n",
2480 ioc->name, ioc->request));
2481 ioc->request = NULL;
2482 }
2483
2484 if (ioc->sense) {
2485 pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
2486 if (ioc->sense_dma_pool)
2487 pci_pool_destroy(ioc->sense_dma_pool);
2488 dexitprintk(ioc, pr_info(MPT3SAS_FMT
2489 "sense_pool(0x%p): free\n",
2490 ioc->name, ioc->sense));
2491 ioc->sense = NULL;
2492 }
2493
2494 if (ioc->reply) {
2495 pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma);
2496 if (ioc->reply_dma_pool)
2497 pci_pool_destroy(ioc->reply_dma_pool);
2498 dexitprintk(ioc, pr_info(MPT3SAS_FMT
2499 "reply_pool(0x%p): free\n",
2500 ioc->name, ioc->reply));
2501 ioc->reply = NULL;
2502 }
2503
2504 if (ioc->reply_free) {
2505 pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free,
2506 ioc->reply_free_dma);
2507 if (ioc->reply_free_dma_pool)
2508 pci_pool_destroy(ioc->reply_free_dma_pool);
2509 dexitprintk(ioc, pr_info(MPT3SAS_FMT
2510 "reply_free_pool(0x%p): free\n",
2511 ioc->name, ioc->reply_free));
2512 ioc->reply_free = NULL;
2513 }
2514
2515 if (ioc->reply_post_free) {
2516 pci_pool_free(ioc->reply_post_free_dma_pool,
2517 ioc->reply_post_free, ioc->reply_post_free_dma);
2518 if (ioc->reply_post_free_dma_pool)
2519 pci_pool_destroy(ioc->reply_post_free_dma_pool);
2520 dexitprintk(ioc, pr_info(MPT3SAS_FMT
2521 "reply_post_free_pool(0x%p): free\n", ioc->name,
2522 ioc->reply_post_free));
2523 ioc->reply_post_free = NULL;
2524 }
2525
2526 if (ioc->config_page) {
2527 dexitprintk(ioc, pr_info(MPT3SAS_FMT
2528 "config_page(0x%p): free\n", ioc->name,
2529 ioc->config_page));
2530 pci_free_consistent(ioc->pdev, ioc->config_page_sz,
2531 ioc->config_page, ioc->config_page_dma);
2532 }
2533
2534 if (ioc->scsi_lookup) {
2535 free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages);
2536 ioc->scsi_lookup = NULL;
2537 }
2538 kfree(ioc->hpr_lookup);
2539 kfree(ioc->internal_lookup);
2540 if (ioc->chain_lookup) {
2541 for (i = 0; i < ioc->chain_depth; i++) {
2542 if (ioc->chain_lookup[i].chain_buffer)
2543 pci_pool_free(ioc->chain_dma_pool,
2544 ioc->chain_lookup[i].chain_buffer,
2545 ioc->chain_lookup[i].chain_buffer_dma);
2546 }
2547 if (ioc->chain_dma_pool)
2548 pci_pool_destroy(ioc->chain_dma_pool);
2549 free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
2550 ioc->chain_lookup = NULL;
2551 }
2552}
2553
2554/**
2555 * _base_allocate_memory_pools - allocate start of day memory pools
2556 * @ioc: per adapter object
2557 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2558 *
2559 * Returns 0 success, anything else error
2560 */
2561static int
2562_base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
2563{
2564 struct mpt3sas_facts *facts;
2565 u16 max_sge_elements;
2566 u16 chains_needed_per_io;
2567 u32 sz, total_sz, reply_post_free_sz;
2568 u32 retry_sz;
2569 u16 max_request_credit;
2570 unsigned short sg_tablesize;
2571 u16 sge_size;
2572 int i;
2573
2574 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
2575 __func__));
2576
2577
2578 retry_sz = 0;
2579 facts = &ioc->facts;
2580
2581 /* command line tunables for max sgl entries */
2582 if (max_sgl_entries != -1)
2583 sg_tablesize = max_sgl_entries;
2584 else
2585 sg_tablesize = MPT3SAS_SG_DEPTH;
2586
2587 if (sg_tablesize < MPT3SAS_MIN_PHYS_SEGMENTS)
2588 sg_tablesize = MPT3SAS_MIN_PHYS_SEGMENTS;
2589 else if (sg_tablesize > MPT3SAS_MAX_PHYS_SEGMENTS)
2590 sg_tablesize = MPT3SAS_MAX_PHYS_SEGMENTS;
2591 ioc->shost->sg_tablesize = sg_tablesize;
2592
2593 ioc->hi_priority_depth = facts->HighPriorityCredit;
2594 ioc->internal_depth = ioc->hi_priority_depth + (5);
2595 /* command line tunables for max controller queue depth */
2596 if (max_queue_depth != -1 && max_queue_depth != 0) {
2597 max_request_credit = min_t(u16, max_queue_depth +
2598 ioc->hi_priority_depth + ioc->internal_depth,
2599 facts->RequestCredit);
2600 if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
2601 max_request_credit = MAX_HBA_QUEUE_DEPTH;
2602 } else
2603 max_request_credit = min_t(u16, facts->RequestCredit,
2604 MAX_HBA_QUEUE_DEPTH);
2605
2606 ioc->hba_queue_depth = max_request_credit;
2607
2608 /* request frame size */
2609 ioc->request_sz = facts->IOCRequestFrameSize * 4;
2610
2611 /* reply frame size */
2612 ioc->reply_sz = facts->ReplyFrameSize * 4;
2613
2614 /* calculate the max scatter element size */
2615 sge_size = max_t(u16, ioc->sge_size, ioc->sge_size_ieee);
2616
2617 retry_allocation:
2618 total_sz = 0;
2619 /* calculate number of sg elements left over in the 1st frame */
2620 max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) -
2621 sizeof(Mpi2SGEIOUnion_t)) + sge_size);
2622 ioc->max_sges_in_main_message = max_sge_elements/sge_size;
2623
2624 /* now do the same for a chain buffer */
2625 max_sge_elements = ioc->request_sz - sge_size;
2626 ioc->max_sges_in_chain_message = max_sge_elements/sge_size;
2627
2628 /*
2629 * MPT3SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE
2630 */
2631 chains_needed_per_io = ((ioc->shost->sg_tablesize -
2632 ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message)
2633 + 1;
2634 if (chains_needed_per_io > facts->MaxChainDepth) {
2635 chains_needed_per_io = facts->MaxChainDepth;
2636 ioc->shost->sg_tablesize = min_t(u16,
2637 ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message
2638 * chains_needed_per_io), ioc->shost->sg_tablesize);
2639 }
2640 ioc->chains_needed_per_io = chains_needed_per_io;
2641
2642 /* reply free queue sizing - taking into account for 64 FW events */
2643 ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
2644
2645 /* calculate reply descriptor post queue depth */
2646 ioc->reply_post_queue_depth = ioc->hba_queue_depth +
2647 ioc->reply_free_queue_depth + 1 ;
2648 /* align the reply post queue on the next 16 count boundary */
2649 if (ioc->reply_post_queue_depth % 16)
2650 ioc->reply_post_queue_depth += 16 -
2651 (ioc->reply_post_queue_depth % 16);
2652
2653
2654 if (ioc->reply_post_queue_depth >
2655 facts->MaxReplyDescriptorPostQueueDepth) {
2656 ioc->reply_post_queue_depth =
2657 facts->MaxReplyDescriptorPostQueueDepth -
2658 (facts->MaxReplyDescriptorPostQueueDepth % 16);
2659 ioc->hba_queue_depth =
2660 ((ioc->reply_post_queue_depth - 64) / 2) - 1;
2661 ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
2662 }
2663
2664 dinitprintk(ioc, pr_info(MPT3SAS_FMT "scatter gather: " \
2665 "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
2666 "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message,
2667 ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
2668 ioc->chains_needed_per_io));
2669
2670 ioc->scsiio_depth = ioc->hba_queue_depth -
2671 ioc->hi_priority_depth - ioc->internal_depth;
2672
2673 /* set the scsi host can_queue depth
2674 * with some internal commands that could be outstanding
2675 */
2676 ioc->shost->can_queue = ioc->scsiio_depth;
2677 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2678 "scsi host: can_queue depth (%d)\n",
2679 ioc->name, ioc->shost->can_queue));
2680
2681
2682 /* contiguous pool for request and chains, 16 byte align, one extra "
2683 * "frame for smid=0
2684 */
2685 ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth;
2686 sz = ((ioc->scsiio_depth + 1) * ioc->request_sz);
2687
2688 /* hi-priority queue */
2689 sz += (ioc->hi_priority_depth * ioc->request_sz);
2690
2691 /* internal queue */
2692 sz += (ioc->internal_depth * ioc->request_sz);
2693
2694 ioc->request_dma_sz = sz;
2695 ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma);
2696 if (!ioc->request) {
2697 pr_err(MPT3SAS_FMT "request pool: pci_alloc_consistent " \
2698 "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
2699 "total(%d kB)\n", ioc->name, ioc->hba_queue_depth,
2700 ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
2701 if (ioc->scsiio_depth < MPT3SAS_SAS_QUEUE_DEPTH)
2702 goto out;
2703 retry_sz += 64;
2704 ioc->hba_queue_depth = max_request_credit - retry_sz;
2705 goto retry_allocation;
2706 }
2707
2708 if (retry_sz)
2709 pr_err(MPT3SAS_FMT "request pool: pci_alloc_consistent " \
2710 "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), "
2711 "total(%d kb)\n", ioc->name, ioc->hba_queue_depth,
2712 ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
2713
2714 /* hi-priority queue */
2715 ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) *
2716 ioc->request_sz);
2717 ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) *
2718 ioc->request_sz);
2719
2720 /* internal queue */
2721 ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth *
2722 ioc->request_sz);
2723 ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
2724 ioc->request_sz);
2725
2726 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2727 "request pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n",
2728 ioc->name, ioc->request, ioc->hba_queue_depth, ioc->request_sz,
2729 (ioc->hba_queue_depth * ioc->request_sz)/1024));
2730
2731 dinitprintk(ioc, pr_info(MPT3SAS_FMT "request pool: dma(0x%llx)\n",
2732 ioc->name, (unsigned long long) ioc->request_dma));
2733 total_sz += sz;
2734
2735 sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker);
2736 ioc->scsi_lookup_pages = get_order(sz);
2737 ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages(
2738 GFP_KERNEL, ioc->scsi_lookup_pages);
2739 if (!ioc->scsi_lookup) {
2740 pr_err(MPT3SAS_FMT "scsi_lookup: get_free_pages failed, sz(%d)\n",
2741 ioc->name, (int)sz);
2742 goto out;
2743 }
2744
2745 dinitprintk(ioc, pr_info(MPT3SAS_FMT "scsiio(0x%p): depth(%d)\n",
2746 ioc->name, ioc->request, ioc->scsiio_depth));
2747
2748 ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
2749 sz = ioc->chain_depth * sizeof(struct chain_tracker);
2750 ioc->chain_pages = get_order(sz);
2751 ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
2752 GFP_KERNEL, ioc->chain_pages);
2753 if (!ioc->chain_lookup) {
2754 pr_err(MPT3SAS_FMT "chain_lookup: __get_free_pages failed\n",
2755 ioc->name);
2756 goto out;
2757 }
2758 ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
2759 ioc->request_sz, 16, 0);
2760 if (!ioc->chain_dma_pool) {
2761 pr_err(MPT3SAS_FMT "chain_dma_pool: pci_pool_create failed\n",
2762 ioc->name);
2763 goto out;
2764 }
2765 for (i = 0; i < ioc->chain_depth; i++) {
2766 ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
2767 ioc->chain_dma_pool , GFP_KERNEL,
2768 &ioc->chain_lookup[i].chain_buffer_dma);
2769 if (!ioc->chain_lookup[i].chain_buffer) {
2770 ioc->chain_depth = i;
2771 goto chain_done;
2772 }
2773 total_sz += ioc->request_sz;
2774 }
2775 chain_done:
2776 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2777 "chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n",
2778 ioc->name, ioc->chain_depth, ioc->request_sz,
2779 ((ioc->chain_depth * ioc->request_sz))/1024));
2780
2781 /* initialize hi-priority queue smid's */
2782 ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
2783 sizeof(struct request_tracker), GFP_KERNEL);
2784 if (!ioc->hpr_lookup) {
2785 pr_err(MPT3SAS_FMT "hpr_lookup: kcalloc failed\n",
2786 ioc->name);
2787 goto out;
2788 }
2789 ioc->hi_priority_smid = ioc->scsiio_depth + 1;
2790 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2791 "hi_priority(0x%p): depth(%d), start smid(%d)\n",
2792 ioc->name, ioc->hi_priority,
2793 ioc->hi_priority_depth, ioc->hi_priority_smid));
2794
2795 /* initialize internal queue smid's */
2796 ioc->internal_lookup = kcalloc(ioc->internal_depth,
2797 sizeof(struct request_tracker), GFP_KERNEL);
2798 if (!ioc->internal_lookup) {
2799 pr_err(MPT3SAS_FMT "internal_lookup: kcalloc failed\n",
2800 ioc->name);
2801 goto out;
2802 }
2803 ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth;
2804 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2805 "internal(0x%p): depth(%d), start smid(%d)\n",
2806 ioc->name, ioc->internal,
2807 ioc->internal_depth, ioc->internal_smid));
2808
2809 /* sense buffers, 4 byte align */
2810 sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
2811 ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
2812 0);
2813 if (!ioc->sense_dma_pool) {
2814 pr_err(MPT3SAS_FMT "sense pool: pci_pool_create failed\n",
2815 ioc->name);
2816 goto out;
2817 }
2818 ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL,
2819 &ioc->sense_dma);
2820 if (!ioc->sense) {
2821 pr_err(MPT3SAS_FMT "sense pool: pci_pool_alloc failed\n",
2822 ioc->name);
2823 goto out;
2824 }
2825 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2826 "sense pool(0x%p): depth(%d), element_size(%d), pool_size"
2827 "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth,
2828 SCSI_SENSE_BUFFERSIZE, sz/1024));
2829 dinitprintk(ioc, pr_info(MPT3SAS_FMT "sense_dma(0x%llx)\n",
2830 ioc->name, (unsigned long long)ioc->sense_dma));
2831 total_sz += sz;
2832
2833 /* reply pool, 4 byte align */
2834 sz = ioc->reply_free_queue_depth * ioc->reply_sz;
2835 ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4,
2836 0);
2837 if (!ioc->reply_dma_pool) {
2838 pr_err(MPT3SAS_FMT "reply pool: pci_pool_create failed\n",
2839 ioc->name);
2840 goto out;
2841 }
2842 ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL,
2843 &ioc->reply_dma);
2844 if (!ioc->reply) {
2845 pr_err(MPT3SAS_FMT "reply pool: pci_pool_alloc failed\n",
2846 ioc->name);
2847 goto out;
2848 }
2849 ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
2850 ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
2851 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2852 "reply pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n",
2853 ioc->name, ioc->reply,
2854 ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
2855 dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply_dma(0x%llx)\n",
2856 ioc->name, (unsigned long long)ioc->reply_dma));
2857 total_sz += sz;
2858
2859 /* reply free queue, 16 byte align */
2860 sz = ioc->reply_free_queue_depth * 4;
2861 ioc->reply_free_dma_pool = pci_pool_create("reply_free pool",
2862 ioc->pdev, sz, 16, 0);
2863 if (!ioc->reply_free_dma_pool) {
2864 pr_err(MPT3SAS_FMT "reply_free pool: pci_pool_create failed\n",
2865 ioc->name);
2866 goto out;
2867 }
2868 ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL,
2869 &ioc->reply_free_dma);
2870 if (!ioc->reply_free) {
2871 pr_err(MPT3SAS_FMT "reply_free pool: pci_pool_alloc failed\n",
2872 ioc->name);
2873 goto out;
2874 }
2875 memset(ioc->reply_free, 0, sz);
2876 dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply_free pool(0x%p): " \
2877 "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name,
2878 ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024));
2879 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2880 "reply_free_dma (0x%llx)\n",
2881 ioc->name, (unsigned long long)ioc->reply_free_dma));
2882 total_sz += sz;
2883
2884 /* reply post queue, 16 byte align */
2885 reply_post_free_sz = ioc->reply_post_queue_depth *
2886 sizeof(Mpi2DefaultReplyDescriptor_t);
2887 if (_base_is_controller_msix_enabled(ioc))
2888 sz = reply_post_free_sz * ioc->reply_queue_count;
2889 else
2890 sz = reply_post_free_sz;
2891 ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
2892 ioc->pdev, sz, 16, 0);
2893 if (!ioc->reply_post_free_dma_pool) {
2894 pr_err(MPT3SAS_FMT
2895 "reply_post_free pool: pci_pool_create failed\n",
2896 ioc->name);
2897 goto out;
2898 }
2899 ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool ,
2900 GFP_KERNEL, &ioc->reply_post_free_dma);
2901 if (!ioc->reply_post_free) {
2902 pr_err(MPT3SAS_FMT
2903 "reply_post_free pool: pci_pool_alloc failed\n",
2904 ioc->name);
2905 goto out;
2906 }
2907 memset(ioc->reply_post_free, 0, sz);
2908 dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply post free pool" \
2909 "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
2910 ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8,
2911 sz/1024));
2912 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2913 "reply_post_free_dma = (0x%llx)\n",
2914 ioc->name, (unsigned long long)
2915 ioc->reply_post_free_dma));
2916 total_sz += sz;
2917
2918 ioc->config_page_sz = 512;
2919 ioc->config_page = pci_alloc_consistent(ioc->pdev,
2920 ioc->config_page_sz, &ioc->config_page_dma);
2921 if (!ioc->config_page) {
2922 pr_err(MPT3SAS_FMT
2923 "config page: pci_pool_alloc failed\n",
2924 ioc->name);
2925 goto out;
2926 }
2927 dinitprintk(ioc, pr_info(MPT3SAS_FMT
2928 "config page(0x%p): size(%d)\n",
2929 ioc->name, ioc->config_page, ioc->config_page_sz));
2930 dinitprintk(ioc, pr_info(MPT3SAS_FMT "config_page_dma(0x%llx)\n",
2931 ioc->name, (unsigned long long)ioc->config_page_dma));
2932 total_sz += ioc->config_page_sz;
2933
2934 pr_info(MPT3SAS_FMT "Allocated physical memory: size(%d kB)\n",
2935 ioc->name, total_sz/1024);
2936 pr_info(MPT3SAS_FMT
2937 "Current Controller Queue Depth(%d),Max Controller Queue Depth(%d)\n",
2938 ioc->name, ioc->shost->can_queue, facts->RequestCredit);
2939 pr_info(MPT3SAS_FMT "Scatter Gather Elements per IO(%d)\n",
2940 ioc->name, ioc->shost->sg_tablesize);
2941 return 0;
2942
2943 out:
2944 return -ENOMEM;
2945}
2946
2947/**
2948 * mpt3sas_base_get_iocstate - Get the current state of a MPT adapter.
2949 * @ioc: Pointer to MPT_ADAPTER structure
2950 * @cooked: Request raw or cooked IOC state
2951 *
2952 * Returns all IOC Doorbell register bits if cooked==0, else just the
2953 * Doorbell bits in MPI_IOC_STATE_MASK.
2954 */
2955u32
2956mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked)
2957{
2958 u32 s, sc;
2959
2960 s = readl(&ioc->chip->Doorbell);
2961 sc = s & MPI2_IOC_STATE_MASK;
2962 return cooked ? sc : s;
2963}
2964
2965/**
2966 * _base_wait_on_iocstate - waiting on a particular ioc state
2967 * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
2968 * @timeout: timeout in second
2969 * @sleep_flag: CAN_SLEEP or NO_SLEEP
2970 *
2971 * Returns 0 for success, non-zero for failure.
2972 */
2973static int
2974_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
2975 int sleep_flag)
2976{
2977 u32 count, cntdn;
2978 u32 current_state;
2979
2980 count = 0;
2981 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
2982 do {
2983 current_state = mpt3sas_base_get_iocstate(ioc, 1);
2984 if (current_state == ioc_state)
2985 return 0;
2986 if (count && current_state == MPI2_IOC_STATE_FAULT)
2987 break;
2988 if (sleep_flag == CAN_SLEEP)
2989 usleep_range(1000, 1500);
2990 else
2991 udelay(500);
2992 count++;
2993 } while (--cntdn);
2994
2995 return current_state;
2996}
2997
2998/**
2999 * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
3000 * a write to the doorbell)
3001 * @ioc: per adapter object
3002 * @timeout: timeout in second
3003 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3004 *
3005 * Returns 0 for success, non-zero for failure.
3006 *
3007 * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
3008 */
3009static int
3010_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout,
3011 int sleep_flag)
3012{
3013 u32 cntdn, count;
3014 u32 int_status;
3015
3016 count = 0;
3017 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
3018 do {
3019 int_status = readl(&ioc->chip->HostInterruptStatus);
3020 if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
3021 dhsprintk(ioc, pr_info(MPT3SAS_FMT
3022 "%s: successful count(%d), timeout(%d)\n",
3023 ioc->name, __func__, count, timeout));
3024 return 0;
3025 }
3026 if (sleep_flag == CAN_SLEEP)
3027 usleep_range(1000, 1500);
3028 else
3029 udelay(500);
3030 count++;
3031 } while (--cntdn);
3032
3033 pr_err(MPT3SAS_FMT
3034 "%s: failed due to timeout count(%d), int_status(%x)!\n",
3035 ioc->name, __func__, count, int_status);
3036 return -EFAULT;
3037}
3038
3039/**
3040 * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
3041 * @ioc: per adapter object
3042 * @timeout: timeout in second
3043 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3044 *
3045 * Returns 0 for success, non-zero for failure.
3046 *
3047 * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
3048 * doorbell.
3049 */
3050static int
3051_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout,
3052 int sleep_flag)
3053{
3054 u32 cntdn, count;
3055 u32 int_status;
3056 u32 doorbell;
3057
3058 count = 0;
3059 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
3060 do {
3061 int_status = readl(&ioc->chip->HostInterruptStatus);
3062 if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
3063 dhsprintk(ioc, pr_info(MPT3SAS_FMT
3064 "%s: successful count(%d), timeout(%d)\n",
3065 ioc->name, __func__, count, timeout));
3066 return 0;
3067 } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
3068 doorbell = readl(&ioc->chip->Doorbell);
3069 if ((doorbell & MPI2_IOC_STATE_MASK) ==
3070 MPI2_IOC_STATE_FAULT) {
3071 mpt3sas_base_fault_info(ioc , doorbell);
3072 return -EFAULT;
3073 }
3074 } else if (int_status == 0xFFFFFFFF)
3075 goto out;
3076
3077 if (sleep_flag == CAN_SLEEP)
3078 usleep_range(1000, 1500);
3079 else
3080 udelay(500);
3081 count++;
3082 } while (--cntdn);
3083
3084 out:
3085 pr_err(MPT3SAS_FMT
3086 "%s: failed due to timeout count(%d), int_status(%x)!\n",
3087 ioc->name, __func__, count, int_status);
3088 return -EFAULT;
3089}
3090
3091/**
3092 * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
3093 * @ioc: per adapter object
3094 * @timeout: timeout in second
3095 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3096 *
3097 * Returns 0 for success, non-zero for failure.
3098 *
3099 */
3100static int
3101_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout,
3102 int sleep_flag)
3103{
3104 u32 cntdn, count;
3105 u32 doorbell_reg;
3106
3107 count = 0;
3108 cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
3109 do {
3110 doorbell_reg = readl(&ioc->chip->Doorbell);
3111 if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
3112 dhsprintk(ioc, pr_info(MPT3SAS_FMT
3113 "%s: successful count(%d), timeout(%d)\n",
3114 ioc->name, __func__, count, timeout));
3115 return 0;
3116 }
3117 if (sleep_flag == CAN_SLEEP)
3118 usleep_range(1000, 1500);
3119 else
3120 udelay(500);
3121 count++;
3122 } while (--cntdn);
3123
3124 pr_err(MPT3SAS_FMT
3125 "%s: failed due to timeout count(%d), doorbell_reg(%x)!\n",
3126 ioc->name, __func__, count, doorbell_reg);
3127 return -EFAULT;
3128}
3129
3130/**
3131 * _base_send_ioc_reset - send doorbell reset
3132 * @ioc: per adapter object
3133 * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
3134 * @timeout: timeout in second
3135 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3136 *
3137 * Returns 0 for success, non-zero for failure.
3138 */
3139static int
3140_base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout,
3141 int sleep_flag)
3142{
3143 u32 ioc_state;
3144 int r = 0;
3145
3146 if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
3147 pr_err(MPT3SAS_FMT "%s: unknown reset_type\n",
3148 ioc->name, __func__);
3149 return -EFAULT;
3150 }
3151
3152 if (!(ioc->facts.IOCCapabilities &
3153 MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY))
3154 return -EFAULT;
3155
3156 pr_info(MPT3SAS_FMT "sending message unit reset !!\n", ioc->name);
3157
3158 writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
3159 &ioc->chip->Doorbell);
3160 if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
3161 r = -EFAULT;
3162 goto out;
3163 }
3164 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
3165 timeout, sleep_flag);
3166 if (ioc_state) {
3167 pr_err(MPT3SAS_FMT
3168 "%s: failed going to ready state (ioc_state=0x%x)\n",
3169 ioc->name, __func__, ioc_state);
3170 r = -EFAULT;
3171 goto out;
3172 }
3173 out:
3174 pr_info(MPT3SAS_FMT "message unit reset: %s\n",
3175 ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
3176 return r;
3177}
3178
3179/**
3180 * _base_handshake_req_reply_wait - send request thru doorbell interface
3181 * @ioc: per adapter object
3182 * @request_bytes: request length
3183 * @request: pointer having request payload
3184 * @reply_bytes: reply length
3185 * @reply: pointer to reply payload
3186 * @timeout: timeout in second
3187 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3188 *
3189 * Returns 0 for success, non-zero for failure.
3190 */
3191static int
3192_base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
3193 u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
3194{
3195 MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
3196 int i;
3197 u8 failed;
3198 u16 dummy;
3199 __le32 *mfp;
3200
3201 /* make sure doorbell is not in use */
3202 if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
3203 pr_err(MPT3SAS_FMT
3204 "doorbell is in use (line=%d)\n",
3205 ioc->name, __LINE__);
3206 return -EFAULT;
3207 }
3208
3209 /* clear pending doorbell interrupts from previous state changes */
3210 if (readl(&ioc->chip->HostInterruptStatus) &
3211 MPI2_HIS_IOC2SYS_DB_STATUS)
3212 writel(0, &ioc->chip->HostInterruptStatus);
3213
3214 /* send message to ioc */
3215 writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
3216 ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
3217 &ioc->chip->Doorbell);
3218
3219 if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) {
3220 pr_err(MPT3SAS_FMT
3221 "doorbell handshake int failed (line=%d)\n",
3222 ioc->name, __LINE__);
3223 return -EFAULT;
3224 }
3225 writel(0, &ioc->chip->HostInterruptStatus);
3226
3227 if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
3228 pr_err(MPT3SAS_FMT
3229 "doorbell handshake ack failed (line=%d)\n",
3230 ioc->name, __LINE__);
3231 return -EFAULT;
3232 }
3233
3234 /* send message 32-bits at a time */
3235 for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
3236 writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
3237 if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
3238 failed = 1;
3239 }
3240
3241 if (failed) {
3242 pr_err(MPT3SAS_FMT
3243 "doorbell handshake sending request failed (line=%d)\n",
3244 ioc->name, __LINE__);
3245 return -EFAULT;
3246 }
3247
3248 /* now wait for the reply */
3249 if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
3250 pr_err(MPT3SAS_FMT
3251 "doorbell handshake int failed (line=%d)\n",
3252 ioc->name, __LINE__);
3253 return -EFAULT;
3254 }
3255
3256 /* read the first two 16-bits, it gives the total length of the reply */
3257 reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
3258 & MPI2_DOORBELL_DATA_MASK);
3259 writel(0, &ioc->chip->HostInterruptStatus);
3260 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
3261 pr_err(MPT3SAS_FMT
3262 "doorbell handshake int failed (line=%d)\n",
3263 ioc->name, __LINE__);
3264 return -EFAULT;
3265 }
3266 reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
3267 & MPI2_DOORBELL_DATA_MASK);
3268 writel(0, &ioc->chip->HostInterruptStatus);
3269
3270 for (i = 2; i < default_reply->MsgLength * 2; i++) {
3271 if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
3272 pr_err(MPT3SAS_FMT
3273 "doorbell handshake int failed (line=%d)\n",
3274 ioc->name, __LINE__);
3275 return -EFAULT;
3276 }
3277 if (i >= reply_bytes/2) /* overflow case */
3278 dummy = readl(&ioc->chip->Doorbell);
3279 else
3280 reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
3281 & MPI2_DOORBELL_DATA_MASK);
3282 writel(0, &ioc->chip->HostInterruptStatus);
3283 }
3284
3285 _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
3286 if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
3287 dhsprintk(ioc, pr_info(MPT3SAS_FMT
3288 "doorbell is in use (line=%d)\n", ioc->name, __LINE__));
3289 }
3290 writel(0, &ioc->chip->HostInterruptStatus);
3291
3292 if (ioc->logging_level & MPT_DEBUG_INIT) {
3293 mfp = (__le32 *)reply;
3294 pr_info("\toffset:data\n");
3295 for (i = 0; i < reply_bytes/4; i++)
3296 pr_info("\t[0x%02x]:%08x\n", i*4,
3297 le32_to_cpu(mfp[i]));
3298 }
3299 return 0;
3300}
3301
3302/**
3303 * mpt3sas_base_sas_iounit_control - send sas iounit control to FW
3304 * @ioc: per adapter object
3305 * @mpi_reply: the reply payload from FW
3306 * @mpi_request: the request payload sent to FW
3307 *
3308 * The SAS IO Unit Control Request message allows the host to perform low-level
3309 * operations, such as resets on the PHYs of the IO Unit, also allows the host
3310 * to obtain the IOC assigned device handles for a device if it has other
3311 * identifying information about the device, in addition allows the host to
3312 * remove IOC resources associated with the device.
3313 *
3314 * Returns 0 for success, non-zero for failure.
3315 */
3316int
3317mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
3318 Mpi2SasIoUnitControlReply_t *mpi_reply,
3319 Mpi2SasIoUnitControlRequest_t *mpi_request)
3320{
3321 u16 smid;
3322 u32 ioc_state;
3323 unsigned long timeleft;
3324 u8 issue_reset;
3325 int rc;
3326 void *request;
3327 u16 wait_state_count;
3328
3329 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
3330 __func__));
3331
3332 mutex_lock(&ioc->base_cmds.mutex);
3333
3334 if (ioc->base_cmds.status != MPT3_CMD_NOT_USED) {
3335 pr_err(MPT3SAS_FMT "%s: base_cmd in use\n",
3336 ioc->name, __func__);
3337 rc = -EAGAIN;
3338 goto out;
3339 }
3340
3341 wait_state_count = 0;
3342 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3343 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3344 if (wait_state_count++ == 10) {
3345 pr_err(MPT3SAS_FMT
3346 "%s: failed due to ioc not operational\n",
3347 ioc->name, __func__);
3348 rc = -EFAULT;
3349 goto out;
3350 }
3351 ssleep(1);
3352 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3353 pr_info(MPT3SAS_FMT
3354 "%s: waiting for operational state(count=%d)\n",
3355 ioc->name, __func__, wait_state_count);
3356 }
3357
3358 smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
3359 if (!smid) {
3360 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3361 ioc->name, __func__);
3362 rc = -EAGAIN;
3363 goto out;
3364 }
3365
3366 rc = 0;
3367 ioc->base_cmds.status = MPT3_CMD_PENDING;
3368 request = mpt3sas_base_get_msg_frame(ioc, smid);
3369 ioc->base_cmds.smid = smid;
3370 memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t));
3371 if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
3372 mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
3373 ioc->ioc_link_reset_in_progress = 1;
3374 init_completion(&ioc->base_cmds.done);
3375 mpt3sas_base_put_smid_default(ioc, smid);
3376 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
3377 msecs_to_jiffies(10000));
3378 if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
3379 mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) &&
3380 ioc->ioc_link_reset_in_progress)
3381 ioc->ioc_link_reset_in_progress = 0;
3382 if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
3383 pr_err(MPT3SAS_FMT "%s: timeout\n",
3384 ioc->name, __func__);
3385 _debug_dump_mf(mpi_request,
3386 sizeof(Mpi2SasIoUnitControlRequest_t)/4);
3387 if (!(ioc->base_cmds.status & MPT3_CMD_RESET))
3388 issue_reset = 1;
3389 goto issue_host_reset;
3390 }
3391 if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID)
3392 memcpy(mpi_reply, ioc->base_cmds.reply,
3393 sizeof(Mpi2SasIoUnitControlReply_t));
3394 else
3395 memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t));
3396 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
3397 goto out;
3398
3399 issue_host_reset:
3400 if (issue_reset)
3401 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
3402 FORCE_BIG_HAMMER);
3403 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
3404 rc = -EFAULT;
3405 out:
3406 mutex_unlock(&ioc->base_cmds.mutex);
3407 return rc;
3408}
3409
3410/**
3411 * mpt3sas_base_scsi_enclosure_processor - sending request to sep device
3412 * @ioc: per adapter object
3413 * @mpi_reply: the reply payload from FW
3414 * @mpi_request: the request payload sent to FW
3415 *
3416 * The SCSI Enclosure Processor request message causes the IOC to
3417 * communicate with SES devices to control LED status signals.
3418 *
3419 * Returns 0 for success, non-zero for failure.
3420 */
3421int
3422mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
3423 Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
3424{
3425 u16 smid;
3426 u32 ioc_state;
3427 unsigned long timeleft;
3428 u8 issue_reset;
3429 int rc;
3430 void *request;
3431 u16 wait_state_count;
3432
3433 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
3434 __func__));
3435
3436 mutex_lock(&ioc->base_cmds.mutex);
3437
3438 if (ioc->base_cmds.status != MPT3_CMD_NOT_USED) {
3439 pr_err(MPT3SAS_FMT "%s: base_cmd in use\n",
3440 ioc->name, __func__);
3441 rc = -EAGAIN;
3442 goto out;
3443 }
3444
3445 wait_state_count = 0;
3446 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3447 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3448 if (wait_state_count++ == 10) {
3449 pr_err(MPT3SAS_FMT
3450 "%s: failed due to ioc not operational\n",
3451 ioc->name, __func__);
3452 rc = -EFAULT;
3453 goto out;
3454 }
3455 ssleep(1);
3456 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3457 pr_info(MPT3SAS_FMT
3458 "%s: waiting for operational state(count=%d)\n",
3459 ioc->name,
3460 __func__, wait_state_count);
3461 }
3462
3463 smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
3464 if (!smid) {
3465 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3466 ioc->name, __func__);
3467 rc = -EAGAIN;
3468 goto out;
3469 }
3470
3471 rc = 0;
3472 ioc->base_cmds.status = MPT3_CMD_PENDING;
3473 request = mpt3sas_base_get_msg_frame(ioc, smid);
3474 ioc->base_cmds.smid = smid;
3475 memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
3476 init_completion(&ioc->base_cmds.done);
3477 mpt3sas_base_put_smid_default(ioc, smid);
3478 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
3479 msecs_to_jiffies(10000));
3480 if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
3481 pr_err(MPT3SAS_FMT "%s: timeout\n",
3482 ioc->name, __func__);
3483 _debug_dump_mf(mpi_request,
3484 sizeof(Mpi2SepRequest_t)/4);
3485 if (!(ioc->base_cmds.status & MPT3_CMD_RESET))
3486 issue_reset = 1;
3487 goto issue_host_reset;
3488 }
3489 if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID)
3490 memcpy(mpi_reply, ioc->base_cmds.reply,
3491 sizeof(Mpi2SepReply_t));
3492 else
3493 memset(mpi_reply, 0, sizeof(Mpi2SepReply_t));
3494 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
3495 goto out;
3496
3497 issue_host_reset:
3498 if (issue_reset)
3499 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
3500 FORCE_BIG_HAMMER);
3501 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
3502 rc = -EFAULT;
3503 out:
3504 mutex_unlock(&ioc->base_cmds.mutex);
3505 return rc;
3506}
3507
3508/**
3509 * _base_get_port_facts - obtain port facts reply and save in ioc
3510 * @ioc: per adapter object
3511 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3512 *
3513 * Returns 0 for success, non-zero for failure.
3514 */
3515static int
3516_base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag)
3517{
3518 Mpi2PortFactsRequest_t mpi_request;
3519 Mpi2PortFactsReply_t mpi_reply;
3520 struct mpt3sas_port_facts *pfacts;
3521 int mpi_reply_sz, mpi_request_sz, r;
3522
3523 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
3524 __func__));
3525
3526 mpi_reply_sz = sizeof(Mpi2PortFactsReply_t);
3527 mpi_request_sz = sizeof(Mpi2PortFactsRequest_t);
3528 memset(&mpi_request, 0, mpi_request_sz);
3529 mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
3530 mpi_request.PortNumber = port;
3531 r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
3532 (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
3533
3534 if (r != 0) {
3535 pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n",
3536 ioc->name, __func__, r);
3537 return r;
3538 }
3539
3540 pfacts = &ioc->pfacts[port];
3541 memset(pfacts, 0, sizeof(struct mpt3sas_port_facts));
3542 pfacts->PortNumber = mpi_reply.PortNumber;
3543 pfacts->VP_ID = mpi_reply.VP_ID;
3544 pfacts->VF_ID = mpi_reply.VF_ID;
3545 pfacts->MaxPostedCmdBuffers =
3546 le16_to_cpu(mpi_reply.MaxPostedCmdBuffers);
3547
3548 return 0;
3549}
3550
3551/**
3552 * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
3553 * @ioc: per adapter object
3554 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3555 *
3556 * Returns 0 for success, non-zero for failure.
3557 */
3558static int
3559_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
3560{
3561 Mpi2IOCFactsRequest_t mpi_request;
3562 Mpi2IOCFactsReply_t mpi_reply;
3563 struct mpt3sas_facts *facts;
3564 int mpi_reply_sz, mpi_request_sz, r;
3565
3566 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
3567 __func__));
3568
3569 mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
3570 mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
3571 memset(&mpi_request, 0, mpi_request_sz);
3572 mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
3573 r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
3574 (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
3575
3576 if (r != 0) {
3577 pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n",
3578 ioc->name, __func__, r);
3579 return r;
3580 }
3581
3582 facts = &ioc->facts;
3583 memset(facts, 0, sizeof(struct mpt3sas_facts));
3584 facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
3585 facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
3586 facts->VP_ID = mpi_reply.VP_ID;
3587 facts->VF_ID = mpi_reply.VF_ID;
3588 facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
3589 facts->MaxChainDepth = mpi_reply.MaxChainDepth;
3590 facts->WhoInit = mpi_reply.WhoInit;
3591 facts->NumberOfPorts = mpi_reply.NumberOfPorts;
3592 facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors;
3593 facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
3594 facts->MaxReplyDescriptorPostQueueDepth =
3595 le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
3596 facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
3597 facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
3598 if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
3599 ioc->ir_firmware = 1;
3600 facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
3601 facts->IOCRequestFrameSize =
3602 le16_to_cpu(mpi_reply.IOCRequestFrameSize);
3603 facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
3604 facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
3605 ioc->shost->max_id = -1;
3606 facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
3607 facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
3608 facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
3609 facts->HighPriorityCredit =
3610 le16_to_cpu(mpi_reply.HighPriorityCredit);
3611 facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
3612 facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
3613
3614 dinitprintk(ioc, pr_info(MPT3SAS_FMT
3615 "hba queue depth(%d), max chains per io(%d)\n",
3616 ioc->name, facts->RequestCredit,
3617 facts->MaxChainDepth));
3618 dinitprintk(ioc, pr_info(MPT3SAS_FMT
3619 "request frame size(%d), reply frame size(%d)\n", ioc->name,
3620 facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
3621 return 0;
3622}
3623
3624/**
3625 * _base_send_ioc_init - send ioc_init to firmware
3626 * @ioc: per adapter object
3627 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3628 *
3629 * Returns 0 for success, non-zero for failure.
3630 */
3631static int
3632_base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
3633{
3634 Mpi2IOCInitRequest_t mpi_request;
3635 Mpi2IOCInitReply_t mpi_reply;
3636 int r;
3637 struct timeval current_time;
3638 u16 ioc_status;
3639
3640 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
3641 __func__));
3642
3643 memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t));
3644 mpi_request.Function = MPI2_FUNCTION_IOC_INIT;
3645 mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
3646 mpi_request.VF_ID = 0; /* TODO */
3647 mpi_request.VP_ID = 0;
3648 mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
3649 mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
3650
3651 if (_base_is_controller_msix_enabled(ioc))
3652 mpi_request.HostMSIxVectors = ioc->reply_queue_count;
3653 mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
3654 mpi_request.ReplyDescriptorPostQueueDepth =
3655 cpu_to_le16(ioc->reply_post_queue_depth);
3656 mpi_request.ReplyFreeQueueDepth =
3657 cpu_to_le16(ioc->reply_free_queue_depth);
3658
3659 mpi_request.SenseBufferAddressHigh =
3660 cpu_to_le32((u64)ioc->sense_dma >> 32);
3661 mpi_request.SystemReplyAddressHigh =
3662 cpu_to_le32((u64)ioc->reply_dma >> 32);
3663 mpi_request.SystemRequestFrameBaseAddress =
3664 cpu_to_le64((u64)ioc->request_dma);
3665 mpi_request.ReplyFreeQueueAddress =
3666 cpu_to_le64((u64)ioc->reply_free_dma);
3667 mpi_request.ReplyDescriptorPostQueueAddress =
3668 cpu_to_le64((u64)ioc->reply_post_free_dma);
3669
3670
3671 /* This time stamp specifies number of milliseconds
3672 * since epoch ~ midnight January 1, 1970.
3673 */
3674 do_gettimeofday(&current_time);
3675 mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 +
3676 (current_time.tv_usec / 1000));
3677
3678 if (ioc->logging_level & MPT_DEBUG_INIT) {
3679 __le32 *mfp;
3680 int i;
3681
3682 mfp = (__le32 *)&mpi_request;
3683 pr_info("\toffset:data\n");
3684 for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
3685 pr_info("\t[0x%02x]:%08x\n", i*4,
3686 le32_to_cpu(mfp[i]));
3687 }
3688
3689 r = _base_handshake_req_reply_wait(ioc,
3690 sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
3691 sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
3692 sleep_flag);
3693
3694 if (r != 0) {
3695 pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n",
3696 ioc->name, __func__, r);
3697 return r;
3698 }
3699
3700 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
3701 if (ioc_status != MPI2_IOCSTATUS_SUCCESS ||
3702 mpi_reply.IOCLogInfo) {
3703 pr_err(MPT3SAS_FMT "%s: failed\n", ioc->name, __func__);
3704 r = -EIO;
3705 }
3706
3707 return 0;
3708}
3709
3710/**
3711 * mpt3sas_port_enable_done - command completion routine for port enable
3712 * @ioc: per adapter object
3713 * @smid: system request message index
3714 * @msix_index: MSIX table index supplied by the OS
3715 * @reply: reply message frame(lower 32bit addr)
3716 *
3717 * Return 1 meaning mf should be freed from _base_interrupt
3718 * 0 means the mf is freed from this function.
3719 */
3720u8
3721mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
3722 u32 reply)
3723{
3724 MPI2DefaultReply_t *mpi_reply;
3725 u16 ioc_status;
3726
3727 if (ioc->port_enable_cmds.status == MPT3_CMD_NOT_USED)
3728 return 1;
3729
3730 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
3731 if (!mpi_reply)
3732 return 1;
3733
3734 if (mpi_reply->Function != MPI2_FUNCTION_PORT_ENABLE)
3735 return 1;
3736
3737 ioc->port_enable_cmds.status &= ~MPT3_CMD_PENDING;
3738 ioc->port_enable_cmds.status |= MPT3_CMD_COMPLETE;
3739 ioc->port_enable_cmds.status |= MPT3_CMD_REPLY_VALID;
3740 memcpy(ioc->port_enable_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
3741 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
3742 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
3743 ioc->port_enable_failed = 1;
3744
3745 if (ioc->is_driver_loading) {
3746 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
3747 mpt3sas_port_enable_complete(ioc);
3748 return 1;
3749 } else {
3750 ioc->start_scan_failed = ioc_status;
3751 ioc->start_scan = 0;
3752 return 1;
3753 }
3754 }
3755 complete(&ioc->port_enable_cmds.done);
3756 return 1;
3757}
3758
3759/**
3760 * _base_send_port_enable - send port_enable(discovery stuff) to firmware
3761 * @ioc: per adapter object
3762 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3763 *
3764 * Returns 0 for success, non-zero for failure.
3765 */
3766static int
3767_base_send_port_enable(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
3768{
3769 Mpi2PortEnableRequest_t *mpi_request;
3770 Mpi2PortEnableReply_t *mpi_reply;
3771 unsigned long timeleft;
3772 int r = 0;
3773 u16 smid;
3774 u16 ioc_status;
3775
3776 pr_info(MPT3SAS_FMT "sending port enable !!\n", ioc->name);
3777
3778 if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) {
3779 pr_err(MPT3SAS_FMT "%s: internal command already in use\n",
3780 ioc->name, __func__);
3781 return -EAGAIN;
3782 }
3783
3784 smid = mpt3sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
3785 if (!smid) {
3786 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3787 ioc->name, __func__);
3788 return -EAGAIN;
3789 }
3790
3791 ioc->port_enable_cmds.status = MPT3_CMD_PENDING;
3792 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3793 ioc->port_enable_cmds.smid = smid;
3794 memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
3795 mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
3796
3797 init_completion(&ioc->port_enable_cmds.done);
3798 mpt3sas_base_put_smid_default(ioc, smid);
3799 timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done,
3800 300*HZ);
3801 if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) {
3802 pr_err(MPT3SAS_FMT "%s: timeout\n",
3803 ioc->name, __func__);
3804 _debug_dump_mf(mpi_request,
3805 sizeof(Mpi2PortEnableRequest_t)/4);
3806 if (ioc->port_enable_cmds.status & MPT3_CMD_RESET)
3807 r = -EFAULT;
3808 else
3809 r = -ETIME;
3810 goto out;
3811 }
3812
3813 mpi_reply = ioc->port_enable_cmds.reply;
3814 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
3815 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
3816 pr_err(MPT3SAS_FMT "%s: failed with (ioc_status=0x%08x)\n",
3817 ioc->name, __func__, ioc_status);
3818 r = -EFAULT;
3819 goto out;
3820 }
3821
3822 out:
3823 ioc->port_enable_cmds.status = MPT3_CMD_NOT_USED;
3824 pr_info(MPT3SAS_FMT "port enable: %s\n", ioc->name, ((r == 0) ?
3825 "SUCCESS" : "FAILED"));
3826 return r;
3827}
3828
3829/**
3830 * mpt3sas_port_enable - initiate firmware discovery (don't wait for reply)
3831 * @ioc: per adapter object
3832 *
3833 * Returns 0 for success, non-zero for failure.
3834 */
3835int
3836mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc)
3837{
3838 Mpi2PortEnableRequest_t *mpi_request;
3839 u16 smid;
3840
3841 pr_info(MPT3SAS_FMT "sending port enable !!\n", ioc->name);
3842
3843 if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) {
3844 pr_err(MPT3SAS_FMT "%s: internal command already in use\n",
3845 ioc->name, __func__);
3846 return -EAGAIN;
3847 }
3848
3849 smid = mpt3sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
3850 if (!smid) {
3851 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3852 ioc->name, __func__);
3853 return -EAGAIN;
3854 }
3855
3856 ioc->port_enable_cmds.status = MPT3_CMD_PENDING;
3857 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3858 ioc->port_enable_cmds.smid = smid;
3859 memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
3860 mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
3861
3862 mpt3sas_base_put_smid_default(ioc, smid);
3863 return 0;
3864}
3865
3866/**
3867 * _base_determine_wait_on_discovery - desposition
3868 * @ioc: per adapter object
3869 *
3870 * Decide whether to wait on discovery to complete. Used to either
3871 * locate boot device, or report volumes ahead of physical devices.
3872 *
3873 * Returns 1 for wait, 0 for don't wait
3874 */
3875static int
3876_base_determine_wait_on_discovery(struct MPT3SAS_ADAPTER *ioc)
3877{
3878 /* We wait for discovery to complete if IR firmware is loaded.
3879 * The sas topology events arrive before PD events, so we need time to
3880 * turn on the bit in ioc->pd_handles to indicate PD
3881 * Also, it maybe required to report Volumes ahead of physical
3882 * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set.
3883 */
3884 if (ioc->ir_firmware)
3885 return 1;
3886
3887 /* if no Bios, then we don't need to wait */
3888 if (!ioc->bios_pg3.BiosVersion)
3889 return 0;
3890
3891 /* Bios is present, then we drop down here.
3892 *
3893 * If there any entries in the Bios Page 2, then we wait
3894 * for discovery to complete.
3895 */
3896
3897 /* Current Boot Device */
3898 if ((ioc->bios_pg2.CurrentBootDeviceForm &
3899 MPI2_BIOSPAGE2_FORM_MASK) ==
3900 MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
3901 /* Request Boot Device */
3902 (ioc->bios_pg2.ReqBootDeviceForm &
3903 MPI2_BIOSPAGE2_FORM_MASK) ==
3904 MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
3905 /* Alternate Request Boot Device */
3906 (ioc->bios_pg2.ReqAltBootDeviceForm &
3907 MPI2_BIOSPAGE2_FORM_MASK) ==
3908 MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED)
3909 return 0;
3910
3911 return 1;
3912}
3913
3914/**
3915 * _base_unmask_events - turn on notification for this event
3916 * @ioc: per adapter object
3917 * @event: firmware event
3918 *
3919 * The mask is stored in ioc->event_masks.
3920 */
3921static void
3922_base_unmask_events(struct MPT3SAS_ADAPTER *ioc, u16 event)
3923{
3924 u32 desired_event;
3925
3926 if (event >= 128)
3927 return;
3928
3929 desired_event = (1 << (event % 32));
3930
3931 if (event < 32)
3932 ioc->event_masks[0] &= ~desired_event;
3933 else if (event < 64)
3934 ioc->event_masks[1] &= ~desired_event;
3935 else if (event < 96)
3936 ioc->event_masks[2] &= ~desired_event;
3937 else if (event < 128)
3938 ioc->event_masks[3] &= ~desired_event;
3939}
3940
3941/**
3942 * _base_event_notification - send event notification
3943 * @ioc: per adapter object
3944 * @sleep_flag: CAN_SLEEP or NO_SLEEP
3945 *
3946 * Returns 0 for success, non-zero for failure.
3947 */
3948static int
3949_base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
3950{
3951 Mpi2EventNotificationRequest_t *mpi_request;
3952 unsigned long timeleft;
3953 u16 smid;
3954 int r = 0;
3955 int i;
3956
3957 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
3958 __func__));
3959
3960 if (ioc->base_cmds.status & MPT3_CMD_PENDING) {
3961 pr_err(MPT3SAS_FMT "%s: internal command already in use\n",
3962 ioc->name, __func__);
3963 return -EAGAIN;
3964 }
3965
3966 smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
3967 if (!smid) {
3968 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3969 ioc->name, __func__);
3970 return -EAGAIN;
3971 }
3972 ioc->base_cmds.status = MPT3_CMD_PENDING;
3973 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3974 ioc->base_cmds.smid = smid;
3975 memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
3976 mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
3977 mpi_request->VF_ID = 0; /* TODO */
3978 mpi_request->VP_ID = 0;
3979 for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
3980 mpi_request->EventMasks[i] =
3981 cpu_to_le32(ioc->event_masks[i]);
3982 init_completion(&ioc->base_cmds.done);
3983 mpt3sas_base_put_smid_default(ioc, smid);
3984 timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
3985 if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
3986 pr_err(MPT3SAS_FMT "%s: timeout\n",
3987 ioc->name, __func__);
3988 _debug_dump_mf(mpi_request,
3989 sizeof(Mpi2EventNotificationRequest_t)/4);
3990 if (ioc->base_cmds.status & MPT3_CMD_RESET)
3991 r = -EFAULT;
3992 else
3993 r = -ETIME;
3994 } else
3995 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s: complete\n",
3996 ioc->name, __func__));
3997 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
3998 return r;
3999}
4000
4001/**
4002 * mpt3sas_base_validate_event_type - validating event types
4003 * @ioc: per adapter object
4004 * @event: firmware event
4005 *
4006 * This will turn on firmware event notification when application
4007 * ask for that event. We don't mask events that are already enabled.
4008 */
4009void
4010mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, u32 *event_type)
4011{
4012 int i, j;
4013 u32 event_mask, desired_event;
4014 u8 send_update_to_fw;
4015
4016 for (i = 0, send_update_to_fw = 0; i <
4017 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) {
4018 event_mask = ~event_type[i];
4019 desired_event = 1;
4020 for (j = 0; j < 32; j++) {
4021 if (!(event_mask & desired_event) &&
4022 (ioc->event_masks[i] & desired_event)) {
4023 ioc->event_masks[i] &= ~desired_event;
4024 send_update_to_fw = 1;
4025 }
4026 desired_event = (desired_event << 1);
4027 }
4028 }
4029
4030 if (!send_update_to_fw)
4031 return;
4032
4033 mutex_lock(&ioc->base_cmds.mutex);
4034 _base_event_notification(ioc, CAN_SLEEP);
4035 mutex_unlock(&ioc->base_cmds.mutex);
4036}
4037
4038/**
4039 * _base_diag_reset - the "big hammer" start of day reset
4040 * @ioc: per adapter object
4041 * @sleep_flag: CAN_SLEEP or NO_SLEEP
4042 *
4043 * Returns 0 for success, non-zero for failure.
4044 */
4045static int
4046_base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
4047{
4048 u32 host_diagnostic;
4049 u32 ioc_state;
4050 u32 count;
4051 u32 hcb_size;
4052
4053 pr_info(MPT3SAS_FMT "sending diag reset !!\n", ioc->name);
4054
4055 drsprintk(ioc, pr_info(MPT3SAS_FMT "clear interrupts\n",
4056 ioc->name));
4057
4058 count = 0;
4059 do {
4060 /* Write magic sequence to WriteSequence register
4061 * Loop until in diagnostic mode
4062 */
4063 drsprintk(ioc, pr_info(MPT3SAS_FMT
4064 "write magic sequence\n", ioc->name));
4065 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
4066 writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence);
4067 writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence);
4068 writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence);
4069 writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence);
4070 writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence);
4071 writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
4072
4073 /* wait 100 msec */
4074 if (sleep_flag == CAN_SLEEP)
4075 msleep(100);
4076 else
4077 mdelay(100);
4078
4079 if (count++ > 20)
4080 goto out;
4081
4082 host_diagnostic = readl(&ioc->chip->HostDiagnostic);
4083 drsprintk(ioc, pr_info(MPT3SAS_FMT
4084 "wrote magic sequence: count(%d), host_diagnostic(0x%08x)\n",
4085 ioc->name, count, host_diagnostic));
4086
4087 } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0);
4088
4089 hcb_size = readl(&ioc->chip->HCBSize);
4090
4091 drsprintk(ioc, pr_info(MPT3SAS_FMT "diag reset: issued\n",
4092 ioc->name));
4093 writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
4094 &ioc->chip->HostDiagnostic);
4095
4096 /* don't access any registers for 50 milliseconds */
4097 msleep(50);
4098
4099 /* 300 second max wait */
4100 for (count = 0; count < 3000000 ; count++) {
4101
4102 host_diagnostic = readl(&ioc->chip->HostDiagnostic);
4103
4104 if (host_diagnostic == 0xFFFFFFFF)
4105 goto out;
4106 if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
4107 break;
4108
4109 /* wait 1 msec */
4110 if (sleep_flag == CAN_SLEEP)
4111 usleep_range(1000, 1500);
4112 else
4113 mdelay(1);
4114 }
4115
4116 if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
4117
4118 drsprintk(ioc, pr_info(MPT3SAS_FMT
4119 "restart the adapter assuming the HCB Address points to good F/W\n",
4120 ioc->name));
4121 host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
4122 host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
4123 writel(host_diagnostic, &ioc->chip->HostDiagnostic);
4124
4125 drsprintk(ioc, pr_info(MPT3SAS_FMT
4126 "re-enable the HCDW\n", ioc->name));
4127 writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,
4128 &ioc->chip->HCBSize);
4129 }
4130
4131 drsprintk(ioc, pr_info(MPT3SAS_FMT "restart the adapter\n",
4132 ioc->name));
4133 writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,
4134 &ioc->chip->HostDiagnostic);
4135
4136 drsprintk(ioc, pr_info(MPT3SAS_FMT
4137 "disable writes to the diagnostic register\n", ioc->name));
4138 writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
4139
4140 drsprintk(ioc, pr_info(MPT3SAS_FMT
4141 "Wait for FW to go to the READY state\n", ioc->name));
4142 ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
4143 sleep_flag);
4144 if (ioc_state) {
4145 pr_err(MPT3SAS_FMT
4146 "%s: failed going to ready state (ioc_state=0x%x)\n",
4147 ioc->name, __func__, ioc_state);
4148 goto out;
4149 }
4150
4151 pr_info(MPT3SAS_FMT "diag reset: SUCCESS\n", ioc->name);
4152 return 0;
4153
4154 out:
4155 pr_err(MPT3SAS_FMT "diag reset: FAILED\n", ioc->name);
4156 return -EFAULT;
4157}
4158
4159/**
4160 * _base_make_ioc_ready - put controller in READY state
4161 * @ioc: per adapter object
4162 * @sleep_flag: CAN_SLEEP or NO_SLEEP
4163 * @type: FORCE_BIG_HAMMER or SOFT_RESET
4164 *
4165 * Returns 0 for success, non-zero for failure.
4166 */
4167static int
4168_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
4169 enum reset_type type)
4170{
4171 u32 ioc_state;
4172 int rc;
4173 int count;
4174
4175 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
4176 __func__));
4177
4178 if (ioc->pci_error_recovery)
4179 return 0;
4180
4181 ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
4182 dhsprintk(ioc, pr_info(MPT3SAS_FMT "%s: ioc_state(0x%08x)\n",
4183 ioc->name, __func__, ioc_state));
4184
4185 /* if in RESET state, it should move to READY state shortly */
4186 count = 0;
4187 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
4188 while ((ioc_state & MPI2_IOC_STATE_MASK) !=
4189 MPI2_IOC_STATE_READY) {
4190 if (count++ == 10) {
4191 pr_err(MPT3SAS_FMT
4192 "%s: failed going to ready state (ioc_state=0x%x)\n",
4193 ioc->name, __func__, ioc_state);
4194 return -EFAULT;
4195 }
4196 if (sleep_flag == CAN_SLEEP)
4197 ssleep(1);
4198 else
4199 mdelay(1000);
4200 ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
4201 }
4202 }
4203
4204 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)
4205 return 0;
4206
4207 if (ioc_state & MPI2_DOORBELL_USED) {
4208 dhsprintk(ioc, pr_info(MPT3SAS_FMT
4209 "unexpected doorbell active!\n",
4210 ioc->name));
4211 goto issue_diag_reset;
4212 }
4213
4214 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
4215 mpt3sas_base_fault_info(ioc, ioc_state &
4216 MPI2_DOORBELL_DATA_MASK);
4217 goto issue_diag_reset;
4218 }
4219
4220 if (type == FORCE_BIG_HAMMER)
4221 goto issue_diag_reset;
4222
4223 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
4224 if (!(_base_send_ioc_reset(ioc,
4225 MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) {
4226 return 0;
4227 }
4228
4229 issue_diag_reset:
4230 rc = _base_diag_reset(ioc, CAN_SLEEP);
4231 return rc;
4232}
4233
4234/**
4235 * _base_make_ioc_operational - put controller in OPERATIONAL state
4236 * @ioc: per adapter object
4237 * @sleep_flag: CAN_SLEEP or NO_SLEEP
4238 *
4239 * Returns 0 for success, non-zero for failure.
4240 */
4241static int
4242_base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
4243{
4244 int r, i;
4245 unsigned long flags;
4246 u32 reply_address;
4247 u16 smid;
4248 struct _tr_list *delayed_tr, *delayed_tr_next;
4249 struct adapter_reply_queue *reply_q;
4250 long reply_post_free;
4251 u32 reply_post_free_sz;
4252
4253 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
4254 __func__));
4255
4256 /* clean the delayed target reset list */
4257 list_for_each_entry_safe(delayed_tr, delayed_tr_next,
4258 &ioc->delayed_tr_list, list) {
4259 list_del(&delayed_tr->list);
4260 kfree(delayed_tr);
4261 }
4262
4263
4264 list_for_each_entry_safe(delayed_tr, delayed_tr_next,
4265 &ioc->delayed_tr_volume_list, list) {
4266 list_del(&delayed_tr->list);
4267 kfree(delayed_tr);
4268 }
4269
4270 /* initialize the scsi lookup free list */
4271 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
4272 INIT_LIST_HEAD(&ioc->free_list);
4273 smid = 1;
4274 for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
4275 INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
4276 ioc->scsi_lookup[i].cb_idx = 0xFF;
4277 ioc->scsi_lookup[i].smid = smid;
4278 ioc->scsi_lookup[i].scmd = NULL;
4279 list_add_tail(&ioc->scsi_lookup[i].tracker_list,
4280 &ioc->free_list);
4281 }
4282
4283 /* hi-priority queue */
4284 INIT_LIST_HEAD(&ioc->hpr_free_list);
4285 smid = ioc->hi_priority_smid;
4286 for (i = 0; i < ioc->hi_priority_depth; i++, smid++) {
4287 ioc->hpr_lookup[i].cb_idx = 0xFF;
4288 ioc->hpr_lookup[i].smid = smid;
4289 list_add_tail(&ioc->hpr_lookup[i].tracker_list,
4290 &ioc->hpr_free_list);
4291 }
4292
4293 /* internal queue */
4294 INIT_LIST_HEAD(&ioc->internal_free_list);
4295 smid = ioc->internal_smid;
4296 for (i = 0; i < ioc->internal_depth; i++, smid++) {
4297 ioc->internal_lookup[i].cb_idx = 0xFF;
4298 ioc->internal_lookup[i].smid = smid;
4299 list_add_tail(&ioc->internal_lookup[i].tracker_list,
4300 &ioc->internal_free_list);
4301 }
4302
4303 /* chain pool */
4304 INIT_LIST_HEAD(&ioc->free_chain_list);
4305 for (i = 0; i < ioc->chain_depth; i++)
4306 list_add_tail(&ioc->chain_lookup[i].tracker_list,
4307 &ioc->free_chain_list);
4308
4309 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
4310
4311 /* initialize Reply Free Queue */
4312 for (i = 0, reply_address = (u32)ioc->reply_dma ;
4313 i < ioc->reply_free_queue_depth ; i++, reply_address +=
4314 ioc->reply_sz)
4315 ioc->reply_free[i] = cpu_to_le32(reply_address);
4316
4317 /* initialize reply queues */
4318 if (ioc->is_driver_loading)
4319 _base_assign_reply_queues(ioc);
4320
4321 /* initialize Reply Post Free Queue */
4322 reply_post_free = (long)ioc->reply_post_free;
4323 reply_post_free_sz = ioc->reply_post_queue_depth *
4324 sizeof(Mpi2DefaultReplyDescriptor_t);
4325 list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
4326 reply_q->reply_post_host_index = 0;
4327 reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
4328 reply_post_free;
4329 for (i = 0; i < ioc->reply_post_queue_depth; i++)
4330 reply_q->reply_post_free[i].Words =
4331 cpu_to_le64(ULLONG_MAX);
4332 if (!_base_is_controller_msix_enabled(ioc))
4333 goto skip_init_reply_post_free_queue;
4334 reply_post_free += reply_post_free_sz;
4335 }
4336 skip_init_reply_post_free_queue:
4337
4338 r = _base_send_ioc_init(ioc, sleep_flag);
4339 if (r)
4340 return r;
4341
4342 /* initialize reply free host index */
4343 ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
4344 writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
4345
4346 /* initialize reply post host index */
4347 list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
4348 writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT,
4349 &ioc->chip->ReplyPostHostIndex);
4350 if (!_base_is_controller_msix_enabled(ioc))
4351 goto skip_init_reply_post_host_index;
4352 }
4353
4354 skip_init_reply_post_host_index:
4355
4356 _base_unmask_interrupts(ioc);
4357 r = _base_event_notification(ioc, sleep_flag);
4358 if (r)
4359 return r;
4360
4361 if (sleep_flag == CAN_SLEEP)
4362 _base_static_config_pages(ioc);
4363
4364
4365 if (ioc->is_driver_loading) {
4366 ioc->wait_for_discovery_to_complete =
4367 _base_determine_wait_on_discovery(ioc);
4368
4369 return r; /* scan_start and scan_finished support */
4370 }
4371
4372 r = _base_send_port_enable(ioc, sleep_flag);
4373 if (r)
4374 return r;
4375
4376 return r;
4377}
4378
4379/**
4380 * mpt3sas_base_free_resources - free resources controller resources
4381 * @ioc: per adapter object
4382 *
4383 * Return nothing.
4384 */
4385void
4386mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc)
4387{
4388 struct pci_dev *pdev = ioc->pdev;
4389
4390 dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
4391 __func__));
4392
4393 _base_mask_interrupts(ioc);
4394 ioc->shost_recovery = 1;
4395 _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
4396 ioc->shost_recovery = 0;
4397 _base_free_irq(ioc);
4398 _base_disable_msix(ioc);
4399 if (ioc->chip_phys)
4400 iounmap(ioc->chip);
4401 ioc->chip_phys = 0;
4402 pci_release_selected_regions(ioc->pdev, ioc->bars);
4403 pci_disable_pcie_error_reporting(pdev);
4404 pci_disable_device(pdev);
4405 return;
4406}
4407
4408/**
4409 * mpt3sas_base_attach - attach controller instance
4410 * @ioc: per adapter object
4411 *
4412 * Returns 0 for success, non-zero for failure.
4413 */
4414int
4415mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
4416{
4417 int r, i;
4418 int cpu_id, last_cpu_id = 0;
4419
4420 dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
4421 __func__));
4422
4423 /* setup cpu_msix_table */
4424 ioc->cpu_count = num_online_cpus();
4425 for_each_online_cpu(cpu_id)
4426 last_cpu_id = cpu_id;
4427 ioc->cpu_msix_table_sz = last_cpu_id + 1;
4428 ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL);
4429 ioc->reply_queue_count = 1;
4430 if (!ioc->cpu_msix_table) {
4431 dfailprintk(ioc, pr_info(MPT3SAS_FMT
4432 "allocation for cpu_msix_table failed!!!\n",
4433 ioc->name));
4434 r = -ENOMEM;
4435 goto out_free_resources;
4436 }
4437
4438 r = mpt3sas_base_map_resources(ioc);
4439 if (r)
4440 goto out_free_resources;
4441
4442
4443 pci_set_drvdata(ioc->pdev, ioc->shost);
4444 r = _base_get_ioc_facts(ioc, CAN_SLEEP);
4445 if (r)
4446 goto out_free_resources;
4447
4448 /*
4449 * In SAS3.0,
4450 * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and
4451 * Target Status - all require the IEEE formated scatter gather
4452 * elements.
4453 */
4454
4455 ioc->build_sg_scmd = &_base_build_sg_scmd_ieee;
4456 ioc->build_sg = &_base_build_sg_ieee;
4457 ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee;
4458 ioc->mpi25 = 1;
4459 ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t);
4460
4461 /*
4462 * These function pointers for other requests that don't
4463 * the require IEEE scatter gather elements.
4464 *
4465 * For example Configuration Pages and SAS IOUNIT Control don't.
4466 */
4467 ioc->build_sg_mpi = &_base_build_sg;
4468 ioc->build_zero_len_sge_mpi = &_base_build_zero_len_sge;
4469
4470 r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
4471 if (r)
4472 goto out_free_resources;
4473
4474 ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
4475 sizeof(struct mpt3sas_port_facts), GFP_KERNEL);
4476 if (!ioc->pfacts) {
4477 r = -ENOMEM;
4478 goto out_free_resources;
4479 }
4480
4481 for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
4482 r = _base_get_port_facts(ioc, i, CAN_SLEEP);
4483 if (r)
4484 goto out_free_resources;
4485 }
4486
4487 r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
4488 if (r)
4489 goto out_free_resources;
4490
4491 init_waitqueue_head(&ioc->reset_wq);
4492
4493 /* allocate memory pd handle bitmask list */
4494 ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
4495 if (ioc->facts.MaxDevHandle % 8)
4496 ioc->pd_handles_sz++;
4497 ioc->pd_handles = kzalloc(ioc->pd_handles_sz,
4498 GFP_KERNEL);
4499 if (!ioc->pd_handles) {
4500 r = -ENOMEM;
4501 goto out_free_resources;
4502 }
4503 ioc->blocking_handles = kzalloc(ioc->pd_handles_sz,
4504 GFP_KERNEL);
4505 if (!ioc->blocking_handles) {
4506 r = -ENOMEM;
4507 goto out_free_resources;
4508 }
4509
4510 ioc->fwfault_debug = mpt3sas_fwfault_debug;
4511
4512 /* base internal command bits */
4513 mutex_init(&ioc->base_cmds.mutex);
4514 ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
4515 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
4516
4517 /* port_enable command bits */
4518 ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
4519 ioc->port_enable_cmds.status = MPT3_CMD_NOT_USED;
4520
4521 /* transport internal command bits */
4522 ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
4523 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
4524 mutex_init(&ioc->transport_cmds.mutex);
4525
4526 /* scsih internal command bits */
4527 ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
4528 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
4529 mutex_init(&ioc->scsih_cmds.mutex);
4530
4531 /* task management internal command bits */
4532 ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
4533 ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
4534 mutex_init(&ioc->tm_cmds.mutex);
4535
4536 /* config page internal command bits */
4537 ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
4538 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
4539 mutex_init(&ioc->config_cmds.mutex);
4540
4541 /* ctl module internal command bits */
4542 ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
4543 ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
4544 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
4545 mutex_init(&ioc->ctl_cmds.mutex);
4546
4547 if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
4548 !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
4549 !ioc->config_cmds.reply || !ioc->ctl_cmds.reply ||
4550 !ioc->ctl_cmds.sense) {
4551 r = -ENOMEM;
4552 goto out_free_resources;
4553 }
4554
4555 for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
4556 ioc->event_masks[i] = -1;
4557
4558 /* here we enable the events we care about */
4559 _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY);
4560 _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
4561 _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
4562 _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
4563 _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
4564 _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
4565 _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
4566 _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
4567 _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
4568 _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
4569
4570 r = _base_make_ioc_operational(ioc, CAN_SLEEP);
4571 if (r)
4572 goto out_free_resources;
4573
4574 return 0;
4575
4576 out_free_resources:
4577
4578 ioc->remove_host = 1;
4579
4580 mpt3sas_base_free_resources(ioc);
4581 _base_release_memory_pools(ioc);
4582 pci_set_drvdata(ioc->pdev, NULL);
4583 kfree(ioc->cpu_msix_table);
4584 kfree(ioc->pd_handles);
4585 kfree(ioc->blocking_handles);
4586 kfree(ioc->tm_cmds.reply);
4587 kfree(ioc->transport_cmds.reply);
4588 kfree(ioc->scsih_cmds.reply);
4589 kfree(ioc->config_cmds.reply);
4590 kfree(ioc->base_cmds.reply);
4591 kfree(ioc->port_enable_cmds.reply);
4592 kfree(ioc->ctl_cmds.reply);
4593 kfree(ioc->ctl_cmds.sense);
4594 kfree(ioc->pfacts);
4595 ioc->ctl_cmds.reply = NULL;
4596 ioc->base_cmds.reply = NULL;
4597 ioc->tm_cmds.reply = NULL;
4598 ioc->scsih_cmds.reply = NULL;
4599 ioc->transport_cmds.reply = NULL;
4600 ioc->config_cmds.reply = NULL;
4601 ioc->pfacts = NULL;
4602 return r;
4603}
4604
4605
4606/**
4607 * mpt3sas_base_detach - remove controller instance
4608 * @ioc: per adapter object
4609 *
4610 * Return nothing.
4611 */
4612void
4613mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc)
4614{
4615 dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
4616 __func__));
4617
4618 mpt3sas_base_stop_watchdog(ioc);
4619 mpt3sas_base_free_resources(ioc);
4620 _base_release_memory_pools(ioc);
4621 pci_set_drvdata(ioc->pdev, NULL);
4622 kfree(ioc->cpu_msix_table);
4623 kfree(ioc->pd_handles);
4624 kfree(ioc->blocking_handles);
4625 kfree(ioc->pfacts);
4626 kfree(ioc->ctl_cmds.reply);
4627 kfree(ioc->ctl_cmds.sense);
4628 kfree(ioc->base_cmds.reply);
4629 kfree(ioc->port_enable_cmds.reply);
4630 kfree(ioc->tm_cmds.reply);
4631 kfree(ioc->transport_cmds.reply);
4632 kfree(ioc->scsih_cmds.reply);
4633 kfree(ioc->config_cmds.reply);
4634}
4635
4636/**
4637 * _base_reset_handler - reset callback handler (for base)
4638 * @ioc: per adapter object
4639 * @reset_phase: phase
4640 *
4641 * The handler for doing any required cleanup or initialization.
4642 *
4643 * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
4644 * MPT3_IOC_DONE_RESET
4645 *
4646 * Return nothing.
4647 */
4648static void
4649_base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
4650{
4651 mpt3sas_scsih_reset_handler(ioc, reset_phase);
4652 mpt3sas_ctl_reset_handler(ioc, reset_phase);
4653 switch (reset_phase) {
4654 case MPT3_IOC_PRE_RESET:
4655 dtmprintk(ioc, pr_info(MPT3SAS_FMT
4656 "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
4657 break;
4658 case MPT3_IOC_AFTER_RESET:
4659 dtmprintk(ioc, pr_info(MPT3SAS_FMT
4660 "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
4661 if (ioc->transport_cmds.status & MPT3_CMD_PENDING) {
4662 ioc->transport_cmds.status |= MPT3_CMD_RESET;
4663 mpt3sas_base_free_smid(ioc, ioc->transport_cmds.smid);
4664 complete(&ioc->transport_cmds.done);
4665 }
4666 if (ioc->base_cmds.status & MPT3_CMD_PENDING) {
4667 ioc->base_cmds.status |= MPT3_CMD_RESET;
4668 mpt3sas_base_free_smid(ioc, ioc->base_cmds.smid);
4669 complete(&ioc->base_cmds.done);
4670 }
4671 if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) {
4672 ioc->port_enable_failed = 1;
4673 ioc->port_enable_cmds.status |= MPT3_CMD_RESET;
4674 mpt3sas_base_free_smid(ioc, ioc->port_enable_cmds.smid);
4675 if (ioc->is_driver_loading) {
4676 ioc->start_scan_failed =
4677 MPI2_IOCSTATUS_INTERNAL_ERROR;
4678 ioc->start_scan = 0;
4679 ioc->port_enable_cmds.status =
4680 MPT3_CMD_NOT_USED;
4681 } else
4682 complete(&ioc->port_enable_cmds.done);
4683 }
4684 if (ioc->config_cmds.status & MPT3_CMD_PENDING) {
4685 ioc->config_cmds.status |= MPT3_CMD_RESET;
4686 mpt3sas_base_free_smid(ioc, ioc->config_cmds.smid);
4687 ioc->config_cmds.smid = USHRT_MAX;
4688 complete(&ioc->config_cmds.done);
4689 }
4690 break;
4691 case MPT3_IOC_DONE_RESET:
4692 dtmprintk(ioc, pr_info(MPT3SAS_FMT
4693 "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
4694 break;
4695 }
4696}
4697
4698/**
4699 * _wait_for_commands_to_complete - reset controller
4700 * @ioc: Pointer to MPT_ADAPTER structure
4701 * @sleep_flag: CAN_SLEEP or NO_SLEEP
4702 *
4703 * This function waiting(3s) for all pending commands to complete
4704 * prior to putting controller in reset.
4705 */
4706static void
4707_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
4708{
4709 u32 ioc_state;
4710 unsigned long flags;
4711 u16 i;
4712
4713 ioc->pending_io_count = 0;
4714 if (sleep_flag != CAN_SLEEP)
4715 return;
4716
4717 ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
4718 if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
4719 return;
4720
4721 /* pending command count */
4722 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
4723 for (i = 0; i < ioc->scsiio_depth; i++)
4724 if (ioc->scsi_lookup[i].cb_idx != 0xFF)
4725 ioc->pending_io_count++;
4726 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
4727
4728 if (!ioc->pending_io_count)
4729 return;
4730
4731 /* wait for pending commands to complete */
4732 wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
4733}
4734
4735/**
4736 * mpt3sas_base_hard_reset_handler - reset controller
4737 * @ioc: Pointer to MPT_ADAPTER structure
4738 * @sleep_flag: CAN_SLEEP or NO_SLEEP
4739 * @type: FORCE_BIG_HAMMER or SOFT_RESET
4740 *
4741 * Returns 0 for success, non-zero for failure.
4742 */
4743int
4744mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
4745 enum reset_type type)
4746{
4747 int r;
4748 unsigned long flags;
4749 u32 ioc_state;
4750 u8 is_fault = 0, is_trigger = 0;
4751
4752 dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
4753 __func__));
4754
4755 if (ioc->pci_error_recovery) {
4756 pr_err(MPT3SAS_FMT "%s: pci error recovery reset\n",
4757 ioc->name, __func__);
4758 r = 0;
4759 goto out_unlocked;
4760 }
4761
4762 if (mpt3sas_fwfault_debug)
4763 mpt3sas_halt_firmware(ioc);
4764
4765 /* TODO - What we really should be doing is pulling
4766 * out all the code associated with NO_SLEEP; its never used.
4767 * That is legacy code from mpt fusion driver, ported over.
4768 * I will leave this BUG_ON here for now till its been resolved.
4769 */
4770 BUG_ON(sleep_flag == NO_SLEEP);
4771
4772 /* wait for an active reset in progress to complete */
4773 if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
4774 do {
4775 ssleep(1);
4776 } while (ioc->shost_recovery == 1);
4777 dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
4778 __func__));
4779 return ioc->ioc_reset_in_progress_status;
4780 }
4781
4782 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
4783 ioc->shost_recovery = 1;
4784 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
4785
4786 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
4787 MPT3_DIAG_BUFFER_IS_REGISTERED) &&
4788 (!(ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
4789 MPT3_DIAG_BUFFER_IS_RELEASED))) {
4790 is_trigger = 1;
4791 ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
4792 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
4793 is_fault = 1;
4794 }
4795 _base_reset_handler(ioc, MPT3_IOC_PRE_RESET);
4796 _wait_for_commands_to_complete(ioc, sleep_flag);
4797 _base_mask_interrupts(ioc);
4798 r = _base_make_ioc_ready(ioc, sleep_flag, type);
4799 if (r)
4800 goto out;
4801 _base_reset_handler(ioc, MPT3_IOC_AFTER_RESET);
4802
4803 /* If this hard reset is called while port enable is active, then
4804 * there is no reason to call make_ioc_operational
4805 */
4806 if (ioc->is_driver_loading && ioc->port_enable_failed) {
4807 ioc->remove_host = 1;
4808 r = -EFAULT;
4809 goto out;
4810 }
4811 r = _base_get_ioc_facts(ioc, CAN_SLEEP);
4812 if (r)
4813 goto out;
4814 r = _base_make_ioc_operational(ioc, sleep_flag);
4815 if (!r)
4816 _base_reset_handler(ioc, MPT3_IOC_DONE_RESET);
4817
4818 out:
4819 dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: %s\n",
4820 ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
4821
4822 spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
4823 ioc->ioc_reset_in_progress_status = r;
4824 ioc->shost_recovery = 0;
4825 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
4826 ioc->ioc_reset_count++;
4827 mutex_unlock(&ioc->reset_in_progress_mutex);
4828
4829 out_unlocked:
4830 if ((r == 0) && is_trigger) {
4831 if (is_fault)
4832 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_FW_FAULT);
4833 else
4834 mpt3sas_trigger_master(ioc,
4835 MASTER_TRIGGER_ADAPTER_RESET);
4836 }
4837 dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
4838 __func__));
4839 return r;
4840}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
new file mode 100644
index 000000000000..994656cbfac9
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -0,0 +1,1139 @@
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/mpt3sas/mpt3sas_base.h
6 * Copyright (C) 2012 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 MPT3SAS_BASE_H_INCLUDED
46#define MPT3SAS_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#include <scsi/scsi_eh.h>
65
66#include "mpt3sas_debug.h"
67#include "mpt3sas_trigger_diag.h"
68
69/* driver versioning info */
70#define MPT3SAS_DRIVER_NAME "mpt3sas"
71#define MPT3SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
72#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
73#define MPT3SAS_DRIVER_VERSION "01.100.01.00"
74#define MPT3SAS_MAJOR_VERSION 1
75#define MPT3SAS_MINOR_VERSION 100
76#define MPT3SAS_BUILD_VERSION 1
77#define MPT3SAS_RELEASE_VERSION 00
78
79/*
80 * Set MPT3SAS_SG_DEPTH value based on user input.
81 */
82#define MPT3SAS_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS
83#define MPT3SAS_MIN_PHYS_SEGMENTS 16
84#ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE
85#define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE
86#else
87#define MPT3SAS_SG_DEPTH MPT3SAS_MAX_PHYS_SEGMENTS
88#endif
89
90
91/*
92 * Generic Defines
93 */
94#define MPT3SAS_SATA_QUEUE_DEPTH 32
95#define MPT3SAS_SAS_QUEUE_DEPTH 254
96#define MPT3SAS_RAID_QUEUE_DEPTH 128
97
98#define MPT_NAME_LENGTH 32 /* generic length of strings */
99#define MPT_STRING_LENGTH 64
100
101#define MPT_MAX_CALLBACKS 32
102
103
104#define CAN_SLEEP 1
105#define NO_SLEEP 0
106
107#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */
108
109#define MPI3_HIM_MASK 0xFFFFFFFF /* mask every bit*/
110
111#define MPT3SAS_INVALID_DEVICE_HANDLE 0xFFFF
112
113/*
114 * reset phases
115 */
116#define MPT3_IOC_PRE_RESET 1 /* prior to host reset */
117#define MPT3_IOC_AFTER_RESET 2 /* just after host reset */
118#define MPT3_IOC_DONE_RESET 3 /* links re-initialized */
119
120/*
121 * logging format
122 */
123#define MPT3SAS_FMT "%s: "
124
125/*
126 * per target private data
127 */
128#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01
129#define MPT_TARGET_FLAGS_VOLUME 0x02
130#define MPT_TARGET_FLAGS_DELETED 0x04
131#define MPT_TARGET_FASTPATH_IO 0x08
132
133
134
135/*
136 * status bits for ioc->diag_buffer_status
137 */
138#define MPT3_DIAG_BUFFER_IS_REGISTERED (0x01)
139#define MPT3_DIAG_BUFFER_IS_RELEASED (0x02)
140#define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04)
141
142
143/* OEM Identifiers */
144#define MFG10_OEM_ID_INVALID (0x00000000)
145#define MFG10_OEM_ID_DELL (0x00000001)
146#define MFG10_OEM_ID_FSC (0x00000002)
147#define MFG10_OEM_ID_SUN (0x00000003)
148#define MFG10_OEM_ID_IBM (0x00000004)
149
150/* GENERIC Flags 0*/
151#define MFG10_GF0_OCE_DISABLED (0x00000001)
152#define MFG10_GF0_R1E_DRIVE_COUNT (0x00000002)
153#define MFG10_GF0_R10_DISPLAY (0x00000004)
154#define MFG10_GF0_SSD_DATA_SCRUB_DISABLE (0x00000008)
155#define MFG10_GF0_SINGLE_DRIVE_R0 (0x00000010)
156
157/* OEM Specific Flags will come from OEM specific header files */
158struct Mpi2ManufacturingPage10_t {
159 MPI2_CONFIG_PAGE_HEADER Header; /* 00h */
160 U8 OEMIdentifier; /* 04h */
161 U8 Reserved1; /* 05h */
162 U16 Reserved2; /* 08h */
163 U32 Reserved3; /* 0Ch */
164 U32 GenericFlags0; /* 10h */
165 U32 GenericFlags1; /* 14h */
166 U32 Reserved4; /* 18h */
167 U32 OEMSpecificFlags0; /* 1Ch */
168 U32 OEMSpecificFlags1; /* 20h */
169 U32 Reserved5[18]; /* 24h - 60h*/
170};
171
172
173/* Miscellaneous options */
174struct Mpi2ManufacturingPage11_t {
175 MPI2_CONFIG_PAGE_HEADER Header; /* 00h */
176 __le32 Reserved1; /* 04h */
177 u8 Reserved2; /* 08h */
178 u8 EEDPTagMode; /* 09h */
179 u8 Reserved3; /* 0Ah */
180 u8 Reserved4; /* 0Bh */
181 __le32 Reserved5[23]; /* 0Ch-60h*/
182};
183
184/**
185 * struct MPT3SAS_TARGET - starget private hostdata
186 * @starget: starget object
187 * @sas_address: target sas address
188 * @handle: device handle
189 * @num_luns: number luns
190 * @flags: MPT_TARGET_FLAGS_XXX flags
191 * @deleted: target flaged for deletion
192 * @tm_busy: target is busy with TM request.
193 */
194struct MPT3SAS_TARGET {
195 struct scsi_target *starget;
196 u64 sas_address;
197 u16 handle;
198 int num_luns;
199 u32 flags;
200 u8 deleted;
201 u8 tm_busy;
202};
203
204
205/*
206 * per device private data
207 */
208#define MPT_DEVICE_FLAGS_INIT 0x01
209#define MPT_DEVICE_TLR_ON 0x02
210
211/**
212 * struct MPT3SAS_DEVICE - sdev private hostdata
213 * @sas_target: starget private hostdata
214 * @lun: lun number
215 * @flags: MPT_DEVICE_XXX flags
216 * @configured_lun: lun is configured
217 * @block: device is in SDEV_BLOCK state
218 * @tlr_snoop_check: flag used in determining whether to disable TLR
219 * @eedp_enable: eedp support enable bit
220 * @eedp_type: 0(type_1), 1(type_2), 2(type_3)
221 * @eedp_block_length: block size
222 */
223struct MPT3SAS_DEVICE {
224 struct MPT3SAS_TARGET *sas_target;
225 unsigned int lun;
226 u32 flags;
227 u8 configured_lun;
228 u8 block;
229 u8 tlr_snoop_check;
230};
231
232#define MPT3_CMD_NOT_USED 0x8000 /* free */
233#define MPT3_CMD_COMPLETE 0x0001 /* completed */
234#define MPT3_CMD_PENDING 0x0002 /* pending */
235#define MPT3_CMD_REPLY_VALID 0x0004 /* reply is valid */
236#define MPT3_CMD_RESET 0x0008 /* host reset dropped the command */
237
238/**
239 * struct _internal_cmd - internal commands struct
240 * @mutex: mutex
241 * @done: completion
242 * @reply: reply message pointer
243 * @sense: sense data
244 * @status: MPT3_CMD_XXX status
245 * @smid: system message id
246 */
247struct _internal_cmd {
248 struct mutex mutex;
249 struct completion done;
250 void *reply;
251 void *sense;
252 u16 status;
253 u16 smid;
254};
255
256
257
258/**
259 * struct _sas_device - attached device information
260 * @list: sas device list
261 * @starget: starget object
262 * @sas_address: device sas address
263 * @device_name: retrieved from the SAS IDENTIFY frame.
264 * @handle: device handle
265 * @sas_address_parent: sas address of parent expander or sas host
266 * @enclosure_handle: enclosure handle
267 * @enclosure_logical_id: enclosure logical identifier
268 * @volume_handle: volume handle (valid when hidden raid member)
269 * @volume_wwid: volume unique identifier
270 * @device_info: bitfield provides detailed info about the device
271 * @id: target id
272 * @channel: target channel
273 * @slot: number number
274 * @phy: phy identifier provided in sas device page 0
275 * @fast_path: fast path feature enable bit
276 * @responding: used in _scsih_sas_device_mark_responding
277 */
278struct _sas_device {
279 struct list_head list;
280 struct scsi_target *starget;
281 u64 sas_address;
282 u64 device_name;
283 u16 handle;
284 u64 sas_address_parent;
285 u16 enclosure_handle;
286 u64 enclosure_logical_id;
287 u16 volume_handle;
288 u64 volume_wwid;
289 u32 device_info;
290 int id;
291 int channel;
292 u16 slot;
293 u8 phy;
294 u8 responding;
295 u8 fast_path;
296};
297
298/**
299 * struct _raid_device - raid volume link list
300 * @list: sas device list
301 * @starget: starget object
302 * @sdev: scsi device struct (volumes are single lun)
303 * @wwid: unique identifier for the volume
304 * @handle: device handle
305 * @id: target id
306 * @channel: target channel
307 * @volume_type: the raid level
308 * @device_info: bitfield provides detailed info about the hidden components
309 * @num_pds: number of hidden raid components
310 * @responding: used in _scsih_raid_device_mark_responding
311 * @percent_complete: resync percent complete
312 */
313#define MPT_MAX_WARPDRIVE_PDS 8
314struct _raid_device {
315 struct list_head list;
316 struct scsi_target *starget;
317 struct scsi_device *sdev;
318 u64 wwid;
319 u16 handle;
320 int id;
321 int channel;
322 u8 volume_type;
323 u8 num_pds;
324 u8 responding;
325 u8 percent_complete;
326 u32 device_info;
327};
328
329/**
330 * struct _boot_device - boot device info
331 * @is_raid: flag to indicate whether this is volume
332 * @device: holds pointer for either struct _sas_device or
333 * struct _raid_device
334 */
335struct _boot_device {
336 u8 is_raid;
337 void *device;
338};
339
340/**
341 * struct _sas_port - wide/narrow sas port information
342 * @port_list: list of ports belonging to expander
343 * @num_phys: number of phys belonging to this port
344 * @remote_identify: attached device identification
345 * @rphy: sas transport rphy object
346 * @port: sas transport wide/narrow port object
347 * @phy_list: _sas_phy list objects belonging to this port
348 */
349struct _sas_port {
350 struct list_head port_list;
351 u8 num_phys;
352 struct sas_identify remote_identify;
353 struct sas_rphy *rphy;
354 struct sas_port *port;
355 struct list_head phy_list;
356};
357
358/**
359 * struct _sas_phy - phy information
360 * @port_siblings: list of phys belonging to a port
361 * @identify: phy identification
362 * @remote_identify: attached device identification
363 * @phy: sas transport phy object
364 * @phy_id: unique phy id
365 * @handle: device handle for this phy
366 * @attached_handle: device handle for attached device
367 * @phy_belongs_to_port: port has been created for this phy
368 */
369struct _sas_phy {
370 struct list_head port_siblings;
371 struct sas_identify identify;
372 struct sas_identify remote_identify;
373 struct sas_phy *phy;
374 u8 phy_id;
375 u16 handle;
376 u16 attached_handle;
377 u8 phy_belongs_to_port;
378};
379
380/**
381 * struct _sas_node - sas_host/expander information
382 * @list: list of expanders
383 * @parent_dev: parent device class
384 * @num_phys: number phys belonging to this sas_host/expander
385 * @sas_address: sas address of this sas_host/expander
386 * @handle: handle for this sas_host/expander
387 * @sas_address_parent: sas address of parent expander or sas host
388 * @enclosure_handle: handle for this a member of an enclosure
389 * @device_info: bitwise defining capabilities of this sas_host/expander
390 * @responding: used in _scsih_expander_device_mark_responding
391 * @phy: a list of phys that make up this sas_host/expander
392 * @sas_port_list: list of ports attached to this sas_host/expander
393 */
394struct _sas_node {
395 struct list_head list;
396 struct device *parent_dev;
397 u8 num_phys;
398 u64 sas_address;
399 u16 handle;
400 u64 sas_address_parent;
401 u16 enclosure_handle;
402 u64 enclosure_logical_id;
403 u8 responding;
404 struct _sas_phy *phy;
405 struct list_head sas_port_list;
406};
407
408/**
409 * enum reset_type - reset state
410 * @FORCE_BIG_HAMMER: issue diagnostic reset
411 * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer
412 */
413enum reset_type {
414 FORCE_BIG_HAMMER,
415 SOFT_RESET,
416};
417
418/**
419 * struct chain_tracker - firmware chain tracker
420 * @chain_buffer: chain buffer
421 * @chain_buffer_dma: physical address
422 * @tracker_list: list of free request (ioc->free_chain_list)
423 */
424struct chain_tracker {
425 void *chain_buffer;
426 dma_addr_t chain_buffer_dma;
427 struct list_head tracker_list;
428};
429
430/**
431 * struct scsiio_tracker - scsi mf request tracker
432 * @smid: system message id
433 * @scmd: scsi request pointer
434 * @cb_idx: callback index
435 * @tracker_list: list of free request (ioc->free_list)
436 */
437struct scsiio_tracker {
438 u16 smid;
439 struct scsi_cmnd *scmd;
440 u8 cb_idx;
441 struct list_head chain_list;
442 struct list_head tracker_list;
443};
444
445/**
446 * struct request_tracker - firmware request tracker
447 * @smid: system message id
448 * @cb_idx: callback index
449 * @tracker_list: list of free request (ioc->free_list)
450 */
451struct request_tracker {
452 u16 smid;
453 u8 cb_idx;
454 struct list_head tracker_list;
455};
456
457/**
458 * struct _tr_list - target reset list
459 * @handle: device handle
460 * @state: state machine
461 */
462struct _tr_list {
463 struct list_head list;
464 u16 handle;
465 u16 state;
466};
467
468
469/**
470 * struct adapter_reply_queue - the reply queue struct
471 * @ioc: per adapter object
472 * @msix_index: msix index into vector table
473 * @vector: irq vector
474 * @reply_post_host_index: head index in the pool where FW completes IO
475 * @reply_post_free: reply post base virt address
476 * @name: the name registered to request_irq()
477 * @busy: isr is actively processing replies on another cpu
478 * @list: this list
479*/
480struct adapter_reply_queue {
481 struct MPT3SAS_ADAPTER *ioc;
482 u8 msix_index;
483 unsigned int vector;
484 u32 reply_post_host_index;
485 Mpi2ReplyDescriptorsUnion_t *reply_post_free;
486 char name[MPT_NAME_LENGTH];
487 atomic_t busy;
488 struct list_head list;
489};
490
491typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
492
493/* SAS3.0 support */
494typedef int (*MPT_BUILD_SG_SCMD)(struct MPT3SAS_ADAPTER *ioc,
495 struct scsi_cmnd *scmd, u16 smid);
496typedef void (*MPT_BUILD_SG)(struct MPT3SAS_ADAPTER *ioc, void *psge,
497 dma_addr_t data_out_dma, size_t data_out_sz,
498 dma_addr_t data_in_dma, size_t data_in_sz);
499typedef void (*MPT_BUILD_ZERO_LEN_SGE)(struct MPT3SAS_ADAPTER *ioc,
500 void *paddr);
501
502
503
504/* IOC Facts and Port Facts converted from little endian to cpu */
505union mpi3_version_union {
506 MPI2_VERSION_STRUCT Struct;
507 u32 Word;
508};
509
510struct mpt3sas_facts {
511 u16 MsgVersion;
512 u16 HeaderVersion;
513 u8 IOCNumber;
514 u8 VP_ID;
515 u8 VF_ID;
516 u16 IOCExceptions;
517 u16 IOCStatus;
518 u32 IOCLogInfo;
519 u8 MaxChainDepth;
520 u8 WhoInit;
521 u8 NumberOfPorts;
522 u8 MaxMSIxVectors;
523 u16 RequestCredit;
524 u16 ProductID;
525 u32 IOCCapabilities;
526 union mpi3_version_union FWVersion;
527 u16 IOCRequestFrameSize;
528 u16 Reserved3;
529 u16 MaxInitiators;
530 u16 MaxTargets;
531 u16 MaxSasExpanders;
532 u16 MaxEnclosures;
533 u16 ProtocolFlags;
534 u16 HighPriorityCredit;
535 u16 MaxReplyDescriptorPostQueueDepth;
536 u8 ReplyFrameSize;
537 u8 MaxVolumes;
538 u16 MaxDevHandle;
539 u16 MaxPersistentEntries;
540 u16 MinDevHandle;
541};
542
543struct mpt3sas_port_facts {
544 u8 PortNumber;
545 u8 VP_ID;
546 u8 VF_ID;
547 u8 PortType;
548 u16 MaxPostedCmdBuffers;
549};
550
551/**
552 * enum mutex_type - task management mutex type
553 * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
554 * @TM_MUTEX_ON: mutex is required
555 */
556enum mutex_type {
557 TM_MUTEX_OFF = 0,
558 TM_MUTEX_ON = 1,
559};
560
561typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
562/**
563 * struct MPT3SAS_ADAPTER - per adapter struct
564 * @list: ioc_list
565 * @shost: shost object
566 * @id: unique adapter id
567 * @cpu_count: number online cpus
568 * @name: generic ioc string
569 * @tmp_string: tmp string used for logging
570 * @pdev: pci pdev object
571 * @pio_chip: physical io register space
572 * @chip: memory mapped register space
573 * @chip_phys: physical addrss prior to mapping
574 * @logging_level: see mpt3sas_debug.h
575 * @fwfault_debug: debuging FW timeouts
576 * @ir_firmware: IR firmware present
577 * @bars: bitmask of BAR's that must be configured
578 * @mask_interrupts: ignore interrupt
579 * @fault_reset_work_q_name: fw fault work queue
580 * @fault_reset_work_q: ""
581 * @fault_reset_work: ""
582 * @firmware_event_name: fw event work queue
583 * @firmware_event_thread: ""
584 * @fw_event_lock:
585 * @fw_event_list: list of fw events
586 * @aen_event_read_flag: event log was read
587 * @broadcast_aen_busy: broadcast aen waiting to be serviced
588 * @shost_recovery: host reset in progress
589 * @ioc_reset_in_progress_lock:
590 * @ioc_link_reset_in_progress: phy/hard reset in progress
591 * @ignore_loginfos: ignore loginfos during task management
592 * @remove_host: flag for when driver unloads, to avoid sending dev resets
593 * @pci_error_recovery: flag to prevent ioc access until slot reset completes
594 * @wait_for_discovery_to_complete: flag set at driver load time when
595 * waiting on reporting devices
596 * @is_driver_loading: flag set at driver load time
597 * @port_enable_failed: flag set when port enable has failed
598 * @start_scan: flag set from scan_start callback, cleared from _mpt3sas_fw_work
599 * @start_scan_failed: means port enable failed, return's the ioc_status
600 * @msix_enable: flag indicating msix is enabled
601 * @msix_vector_count: number msix vectors
602 * @cpu_msix_table: table for mapping cpus to msix index
603 * @cpu_msix_table_sz: table size
604 * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
605 * @scsi_io_cb_idx: shost generated commands
606 * @tm_cb_idx: task management commands
607 * @scsih_cb_idx: scsih internal commands
608 * @transport_cb_idx: transport internal commands
609 * @ctl_cb_idx: clt internal commands
610 * @base_cb_idx: base internal commands
611 * @config_cb_idx: base internal commands
612 * @tm_tr_cb_idx : device removal target reset handshake
613 * @tm_tr_volume_cb_idx : volume removal target reset
614 * @base_cmds:
615 * @transport_cmds:
616 * @scsih_cmds:
617 * @tm_cmds:
618 * @ctl_cmds:
619 * @config_cmds:
620 * @base_add_sg_single: handler for either 32/64 bit sgl's
621 * @event_type: bits indicating which events to log
622 * @event_context: unique id for each logged event
623 * @event_log: event log pointer
624 * @event_masks: events that are masked
625 * @facts: static facts data
626 * @pfacts: static port facts data
627 * @manu_pg0: static manufacturing page 0
628 * @manu_pg10: static manufacturing page 10
629 * @manu_pg11: static manufacturing page 11
630 * @bios_pg2: static bios page 2
631 * @bios_pg3: static bios page 3
632 * @ioc_pg8: static ioc page 8
633 * @iounit_pg0: static iounit page 0
634 * @iounit_pg1: static iounit page 1
635 * @sas_hba: sas host object
636 * @sas_expander_list: expander object list
637 * @sas_node_lock:
638 * @sas_device_list: sas device object list
639 * @sas_device_init_list: sas device object list (used only at init time)
640 * @sas_device_lock:
641 * @io_missing_delay: time for IO completed by fw when PDR enabled
642 * @device_missing_delay: time for device missing by fw when PDR enabled
643 * @sas_id : used for setting volume target IDs
644 * @blocking_handles: bitmask used to identify which devices need blocking
645 * @pd_handles : bitmask for PD handles
646 * @pd_handles_sz : size of pd_handle bitmask
647 * @config_page_sz: config page size
648 * @config_page: reserve memory for config page payload
649 * @config_page_dma:
650 * @hba_queue_depth: hba request queue depth
651 * @sge_size: sg element size for either 32/64 bit
652 * @scsiio_depth: SCSI_IO queue depth
653 * @request_sz: per request frame size
654 * @request: pool of request frames
655 * @request_dma:
656 * @request_dma_sz:
657 * @scsi_lookup: firmware request tracker list
658 * @scsi_lookup_lock:
659 * @free_list: free list of request
660 * @pending_io_count:
661 * @reset_wq:
662 * @chain: pool of chains
663 * @chain_dma:
664 * @max_sges_in_main_message: number sg elements in main message
665 * @max_sges_in_chain_message: number sg elements per chain
666 * @chains_needed_per_io: max chains per io
667 * @chain_depth: total chains allocated
668 * @hi_priority_smid:
669 * @hi_priority:
670 * @hi_priority_dma:
671 * @hi_priority_depth:
672 * @hpr_lookup:
673 * @hpr_free_list:
674 * @internal_smid:
675 * @internal:
676 * @internal_dma:
677 * @internal_depth:
678 * @internal_lookup:
679 * @internal_free_list:
680 * @sense: pool of sense
681 * @sense_dma:
682 * @sense_dma_pool:
683 * @reply_depth: hba reply queue depth:
684 * @reply_sz: per reply frame size:
685 * @reply: pool of replys:
686 * @reply_dma:
687 * @reply_dma_pool:
688 * @reply_free_queue_depth: reply free depth
689 * @reply_free: pool for reply free queue (32 bit addr)
690 * @reply_free_dma:
691 * @reply_free_dma_pool:
692 * @reply_free_host_index: tail index in pool to insert free replys
693 * @reply_post_queue_depth: reply post queue depth
694 * @reply_post_free: pool for reply post (64bit descriptor)
695 * @reply_post_free_dma:
696 * @reply_queue_count: number of reply queue's
697 * @reply_queue_list: link list contaning the reply queue info
698 * @reply_post_host_index: head index in the pool where FW completes IO
699 * @delayed_tr_list: target reset link list
700 * @delayed_tr_volume_list: volume target reset link list
701 */
702struct MPT3SAS_ADAPTER {
703 struct list_head list;
704 struct Scsi_Host *shost;
705 u8 id;
706 int cpu_count;
707 char name[MPT_NAME_LENGTH];
708 char tmp_string[MPT_STRING_LENGTH];
709 struct pci_dev *pdev;
710 Mpi2SystemInterfaceRegs_t __iomem *chip;
711 resource_size_t chip_phys;
712 int logging_level;
713 int fwfault_debug;
714 u8 ir_firmware;
715 int bars;
716 u8 mask_interrupts;
717
718 /* fw fault handler */
719 char fault_reset_work_q_name[20];
720 struct workqueue_struct *fault_reset_work_q;
721 struct delayed_work fault_reset_work;
722
723 /* fw event handler */
724 char firmware_event_name[20];
725 struct workqueue_struct *firmware_event_thread;
726 spinlock_t fw_event_lock;
727 struct list_head fw_event_list;
728
729 /* misc flags */
730 int aen_event_read_flag;
731 u8 broadcast_aen_busy;
732 u16 broadcast_aen_pending;
733 u8 shost_recovery;
734
735 struct mutex reset_in_progress_mutex;
736 spinlock_t ioc_reset_in_progress_lock;
737 u8 ioc_link_reset_in_progress;
738 u8 ioc_reset_in_progress_status;
739
740 u8 ignore_loginfos;
741 u8 remove_host;
742 u8 pci_error_recovery;
743 u8 wait_for_discovery_to_complete;
744 u8 is_driver_loading;
745 u8 port_enable_failed;
746 u8 start_scan;
747 u16 start_scan_failed;
748
749 u8 msix_enable;
750 u16 msix_vector_count;
751 u8 *cpu_msix_table;
752 u16 cpu_msix_table_sz;
753 u32 ioc_reset_count;
754 MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
755
756 /* internal commands, callback index */
757 u8 scsi_io_cb_idx;
758 u8 tm_cb_idx;
759 u8 transport_cb_idx;
760 u8 scsih_cb_idx;
761 u8 ctl_cb_idx;
762 u8 base_cb_idx;
763 u8 port_enable_cb_idx;
764 u8 config_cb_idx;
765 u8 tm_tr_cb_idx;
766 u8 tm_tr_volume_cb_idx;
767 u8 tm_sas_control_cb_idx;
768 struct _internal_cmd base_cmds;
769 struct _internal_cmd port_enable_cmds;
770 struct _internal_cmd transport_cmds;
771 struct _internal_cmd scsih_cmds;
772 struct _internal_cmd tm_cmds;
773 struct _internal_cmd ctl_cmds;
774 struct _internal_cmd config_cmds;
775
776 MPT_ADD_SGE base_add_sg_single;
777
778 /* function ptr for either IEEE or MPI sg elements */
779 MPT_BUILD_SG_SCMD build_sg_scmd;
780 MPT_BUILD_SG build_sg;
781 MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge;
782 u8 mpi25;
783 u16 sge_size_ieee;
784
785 /* function ptr for MPI sg elements only */
786 MPT_BUILD_SG build_sg_mpi;
787 MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge_mpi;
788
789 /* event log */
790 u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
791 u32 event_context;
792 void *event_log;
793 u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
794
795 /* static config pages */
796 struct mpt3sas_facts facts;
797 struct mpt3sas_port_facts *pfacts;
798 Mpi2ManufacturingPage0_t manu_pg0;
799 struct Mpi2ManufacturingPage10_t manu_pg10;
800 struct Mpi2ManufacturingPage11_t manu_pg11;
801 Mpi2BiosPage2_t bios_pg2;
802 Mpi2BiosPage3_t bios_pg3;
803 Mpi2IOCPage8_t ioc_pg8;
804 Mpi2IOUnitPage0_t iounit_pg0;
805 Mpi2IOUnitPage1_t iounit_pg1;
806
807 struct _boot_device req_boot_device;
808 struct _boot_device req_alt_boot_device;
809 struct _boot_device current_boot_device;
810
811 /* sas hba, expander, and device list */
812 struct _sas_node sas_hba;
813 struct list_head sas_expander_list;
814 spinlock_t sas_node_lock;
815 struct list_head sas_device_list;
816 struct list_head sas_device_init_list;
817 spinlock_t sas_device_lock;
818 struct list_head raid_device_list;
819 spinlock_t raid_device_lock;
820 u8 io_missing_delay;
821 u16 device_missing_delay;
822 int sas_id;
823
824 void *blocking_handles;
825 void *pd_handles;
826 u16 pd_handles_sz;
827
828 /* config page */
829 u16 config_page_sz;
830 void *config_page;
831 dma_addr_t config_page_dma;
832
833 /* scsiio request */
834 u16 hba_queue_depth;
835 u16 sge_size;
836 u16 scsiio_depth;
837 u16 request_sz;
838 u8 *request;
839 dma_addr_t request_dma;
840 u32 request_dma_sz;
841 struct scsiio_tracker *scsi_lookup;
842 ulong scsi_lookup_pages;
843 spinlock_t scsi_lookup_lock;
844 struct list_head free_list;
845 int pending_io_count;
846 wait_queue_head_t reset_wq;
847
848 /* chain */
849 struct chain_tracker *chain_lookup;
850 struct list_head free_chain_list;
851 struct dma_pool *chain_dma_pool;
852 ulong chain_pages;
853 u16 max_sges_in_main_message;
854 u16 max_sges_in_chain_message;
855 u16 chains_needed_per_io;
856 u32 chain_depth;
857
858 /* hi-priority queue */
859 u16 hi_priority_smid;
860 u8 *hi_priority;
861 dma_addr_t hi_priority_dma;
862 u16 hi_priority_depth;
863 struct request_tracker *hpr_lookup;
864 struct list_head hpr_free_list;
865
866 /* internal queue */
867 u16 internal_smid;
868 u8 *internal;
869 dma_addr_t internal_dma;
870 u16 internal_depth;
871 struct request_tracker *internal_lookup;
872 struct list_head internal_free_list;
873
874 /* sense */
875 u8 *sense;
876 dma_addr_t sense_dma;
877 struct dma_pool *sense_dma_pool;
878
879 /* reply */
880 u16 reply_sz;
881 u8 *reply;
882 dma_addr_t reply_dma;
883 u32 reply_dma_max_address;
884 u32 reply_dma_min_address;
885 struct dma_pool *reply_dma_pool;
886
887 /* reply free queue */
888 u16 reply_free_queue_depth;
889 __le32 *reply_free;
890 dma_addr_t reply_free_dma;
891 struct dma_pool *reply_free_dma_pool;
892 u32 reply_free_host_index;
893
894 /* reply post queue */
895 u16 reply_post_queue_depth;
896 Mpi2ReplyDescriptorsUnion_t *reply_post_free;
897 dma_addr_t reply_post_free_dma;
898 struct dma_pool *reply_post_free_dma_pool;
899 u8 reply_queue_count;
900 struct list_head reply_queue_list;
901
902 struct list_head delayed_tr_list;
903 struct list_head delayed_tr_volume_list;
904
905 /* diag buffer support */
906 u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
907 u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT];
908 dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT];
909 u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT];
910 u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT];
911 u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
912 u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
913 u32 ring_buffer_offset;
914 u32 ring_buffer_sz;
915 spinlock_t diag_trigger_lock;
916 u8 diag_trigger_active;
917 struct SL_WH_MASTER_TRIGGER_T diag_trigger_master;
918 struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event;
919 struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi;
920 struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi;
921};
922
923typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
924 u32 reply);
925
926
927/* base shared API */
928extern struct list_head mpt3sas_ioc_list;
929void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc);
930void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc);
931
932int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc);
933void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc);
934int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc);
935void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc);
936int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
937 enum reset_type type);
938
939void *mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid);
940void *mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid);
941__le32 mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc,
942 u16 smid);
943void mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc);
944
945/* hi-priority queue */
946u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
947u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
948 struct scsi_cmnd *scmd);
949
950u16 mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
951void mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid);
952void mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid,
953 u16 handle);
954void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
955 u16 handle);
956void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid);
957void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid);
958void mpt3sas_base_initialize_callback_handler(void);
959u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func);
960void mpt3sas_base_release_callback_handler(u8 cb_idx);
961
962u8 mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
963 u32 reply);
964u8 mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid,
965 u8 msix_index, u32 reply);
966void *mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc,
967 u32 phys_addr);
968
969u32 mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked);
970
971void mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code);
972int mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
973 Mpi2SasIoUnitControlReply_t *mpi_reply,
974 Mpi2SasIoUnitControlRequest_t *mpi_request);
975int mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc,
976 Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request);
977
978void mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc,
979 u32 *event_type);
980
981void mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc);
982
983void mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc,
984 u16 device_missing_delay, u8 io_missing_delay);
985
986int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc);
987
988
989/* scsih shared API */
990u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
991 u32 reply);
992void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
993
994int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
995 uint channel, uint id, uint lun, u8 type, u16 smid_task,
996 ulong timeout, unsigned long serial_number, enum mutex_type m_type);
997void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
998void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
999void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
1000void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
1001 u64 sas_address);
1002
1003struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
1004 struct MPT3SAS_ADAPTER *ioc, u16 handle);
1005struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address(
1006 struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
1007struct _sas_device *mpt3sas_scsih_sas_device_find_by_sas_address(
1008 struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
1009
1010void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
1011
1012/* config shared API */
1013u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
1014 u32 reply);
1015int mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc,
1016 u8 *num_phys);
1017int mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
1018 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
1019int mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
1020 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
1021 u16 sz);
1022int mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
1023 Mpi2ConfigReply_t *mpi_reply,
1024 struct Mpi2ManufacturingPage10_t *config_page);
1025
1026int mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
1027 Mpi2ConfigReply_t *mpi_reply,
1028 struct Mpi2ManufacturingPage11_t *config_page);
1029int mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
1030 Mpi2ConfigReply_t *mpi_reply,
1031 struct Mpi2ManufacturingPage11_t *config_page);
1032
1033int mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1034 *mpi_reply, Mpi2BiosPage2_t *config_page);
1035int mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1036 *mpi_reply, Mpi2BiosPage3_t *config_page);
1037int mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1038 *mpi_reply, Mpi2IOUnitPage0_t *config_page);
1039int mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
1040 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
1041 u32 form, u32 handle);
1042int mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
1043 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
1044 u32 form, u32 handle);
1045int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1046 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1047 u16 sz);
1048int mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1049 *mpi_reply, Mpi2IOUnitPage1_t *config_page);
1050int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1051 *mpi_reply, Mpi2IOUnitPage1_t *config_page);
1052int mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1053 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1054 u16 sz);
1055int mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1056 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1057 u16 sz);
1058int mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1059 *mpi_reply, Mpi2IOCPage8_t *config_page);
1060int mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc,
1061 Mpi2ConfigReply_t *mpi_reply, Mpi2ExpanderPage0_t *config_page,
1062 u32 form, u32 handle);
1063int mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc,
1064 Mpi2ConfigReply_t *mpi_reply, Mpi2ExpanderPage1_t *config_page,
1065 u32 phy_number, u16 handle);
1066int mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc,
1067 Mpi2ConfigReply_t *mpi_reply, Mpi2SasEnclosurePage0_t *config_page,
1068 u32 form, u32 handle);
1069int mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1070 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number);
1071int mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1072 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number);
1073int mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1074 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1075 u32 handle);
1076int mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1077 u8 *num_pds);
1078int mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1079 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1080 u32 handle, u16 sz);
1081int mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc,
1082 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page,
1083 u32 form, u32 form_specific);
1084int mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1085 u16 *volume_handle);
1086int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc,
1087 u16 volume_handle, u64 *wwid);
1088
1089/* ctl shared API */
1090extern struct device_attribute *mpt3sas_host_attrs[];
1091extern struct device_attribute *mpt3sas_dev_attrs[];
1092void mpt3sas_ctl_init(void);
1093void mpt3sas_ctl_exit(void);
1094u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
1095 u32 reply);
1096void mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
1097u8 mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc,
1098 u8 msix_index, u32 reply);
1099void mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc,
1100 Mpi2EventNotificationReply_t *mpi_reply);
1101
1102void mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc,
1103 u8 bits_to_regsiter);
1104int mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
1105 u8 *issue_reset);
1106
1107/* transport shared API */
1108u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
1109 u32 reply);
1110struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc,
1111 u16 handle, u64 sas_address);
1112void mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
1113 u64 sas_address_parent);
1114int mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
1115 *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);
1116int mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc,
1117 struct _sas_phy *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
1118 struct device *parent_dev);
1119void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
1120 u64 sas_address, u16 handle, u8 phy_number, u8 link_rate);
1121extern struct sas_function_template mpt3sas_transport_functions;
1122extern struct scsi_transport_template *mpt3sas_transport_template;
1123extern int scsi_internal_device_block(struct scsi_device *sdev);
1124extern int scsi_internal_device_unblock(struct scsi_device *sdev,
1125 enum scsi_device_state new_state);
1126/* trigger data externs */
1127void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
1128 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data);
1129void mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
1130 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data);
1131void mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc,
1132 u32 tigger_bitmask);
1133void mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event,
1134 u16 log_entry_qualifier);
1135void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key,
1136 u8 asc, u8 ascq);
1137void mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status,
1138 u32 loginfo);
1139#endif /* MPT3SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
new file mode 100644
index 000000000000..ce7e59b2fc08
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -0,0 +1,1650 @@
1/*
2 * This module provides common API for accessing firmware configuration pages
3 *
4 * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c
5 * Copyright (C) 2012 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 "mpt3sas_base.h"
56
57/* local definitions */
58
59/* Timeout for config page request (in seconds) */
60#define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15
61
62/* Common sgl flags for READING a config page. */
63#define MPT3_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 MPT3_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 * @sz: size
76 * @page: virt pointer
77 * @page_dma: phys pointer
78 *
79 */
80struct config_request {
81 u16 sz;
82 void *page;
83 dma_addr_t page_dma;
84};
85
86#ifdef CONFIG_SCSI_MPT3SAS_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 helpful when debugging issues
96 * in this module.
97 */
98static void
99_config_display_some_debug(struct MPT3SAS_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 = mpt3sas_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 pr_info(MPT3SAS_FMT
162 "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n",
163 ioc->name, calling_function_name, desc,
164 mpi_request->Header.PageNumber, mpi_request->Action,
165 le32_to_cpu(mpi_request->PageAddress), smid);
166
167 if (!mpi_reply)
168 return;
169
170 if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
171 pr_info(MPT3SAS_FMT
172 "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
173 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
174 le32_to_cpu(mpi_reply->IOCLogInfo));
175}
176#endif
177
178/**
179 * _config_alloc_config_dma_memory - obtain physical memory
180 * @ioc: per adapter object
181 * @mem: struct config_request
182 *
183 * A wrapper for obtaining dma-able memory for config page request.
184 *
185 * Returns 0 for success, non-zero for failure.
186 */
187static int
188_config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
189 struct config_request *mem)
190{
191 int r = 0;
192
193 if (mem->sz > ioc->config_page_sz) {
194 mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
195 &mem->page_dma, GFP_KERNEL);
196 if (!mem->page) {
197 pr_err(MPT3SAS_FMT
198 "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n",
199 ioc->name, __func__, mem->sz);
200 r = -ENOMEM;
201 }
202 } else { /* use tmp buffer if less than 512 bytes */
203 mem->page = ioc->config_page;
204 mem->page_dma = ioc->config_page_dma;
205 }
206 return r;
207}
208
209/**
210 * _config_free_config_dma_memory - wrapper to free the memory
211 * @ioc: per adapter object
212 * @mem: struct config_request
213 *
214 * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
215 *
216 * Returns 0 for success, non-zero for failure.
217 */
218static void
219_config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc,
220 struct config_request *mem)
221{
222 if (mem->sz > ioc->config_page_sz)
223 dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
224 mem->page_dma);
225}
226
227/**
228 * mpt3sas_config_done - config page completion routine
229 * @ioc: per adapter object
230 * @smid: system request message index
231 * @msix_index: MSIX table index supplied by the OS
232 * @reply: reply message frame(lower 32bit addr)
233 * Context: none.
234 *
235 * The callback handler when using _config_request.
236 *
237 * Return 1 meaning mf should be freed from _base_interrupt
238 * 0 means the mf is freed from this function.
239 */
240u8
241mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
242 u32 reply)
243{
244 MPI2DefaultReply_t *mpi_reply;
245
246 if (ioc->config_cmds.status == MPT3_CMD_NOT_USED)
247 return 1;
248 if (ioc->config_cmds.smid != smid)
249 return 1;
250 ioc->config_cmds.status |= MPT3_CMD_COMPLETE;
251 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
252 if (mpi_reply) {
253 ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID;
254 memcpy(ioc->config_cmds.reply, mpi_reply,
255 mpi_reply->MsgLength*4);
256 }
257 ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
258#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
259 _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
260#endif
261 ioc->config_cmds.smid = USHRT_MAX;
262 complete(&ioc->config_cmds.done);
263 return 1;
264}
265
266/**
267 * _config_request - main routine for sending config page requests
268 * @ioc: per adapter object
269 * @mpi_request: request message frame
270 * @mpi_reply: reply mf payload returned from firmware
271 * @timeout: timeout in seconds
272 * @config_page: contents of the config page
273 * @config_page_sz: size of config page
274 * Context: sleep
275 *
276 * A generic API for config page requests to firmware.
277 *
278 * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling
279 * this API.
280 *
281 * The callback index is set inside `ioc->config_cb_idx.
282 *
283 * Returns 0 for success, non-zero for failure.
284 */
285static int
286_config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
287 *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
288 void *config_page, u16 config_page_sz)
289{
290 u16 smid;
291 u32 ioc_state;
292 unsigned long timeleft;
293 Mpi2ConfigRequest_t *config_request;
294 int r;
295 u8 retry_count, issue_host_reset = 0;
296 u16 wait_state_count;
297 struct config_request mem;
298 u32 ioc_status = UINT_MAX;
299
300 mutex_lock(&ioc->config_cmds.mutex);
301 if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) {
302 pr_err(MPT3SAS_FMT "%s: config_cmd in use\n",
303 ioc->name, __func__);
304 mutex_unlock(&ioc->config_cmds.mutex);
305 return -EAGAIN;
306 }
307
308 retry_count = 0;
309 memset(&mem, 0, sizeof(struct config_request));
310
311 mpi_request->VF_ID = 0; /* TODO */
312 mpi_request->VP_ID = 0;
313
314 if (config_page) {
315 mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion;
316 mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber;
317 mpi_request->Header.PageType = mpi_reply->Header.PageType;
318 mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
319 mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
320 mpi_request->ExtPageType = mpi_reply->ExtPageType;
321 if (mpi_request->Header.PageLength)
322 mem.sz = mpi_request->Header.PageLength * 4;
323 else
324 mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
325 r = _config_alloc_config_dma_memory(ioc, &mem);
326 if (r != 0)
327 goto out;
328 if (mpi_request->Action ==
329 MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
330 mpi_request->Action ==
331 MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
332 ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
333 MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
334 mem.page_dma);
335 memcpy(mem.page, config_page, min_t(u16, mem.sz,
336 config_page_sz));
337 } else {
338 memset(config_page, 0, config_page_sz);
339 ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
340 MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
341 memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz));
342 }
343 }
344
345 retry_config:
346 if (retry_count) {
347 if (retry_count > 2) { /* attempt only 2 retries */
348 r = -EFAULT;
349 goto free_mem;
350 }
351 pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n",
352 ioc->name, __func__, retry_count);
353 }
354 wait_state_count = 0;
355 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
356 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
357 if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) {
358 pr_err(MPT3SAS_FMT
359 "%s: failed due to ioc not operational\n",
360 ioc->name, __func__);
361 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
362 r = -EFAULT;
363 goto free_mem;
364 }
365 ssleep(1);
366 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
367 pr_info(MPT3SAS_FMT
368 "%s: waiting for operational state(count=%d)\n",
369 ioc->name, __func__, wait_state_count);
370 }
371 if (wait_state_count)
372 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
373 ioc->name, __func__);
374
375 smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx);
376 if (!smid) {
377 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
378 ioc->name, __func__);
379 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
380 r = -EAGAIN;
381 goto free_mem;
382 }
383
384 r = 0;
385 memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
386 ioc->config_cmds.status = MPT3_CMD_PENDING;
387 config_request = mpt3sas_base_get_msg_frame(ioc, smid);
388 ioc->config_cmds.smid = smid;
389 memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
390#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
391 _config_display_some_debug(ioc, smid, "config_request", NULL);
392#endif
393 init_completion(&ioc->config_cmds.done);
394 mpt3sas_base_put_smid_default(ioc, smid);
395 timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
396 timeout*HZ);
397 if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
398 pr_err(MPT3SAS_FMT "%s: timeout\n",
399 ioc->name, __func__);
400 _debug_dump_mf(mpi_request,
401 sizeof(Mpi2ConfigRequest_t)/4);
402 retry_count++;
403 if (ioc->config_cmds.smid == smid)
404 mpt3sas_base_free_smid(ioc, smid);
405 if ((ioc->shost_recovery) || (ioc->config_cmds.status &
406 MPT3_CMD_RESET) || ioc->pci_error_recovery)
407 goto retry_config;
408 issue_host_reset = 1;
409 r = -EFAULT;
410 goto free_mem;
411 }
412
413 if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) {
414 memcpy(mpi_reply, ioc->config_cmds.reply,
415 sizeof(Mpi2ConfigReply_t));
416
417 /* Reply Frame Sanity Checks to workaround FW issues */
418 if ((mpi_request->Header.PageType & 0xF) !=
419 (mpi_reply->Header.PageType & 0xF)) {
420 _debug_dump_mf(mpi_request, ioc->request_sz/4);
421 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
422 panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
423 " mpi_reply mismatch: Requested PageType(0x%02x)" \
424 " Reply PageType(0x%02x)\n", \
425 ioc->name, __func__,
426 (mpi_request->Header.PageType & 0xF),
427 (mpi_reply->Header.PageType & 0xF));
428 }
429
430 if (((mpi_request->Header.PageType & 0xF) ==
431 MPI2_CONFIG_PAGETYPE_EXTENDED) &&
432 mpi_request->ExtPageType != mpi_reply->ExtPageType) {
433 _debug_dump_mf(mpi_request, ioc->request_sz/4);
434 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
435 panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \
436 " mpi_reply mismatch: Requested ExtPageType(0x%02x)"
437 " Reply ExtPageType(0x%02x)\n",
438 ioc->name, __func__, mpi_request->ExtPageType,
439 mpi_reply->ExtPageType);
440 }
441 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
442 & MPI2_IOCSTATUS_MASK;
443 }
444
445 if (retry_count)
446 pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \
447 ioc->name, __func__, retry_count);
448
449 if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) &&
450 config_page && mpi_request->Action ==
451 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) {
452 u8 *p = (u8 *)mem.page;
453
454 /* Config Page Sanity Checks to workaround FW issues */
455 if (p) {
456 if ((mpi_request->Header.PageType & 0xF) !=
457 (p[3] & 0xF)) {
458 _debug_dump_mf(mpi_request, ioc->request_sz/4);
459 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
460 _debug_dump_config(p, min_t(u16, mem.sz,
461 config_page_sz)/4);
462 panic(KERN_WARNING MPT3SAS_FMT
463 "%s: Firmware BUG:" \
464 " config page mismatch:"
465 " Requested PageType(0x%02x)"
466 " Reply PageType(0x%02x)\n",
467 ioc->name, __func__,
468 (mpi_request->Header.PageType & 0xF),
469 (p[3] & 0xF));
470 }
471
472 if (((mpi_request->Header.PageType & 0xF) ==
473 MPI2_CONFIG_PAGETYPE_EXTENDED) &&
474 (mpi_request->ExtPageType != p[6])) {
475 _debug_dump_mf(mpi_request, ioc->request_sz/4);
476 _debug_dump_reply(mpi_reply, ioc->request_sz/4);
477 _debug_dump_config(p, min_t(u16, mem.sz,
478 config_page_sz)/4);
479 panic(KERN_WARNING MPT3SAS_FMT
480 "%s: Firmware BUG:" \
481 " config page mismatch:"
482 " Requested ExtPageType(0x%02x)"
483 " Reply ExtPageType(0x%02x)\n",
484 ioc->name, __func__,
485 mpi_request->ExtPageType, p[6]);
486 }
487 }
488 memcpy(config_page, mem.page, min_t(u16, mem.sz,
489 config_page_sz));
490 }
491
492 free_mem:
493 if (config_page)
494 _config_free_config_dma_memory(ioc, &mem);
495 out:
496 ioc->config_cmds.status = MPT3_CMD_NOT_USED;
497 mutex_unlock(&ioc->config_cmds.mutex);
498
499 if (issue_host_reset)
500 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
501 FORCE_BIG_HAMMER);
502 return r;
503}
504
505/**
506 * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
507 * @ioc: per adapter object
508 * @mpi_reply: reply mf payload returned from firmware
509 * @config_page: contents of the config page
510 * Context: sleep.
511 *
512 * Returns 0 for success, non-zero for failure.
513 */
514int
515mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc,
516 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
517{
518 Mpi2ConfigRequest_t mpi_request;
519 int r;
520
521 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
522 mpi_request.Function = MPI2_FUNCTION_CONFIG;
523 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
524 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
525 mpi_request.Header.PageNumber = 0;
526 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
527 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
528 r = _config_request(ioc, &mpi_request, mpi_reply,
529 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
530 if (r)
531 goto out;
532
533 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
534 r = _config_request(ioc, &mpi_request, mpi_reply,
535 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
536 sizeof(*config_page));
537 out:
538 return r;
539}
540
541/**
542 * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7
543 * @ioc: per adapter object
544 * @mpi_reply: reply mf payload returned from firmware
545 * @config_page: contents of the config page
546 * @sz: size of buffer passed in config_page
547 * Context: sleep.
548 *
549 * Returns 0 for success, non-zero for failure.
550 */
551int
552mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc,
553 Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page,
554 u16 sz)
555{
556 Mpi2ConfigRequest_t mpi_request;
557 int r;
558
559 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
560 mpi_request.Function = MPI2_FUNCTION_CONFIG;
561 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
562 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
563 mpi_request.Header.PageNumber = 7;
564 mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION;
565 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
566 r = _config_request(ioc, &mpi_request, mpi_reply,
567 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
568 if (r)
569 goto out;
570
571 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
572 r = _config_request(ioc, &mpi_request, mpi_reply,
573 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
574 sz);
575 out:
576 return r;
577}
578
579/**
580 * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
581 * @ioc: per adapter object
582 * @mpi_reply: reply mf payload returned from firmware
583 * @config_page: contents of the config page
584 * Context: sleep.
585 *
586 * Returns 0 for success, non-zero for failure.
587 */
588int
589mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc,
590 Mpi2ConfigReply_t *mpi_reply,
591 struct Mpi2ManufacturingPage10_t *config_page)
592{
593 Mpi2ConfigRequest_t mpi_request;
594 int r;
595
596 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
597 mpi_request.Function = MPI2_FUNCTION_CONFIG;
598 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
599 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
600 mpi_request.Header.PageNumber = 10;
601 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
602 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
603 r = _config_request(ioc, &mpi_request, mpi_reply,
604 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
605 if (r)
606 goto out;
607
608 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
609 r = _config_request(ioc, &mpi_request, mpi_reply,
610 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
611 sizeof(*config_page));
612 out:
613 return r;
614}
615
616/**
617 * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11
618 * @ioc: per adapter object
619 * @mpi_reply: reply mf payload returned from firmware
620 * @config_page: contents of the config page
621 * Context: sleep.
622 *
623 * Returns 0 for success, non-zero for failure.
624 */
625int
626mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
627 Mpi2ConfigReply_t *mpi_reply,
628 struct Mpi2ManufacturingPage11_t *config_page)
629{
630 Mpi2ConfigRequest_t mpi_request;
631 int r;
632
633 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
634 mpi_request.Function = MPI2_FUNCTION_CONFIG;
635 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
636 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
637 mpi_request.Header.PageNumber = 11;
638 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
639 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
640 r = _config_request(ioc, &mpi_request, mpi_reply,
641 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
642 if (r)
643 goto out;
644
645 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
646 r = _config_request(ioc, &mpi_request, mpi_reply,
647 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
648 sizeof(*config_page));
649 out:
650 return r;
651}
652
653/**
654 * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11
655 * @ioc: per adapter object
656 * @mpi_reply: reply mf payload returned from firmware
657 * @config_page: contents of the config page
658 * Context: sleep.
659 *
660 * Returns 0 for success, non-zero for failure.
661 */
662int
663mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc,
664 Mpi2ConfigReply_t *mpi_reply,
665 struct Mpi2ManufacturingPage11_t *config_page)
666{
667 Mpi2ConfigRequest_t mpi_request;
668 int r;
669
670 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
671 mpi_request.Function = MPI2_FUNCTION_CONFIG;
672 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
673 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
674 mpi_request.Header.PageNumber = 11;
675 mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
676 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
677 r = _config_request(ioc, &mpi_request, mpi_reply,
678 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
679 if (r)
680 goto out;
681
682 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
683 r = _config_request(ioc, &mpi_request, mpi_reply,
684 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
685 sizeof(*config_page));
686 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
687 r = _config_request(ioc, &mpi_request, mpi_reply,
688 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
689 sizeof(*config_page));
690 out:
691 return r;
692}
693
694/**
695 * mpt3sas_config_get_bios_pg2 - obtain bios page 2
696 * @ioc: per adapter object
697 * @mpi_reply: reply mf payload returned from firmware
698 * @config_page: contents of the config page
699 * Context: sleep.
700 *
701 * Returns 0 for success, non-zero for failure.
702 */
703int
704mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc,
705 Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
706{
707 Mpi2ConfigRequest_t mpi_request;
708 int r;
709
710 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
711 mpi_request.Function = MPI2_FUNCTION_CONFIG;
712 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
713 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
714 mpi_request.Header.PageNumber = 2;
715 mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
716 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
717 r = _config_request(ioc, &mpi_request, mpi_reply,
718 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
719 if (r)
720 goto out;
721
722 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
723 r = _config_request(ioc, &mpi_request, mpi_reply,
724 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
725 sizeof(*config_page));
726 out:
727 return r;
728}
729
730/**
731 * mpt3sas_config_get_bios_pg3 - obtain bios page 3
732 * @ioc: per adapter object
733 * @mpi_reply: reply mf payload returned from firmware
734 * @config_page: contents of the config page
735 * Context: sleep.
736 *
737 * Returns 0 for success, non-zero for failure.
738 */
739int
740mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
741 *mpi_reply, Mpi2BiosPage3_t *config_page)
742{
743 Mpi2ConfigRequest_t mpi_request;
744 int r;
745
746 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
747 mpi_request.Function = MPI2_FUNCTION_CONFIG;
748 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
749 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
750 mpi_request.Header.PageNumber = 3;
751 mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
752 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
753 r = _config_request(ioc, &mpi_request, mpi_reply,
754 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
755 if (r)
756 goto out;
757
758 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
759 r = _config_request(ioc, &mpi_request, mpi_reply,
760 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
761 sizeof(*config_page));
762 out:
763 return r;
764}
765
766/**
767 * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0
768 * @ioc: per adapter object
769 * @mpi_reply: reply mf payload returned from firmware
770 * @config_page: contents of the config page
771 * Context: sleep.
772 *
773 * Returns 0 for success, non-zero for failure.
774 */
775int
776mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
777 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
778{
779 Mpi2ConfigRequest_t mpi_request;
780 int r;
781
782 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
783 mpi_request.Function = MPI2_FUNCTION_CONFIG;
784 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
785 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
786 mpi_request.Header.PageNumber = 0;
787 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
788 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
789 r = _config_request(ioc, &mpi_request, mpi_reply,
790 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
791 if (r)
792 goto out;
793
794 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
795 r = _config_request(ioc, &mpi_request, mpi_reply,
796 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
797 sizeof(*config_page));
798 out:
799 return r;
800}
801
802/**
803 * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1
804 * @ioc: per adapter object
805 * @mpi_reply: reply mf payload returned from firmware
806 * @config_page: contents of the config page
807 * Context: sleep.
808 *
809 * Returns 0 for success, non-zero for failure.
810 */
811int
812mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
813 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
814{
815 Mpi2ConfigRequest_t mpi_request;
816 int r;
817
818 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
819 mpi_request.Function = MPI2_FUNCTION_CONFIG;
820 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
821 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
822 mpi_request.Header.PageNumber = 1;
823 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
824 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
825 r = _config_request(ioc, &mpi_request, mpi_reply,
826 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
827 if (r)
828 goto out;
829
830 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
831 r = _config_request(ioc, &mpi_request, mpi_reply,
832 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
833 sizeof(*config_page));
834 out:
835 return r;
836}
837
838/**
839 * mpt3sas_config_set_iounit_pg1 - set iounit page 1
840 * @ioc: per adapter object
841 * @mpi_reply: reply mf payload returned from firmware
842 * @config_page: contents of the config page
843 * Context: sleep.
844 *
845 * Returns 0 for success, non-zero for failure.
846 */
847int
848mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
849 Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
850{
851 Mpi2ConfigRequest_t mpi_request;
852 int r;
853
854 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
855 mpi_request.Function = MPI2_FUNCTION_CONFIG;
856 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
857 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
858 mpi_request.Header.PageNumber = 1;
859 mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
860 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
861 r = _config_request(ioc, &mpi_request, mpi_reply,
862 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
863 if (r)
864 goto out;
865
866 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
867 r = _config_request(ioc, &mpi_request, mpi_reply,
868 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
869 sizeof(*config_page));
870 out:
871 return r;
872}
873
874/**
875 * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8
876 * @ioc: per adapter object
877 * @mpi_reply: reply mf payload returned from firmware
878 * @config_page: contents of the config page
879 * Context: sleep.
880 *
881 * Returns 0 for success, non-zero for failure.
882 */
883int
884mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc,
885 Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
886{
887 Mpi2ConfigRequest_t mpi_request;
888 int r;
889
890 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
891 mpi_request.Function = MPI2_FUNCTION_CONFIG;
892 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
893 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
894 mpi_request.Header.PageNumber = 8;
895 mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
896 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
897 r = _config_request(ioc, &mpi_request, mpi_reply,
898 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
899 if (r)
900 goto out;
901
902 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
903 r = _config_request(ioc, &mpi_request, mpi_reply,
904 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
905 sizeof(*config_page));
906 out:
907 return r;
908}
909
910/**
911 * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0
912 * @ioc: per adapter object
913 * @mpi_reply: reply mf payload returned from firmware
914 * @config_page: contents of the config page
915 * @form: GET_NEXT_HANDLE or HANDLE
916 * @handle: device handle
917 * Context: sleep.
918 *
919 * Returns 0 for success, non-zero for failure.
920 */
921int
922mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
923 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page,
924 u32 form, u32 handle)
925{
926 Mpi2ConfigRequest_t mpi_request;
927 int r;
928
929 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
930 mpi_request.Function = MPI2_FUNCTION_CONFIG;
931 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
932 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
933 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
934 mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
935 mpi_request.Header.PageNumber = 0;
936 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
937 r = _config_request(ioc, &mpi_request, mpi_reply,
938 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
939 if (r)
940 goto out;
941
942 mpi_request.PageAddress = cpu_to_le32(form | handle);
943 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
944 r = _config_request(ioc, &mpi_request, mpi_reply,
945 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
946 sizeof(*config_page));
947 out:
948 return r;
949}
950
951/**
952 * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1
953 * @ioc: per adapter object
954 * @mpi_reply: reply mf payload returned from firmware
955 * @config_page: contents of the config page
956 * @form: GET_NEXT_HANDLE or HANDLE
957 * @handle: device handle
958 * Context: sleep.
959 *
960 * Returns 0 for success, non-zero for failure.
961 */
962int
963mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
964 Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
965 u32 form, u32 handle)
966{
967 Mpi2ConfigRequest_t mpi_request;
968 int r;
969
970 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
971 mpi_request.Function = MPI2_FUNCTION_CONFIG;
972 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
973 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
974 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
975 mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
976 mpi_request.Header.PageNumber = 1;
977 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
978 r = _config_request(ioc, &mpi_request, mpi_reply,
979 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
980 if (r)
981 goto out;
982
983 mpi_request.PageAddress = cpu_to_le32(form | handle);
984 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
985 r = _config_request(ioc, &mpi_request, mpi_reply,
986 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
987 sizeof(*config_page));
988 out:
989 return r;
990}
991
992/**
993 * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
994 * @ioc: per adapter object
995 * @num_phys: pointer returned with the number of phys
996 * Context: sleep.
997 *
998 * Returns 0 for success, non-zero for failure.
999 */
1000int
1001mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys)
1002{
1003 Mpi2ConfigRequest_t mpi_request;
1004 int r;
1005 u16 ioc_status;
1006 Mpi2ConfigReply_t mpi_reply;
1007 Mpi2SasIOUnitPage0_t config_page;
1008
1009 *num_phys = 0;
1010 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1011 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1012 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1013 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1014 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1015 mpi_request.Header.PageNumber = 0;
1016 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1017 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1018 r = _config_request(ioc, &mpi_request, &mpi_reply,
1019 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1020 if (r)
1021 goto out;
1022
1023 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1024 r = _config_request(ioc, &mpi_request, &mpi_reply,
1025 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1026 sizeof(Mpi2SasIOUnitPage0_t));
1027 if (!r) {
1028 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1029 MPI2_IOCSTATUS_MASK;
1030 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1031 *num_phys = config_page.NumPhys;
1032 }
1033 out:
1034 return r;
1035}
1036
1037/**
1038 * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
1039 * @ioc: per adapter object
1040 * @mpi_reply: reply mf payload returned from firmware
1041 * @config_page: contents of the config page
1042 * @sz: size of buffer passed in config_page
1043 * Context: sleep.
1044 *
1045 * Calling function should call config_get_number_hba_phys prior to
1046 * this function, so enough memory is allocated for config_page.
1047 *
1048 * Returns 0 for success, non-zero for failure.
1049 */
1050int
1051mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
1052 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
1053 u16 sz)
1054{
1055 Mpi2ConfigRequest_t mpi_request;
1056 int r;
1057
1058 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1059 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1060 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1061 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1062 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1063 mpi_request.Header.PageNumber = 0;
1064 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
1065 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1066 r = _config_request(ioc, &mpi_request, mpi_reply,
1067 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1068 if (r)
1069 goto out;
1070
1071 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1072 r = _config_request(ioc, &mpi_request, mpi_reply,
1073 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1074 out:
1075 return r;
1076}
1077
1078/**
1079 * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
1080 * @ioc: per adapter object
1081 * @mpi_reply: reply mf payload returned from firmware
1082 * @config_page: contents of the config page
1083 * @sz: size of buffer passed in config_page
1084 * Context: sleep.
1085 *
1086 * Calling function should call config_get_number_hba_phys prior to
1087 * this function, so enough memory is allocated for config_page.
1088 *
1089 * Returns 0 for success, non-zero for failure.
1090 */
1091int
1092mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1093 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1094 u16 sz)
1095{
1096 Mpi2ConfigRequest_t mpi_request;
1097 int r;
1098
1099 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1100 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1101 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1102 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1103 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1104 mpi_request.Header.PageNumber = 1;
1105 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1106 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1107 r = _config_request(ioc, &mpi_request, mpi_reply,
1108 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1109 if (r)
1110 goto out;
1111
1112 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1113 r = _config_request(ioc, &mpi_request, mpi_reply,
1114 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1115 out:
1116 return r;
1117}
1118
1119/**
1120 * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1
1121 * @ioc: per adapter object
1122 * @mpi_reply: reply mf payload returned from firmware
1123 * @config_page: contents of the config page
1124 * @sz: size of buffer passed in config_page
1125 * Context: sleep.
1126 *
1127 * Calling function should call config_get_number_hba_phys prior to
1128 * this function, so enough memory is allocated for config_page.
1129 *
1130 * Returns 0 for success, non-zero for failure.
1131 */
1132int
1133mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
1134 Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page,
1135 u16 sz)
1136{
1137 Mpi2ConfigRequest_t mpi_request;
1138 int r;
1139
1140 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1141 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1142 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1143 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1144 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1145 mpi_request.Header.PageNumber = 1;
1146 mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
1147 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1148 r = _config_request(ioc, &mpi_request, mpi_reply,
1149 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1150 if (r)
1151 goto out;
1152
1153 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
1154 _config_request(ioc, &mpi_request, mpi_reply,
1155 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1156 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
1157 r = _config_request(ioc, &mpi_request, mpi_reply,
1158 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1159 out:
1160 return r;
1161}
1162
1163/**
1164 * mpt3sas_config_get_expander_pg0 - obtain expander page 0
1165 * @ioc: per adapter object
1166 * @mpi_reply: reply mf payload returned from firmware
1167 * @config_page: contents of the config page
1168 * @form: GET_NEXT_HANDLE or HANDLE
1169 * @handle: expander handle
1170 * Context: sleep.
1171 *
1172 * Returns 0 for success, non-zero for failure.
1173 */
1174int
1175mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1176 *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
1177{
1178 Mpi2ConfigRequest_t mpi_request;
1179 int r;
1180
1181 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1182 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1183 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1184 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1185 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1186 mpi_request.Header.PageNumber = 0;
1187 mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
1188 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1189 r = _config_request(ioc, &mpi_request, mpi_reply,
1190 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1191 if (r)
1192 goto out;
1193
1194 mpi_request.PageAddress = cpu_to_le32(form | handle);
1195 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1196 r = _config_request(ioc, &mpi_request, mpi_reply,
1197 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1198 sizeof(*config_page));
1199 out:
1200 return r;
1201}
1202
1203/**
1204 * mpt3sas_config_get_expander_pg1 - obtain expander page 1
1205 * @ioc: per adapter object
1206 * @mpi_reply: reply mf payload returned from firmware
1207 * @config_page: contents of the config page
1208 * @phy_number: phy number
1209 * @handle: expander handle
1210 * Context: sleep.
1211 *
1212 * Returns 0 for success, non-zero for failure.
1213 */
1214int
1215mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1216 *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
1217 u16 handle)
1218{
1219 Mpi2ConfigRequest_t mpi_request;
1220 int r;
1221
1222 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1223 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1224 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1225 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1226 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1227 mpi_request.Header.PageNumber = 1;
1228 mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
1229 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1230 r = _config_request(ioc, &mpi_request, mpi_reply,
1231 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1232 if (r)
1233 goto out;
1234
1235 mpi_request.PageAddress =
1236 cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
1237 (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
1238 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1239 r = _config_request(ioc, &mpi_request, mpi_reply,
1240 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1241 sizeof(*config_page));
1242 out:
1243 return r;
1244}
1245
1246/**
1247 * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0
1248 * @ioc: per adapter object
1249 * @mpi_reply: reply mf payload returned from firmware
1250 * @config_page: contents of the config page
1251 * @form: GET_NEXT_HANDLE or HANDLE
1252 * @handle: expander handle
1253 * Context: sleep.
1254 *
1255 * Returns 0 for success, non-zero for failure.
1256 */
1257int
1258mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1259 *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
1260{
1261 Mpi2ConfigRequest_t mpi_request;
1262 int r;
1263
1264 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1265 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1266 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1267 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1268 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
1269 mpi_request.Header.PageNumber = 0;
1270 mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
1271 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1272 r = _config_request(ioc, &mpi_request, mpi_reply,
1273 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1274 if (r)
1275 goto out;
1276
1277 mpi_request.PageAddress = cpu_to_le32(form | handle);
1278 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1279 r = _config_request(ioc, &mpi_request, mpi_reply,
1280 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1281 sizeof(*config_page));
1282 out:
1283 return r;
1284}
1285
1286/**
1287 * mpt3sas_config_get_phy_pg0 - obtain phy page 0
1288 * @ioc: per adapter object
1289 * @mpi_reply: reply mf payload returned from firmware
1290 * @config_page: contents of the config page
1291 * @phy_number: phy number
1292 * Context: sleep.
1293 *
1294 * Returns 0 for success, non-zero for failure.
1295 */
1296int
1297mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1298 *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
1299{
1300 Mpi2ConfigRequest_t mpi_request;
1301 int r;
1302
1303 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1304 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1305 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1306 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1307 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1308 mpi_request.Header.PageNumber = 0;
1309 mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
1310 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1311 r = _config_request(ioc, &mpi_request, mpi_reply,
1312 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1313 if (r)
1314 goto out;
1315
1316 mpi_request.PageAddress =
1317 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1318 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1319 r = _config_request(ioc, &mpi_request, mpi_reply,
1320 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1321 sizeof(*config_page));
1322 out:
1323 return r;
1324}
1325
1326/**
1327 * mpt3sas_config_get_phy_pg1 - obtain phy page 1
1328 * @ioc: per adapter object
1329 * @mpi_reply: reply mf payload returned from firmware
1330 * @config_page: contents of the config page
1331 * @phy_number: phy number
1332 * Context: sleep.
1333 *
1334 * Returns 0 for success, non-zero for failure.
1335 */
1336int
1337mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1338 *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
1339{
1340 Mpi2ConfigRequest_t mpi_request;
1341 int r;
1342
1343 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1344 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1345 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1346 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1347 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
1348 mpi_request.Header.PageNumber = 1;
1349 mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
1350 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1351 r = _config_request(ioc, &mpi_request, mpi_reply,
1352 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1353 if (r)
1354 goto out;
1355
1356 mpi_request.PageAddress =
1357 cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
1358 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1359 r = _config_request(ioc, &mpi_request, mpi_reply,
1360 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1361 sizeof(*config_page));
1362 out:
1363 return r;
1364}
1365
1366/**
1367 * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1
1368 * @ioc: per adapter object
1369 * @mpi_reply: reply mf payload returned from firmware
1370 * @config_page: contents of the config page
1371 * @form: GET_NEXT_HANDLE or HANDLE
1372 * @handle: volume handle
1373 * Context: sleep.
1374 *
1375 * Returns 0 for success, non-zero for failure.
1376 */
1377int
1378mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc,
1379 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
1380 u32 handle)
1381{
1382 Mpi2ConfigRequest_t mpi_request;
1383 int r;
1384
1385 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1386 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1387 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1388 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1389 mpi_request.Header.PageNumber = 1;
1390 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1391 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1392 r = _config_request(ioc, &mpi_request, mpi_reply,
1393 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1394 if (r)
1395 goto out;
1396
1397 mpi_request.PageAddress = cpu_to_le32(form | handle);
1398 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1399 r = _config_request(ioc, &mpi_request, mpi_reply,
1400 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1401 sizeof(*config_page));
1402 out:
1403 return r;
1404}
1405
1406/**
1407 * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume
1408 * @ioc: per adapter object
1409 * @handle: volume handle
1410 * @num_pds: returns pds count
1411 * Context: sleep.
1412 *
1413 * Returns 0 for success, non-zero for failure.
1414 */
1415int
1416mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle,
1417 u8 *num_pds)
1418{
1419 Mpi2ConfigRequest_t mpi_request;
1420 Mpi2RaidVolPage0_t config_page;
1421 Mpi2ConfigReply_t mpi_reply;
1422 int r;
1423 u16 ioc_status;
1424
1425 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1426 *num_pds = 0;
1427 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1428 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1429 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1430 mpi_request.Header.PageNumber = 0;
1431 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1432 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1433 r = _config_request(ioc, &mpi_request, &mpi_reply,
1434 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1435 if (r)
1436 goto out;
1437
1438 mpi_request.PageAddress =
1439 cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
1440 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1441 r = _config_request(ioc, &mpi_request, &mpi_reply,
1442 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
1443 sizeof(Mpi2RaidVolPage0_t));
1444 if (!r) {
1445 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1446 MPI2_IOCSTATUS_MASK;
1447 if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
1448 *num_pds = config_page.NumPhysDisks;
1449 }
1450
1451 out:
1452 return r;
1453}
1454
1455/**
1456 * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0
1457 * @ioc: per adapter object
1458 * @mpi_reply: reply mf payload returned from firmware
1459 * @config_page: contents of the config page
1460 * @form: GET_NEXT_HANDLE or HANDLE
1461 * @handle: volume handle
1462 * @sz: size of buffer passed in config_page
1463 * Context: sleep.
1464 *
1465 * Returns 0 for success, non-zero for failure.
1466 */
1467int
1468mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc,
1469 Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
1470 u32 handle, u16 sz)
1471{
1472 Mpi2ConfigRequest_t mpi_request;
1473 int r;
1474
1475 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1476 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1477 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1478 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1479 mpi_request.Header.PageNumber = 0;
1480 mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1481 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1482 r = _config_request(ioc, &mpi_request, mpi_reply,
1483 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1484 if (r)
1485 goto out;
1486
1487 mpi_request.PageAddress = cpu_to_le32(form | handle);
1488 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1489 r = _config_request(ioc, &mpi_request, mpi_reply,
1490 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
1491 out:
1492 return r;
1493}
1494
1495/**
1496 * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0
1497 * @ioc: per adapter object
1498 * @mpi_reply: reply mf payload returned from firmware
1499 * @config_page: contents of the config page
1500 * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
1501 * @form_specific: specific to the form
1502 * Context: sleep.
1503 *
1504 * Returns 0 for success, non-zero for failure.
1505 */
1506int
1507mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
1508 *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
1509 u32 form_specific)
1510{
1511 Mpi2ConfigRequest_t mpi_request;
1512 int r;
1513
1514 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1515 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1516 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1517 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1518 mpi_request.Header.PageNumber = 0;
1519 mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1520 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1521 r = _config_request(ioc, &mpi_request, mpi_reply,
1522 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1523 if (r)
1524 goto out;
1525
1526 mpi_request.PageAddress = cpu_to_le32(form | form_specific);
1527 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1528 r = _config_request(ioc, &mpi_request, mpi_reply,
1529 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1530 sizeof(*config_page));
1531 out:
1532 return r;
1533}
1534
1535/**
1536 * mpt3sas_config_get_volume_handle - returns volume handle for give hidden
1537 * raid components
1538 * @ioc: per adapter object
1539 * @pd_handle: phys disk handle
1540 * @volume_handle: volume handle
1541 * Context: sleep.
1542 *
1543 * Returns 0 for success, non-zero for failure.
1544 */
1545int
1546mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle,
1547 u16 *volume_handle)
1548{
1549 Mpi2RaidConfigurationPage0_t *config_page = NULL;
1550 Mpi2ConfigRequest_t mpi_request;
1551 Mpi2ConfigReply_t mpi_reply;
1552 int r, i, config_page_sz;
1553 u16 ioc_status;
1554 int config_num;
1555 u16 element_type;
1556 u16 phys_disk_dev_handle;
1557
1558 *volume_handle = 0;
1559 memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
1560 mpi_request.Function = MPI2_FUNCTION_CONFIG;
1561 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1562 mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1563 mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
1564 mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
1565 mpi_request.Header.PageNumber = 0;
1566 ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
1567 r = _config_request(ioc, &mpi_request, &mpi_reply,
1568 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
1569 if (r)
1570 goto out;
1571
1572 mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1573 config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
1574 config_page = kmalloc(config_page_sz, GFP_KERNEL);
1575 if (!config_page) {
1576 r = -1;
1577 goto out;
1578 }
1579
1580 config_num = 0xff;
1581 while (1) {
1582 mpi_request.PageAddress = cpu_to_le32(config_num +
1583 MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
1584 r = _config_request(ioc, &mpi_request, &mpi_reply,
1585 MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
1586 config_page_sz);
1587 if (r)
1588 goto out;
1589 r = -1;
1590 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1591 MPI2_IOCSTATUS_MASK;
1592 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
1593 goto out;
1594 for (i = 0; i < config_page->NumElements; i++) {
1595 element_type = le16_to_cpu(config_page->
1596 ConfigElement[i].ElementFlags) &
1597 MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
1598 if (element_type ==
1599 MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
1600 element_type ==
1601 MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
1602 phys_disk_dev_handle =
1603 le16_to_cpu(config_page->ConfigElement[i].
1604 PhysDiskDevHandle);
1605 if (phys_disk_dev_handle == pd_handle) {
1606 *volume_handle =
1607 le16_to_cpu(config_page->
1608 ConfigElement[i].VolDevHandle);
1609 r = 0;
1610 goto out;
1611 }
1612 } else if (element_type ==
1613 MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
1614 *volume_handle = 0;
1615 r = 0;
1616 goto out;
1617 }
1618 }
1619 config_num = config_page->ConfigNum;
1620 }
1621 out:
1622 kfree(config_page);
1623 return r;
1624}
1625
1626/**
1627 * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle
1628 * @ioc: per adapter object
1629 * @volume_handle: volume handle
1630 * @wwid: volume wwid
1631 * Context: sleep.
1632 *
1633 * Returns 0 for success, non-zero for failure.
1634 */
1635int
1636mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle,
1637 u64 *wwid)
1638{
1639 Mpi2ConfigReply_t mpi_reply;
1640 Mpi2RaidVolPage1_t raid_vol_pg1;
1641
1642 *wwid = 0;
1643 if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
1644 &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
1645 volume_handle))) {
1646 *wwid = le64_to_cpu(raid_vol_pg1.WWID);
1647 return 0;
1648 } else
1649 return -1;
1650}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
new file mode 100644
index 000000000000..8af944d7d13d
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -0,0 +1,3297 @@
1/*
2 * Management Module Support for MPT (Message Passing Technology) based
3 * controllers
4 *
5 * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.c
6 * Copyright (C) 2012 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/compat.h>
55#include <linux/poll.h>
56
57#include <linux/io.h>
58#include <linux/uaccess.h>
59
60#include "mpt3sas_base.h"
61#include "mpt3sas_ctl.h"
62
63
64static struct fasync_struct *async_queue;
65static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
66
67
68/**
69 * enum block_state - blocking state
70 * @NON_BLOCKING: non blocking
71 * @BLOCKING: blocking
72 *
73 * These states are for ioctls that need to wait for a response
74 * from firmware, so they probably require sleep.
75 */
76enum block_state {
77 NON_BLOCKING,
78 BLOCKING,
79};
80
81#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
82/**
83 * _ctl_sas_device_find_by_handle - sas device search
84 * @ioc: per adapter object
85 * @handle: sas device handle (assigned by firmware)
86 * Context: Calling function should acquire ioc->sas_device_lock
87 *
88 * This searches for sas_device based on sas_address, then return sas_device
89 * object.
90 */
91static struct _sas_device *
92_ctl_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
93{
94 struct _sas_device *sas_device, *r;
95
96 r = NULL;
97 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
98 if (sas_device->handle != handle)
99 continue;
100 r = sas_device;
101 goto out;
102 }
103
104 out:
105 return r;
106}
107
108/**
109 * _ctl_display_some_debug - debug routine
110 * @ioc: per adapter object
111 * @smid: system request message index
112 * @calling_function_name: string pass from calling function
113 * @mpi_reply: reply message frame
114 * Context: none.
115 *
116 * Function for displaying debug info helpful when debugging issues
117 * in this module.
118 */
119static void
120_ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
121 char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
122{
123 Mpi2ConfigRequest_t *mpi_request;
124 char *desc = NULL;
125
126 if (!(ioc->logging_level & MPT_DEBUG_IOCTL))
127 return;
128
129 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
130 switch (mpi_request->Function) {
131 case MPI2_FUNCTION_SCSI_IO_REQUEST:
132 {
133 Mpi2SCSIIORequest_t *scsi_request =
134 (Mpi2SCSIIORequest_t *)mpi_request;
135
136 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
137 "scsi_io, cmd(0x%02x), cdb_len(%d)",
138 scsi_request->CDB.CDB32[0],
139 le16_to_cpu(scsi_request->IoFlags) & 0xF);
140 desc = ioc->tmp_string;
141 break;
142 }
143 case MPI2_FUNCTION_SCSI_TASK_MGMT:
144 desc = "task_mgmt";
145 break;
146 case MPI2_FUNCTION_IOC_INIT:
147 desc = "ioc_init";
148 break;
149 case MPI2_FUNCTION_IOC_FACTS:
150 desc = "ioc_facts";
151 break;
152 case MPI2_FUNCTION_CONFIG:
153 {
154 Mpi2ConfigRequest_t *config_request =
155 (Mpi2ConfigRequest_t *)mpi_request;
156
157 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
158 "config, type(0x%02x), ext_type(0x%02x), number(%d)",
159 (config_request->Header.PageType &
160 MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType,
161 config_request->Header.PageNumber);
162 desc = ioc->tmp_string;
163 break;
164 }
165 case MPI2_FUNCTION_PORT_FACTS:
166 desc = "port_facts";
167 break;
168 case MPI2_FUNCTION_PORT_ENABLE:
169 desc = "port_enable";
170 break;
171 case MPI2_FUNCTION_EVENT_NOTIFICATION:
172 desc = "event_notification";
173 break;
174 case MPI2_FUNCTION_FW_DOWNLOAD:
175 desc = "fw_download";
176 break;
177 case MPI2_FUNCTION_FW_UPLOAD:
178 desc = "fw_upload";
179 break;
180 case MPI2_FUNCTION_RAID_ACTION:
181 desc = "raid_action";
182 break;
183 case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
184 {
185 Mpi2SCSIIORequest_t *scsi_request =
186 (Mpi2SCSIIORequest_t *)mpi_request;
187
188 snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
189 "raid_pass, cmd(0x%02x), cdb_len(%d)",
190 scsi_request->CDB.CDB32[0],
191 le16_to_cpu(scsi_request->IoFlags) & 0xF);
192 desc = ioc->tmp_string;
193 break;
194 }
195 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
196 desc = "sas_iounit_cntl";
197 break;
198 case MPI2_FUNCTION_SATA_PASSTHROUGH:
199 desc = "sata_pass";
200 break;
201 case MPI2_FUNCTION_DIAG_BUFFER_POST:
202 desc = "diag_buffer_post";
203 break;
204 case MPI2_FUNCTION_DIAG_RELEASE:
205 desc = "diag_release";
206 break;
207 case MPI2_FUNCTION_SMP_PASSTHROUGH:
208 desc = "smp_passthrough";
209 break;
210 }
211
212 if (!desc)
213 return;
214
215 pr_info(MPT3SAS_FMT "%s: %s, smid(%d)\n",
216 ioc->name, calling_function_name, desc, smid);
217
218 if (!mpi_reply)
219 return;
220
221 if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
222 pr_info(MPT3SAS_FMT
223 "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
224 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
225 le32_to_cpu(mpi_reply->IOCLogInfo));
226
227 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
228 mpi_request->Function ==
229 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
230 Mpi2SCSIIOReply_t *scsi_reply =
231 (Mpi2SCSIIOReply_t *)mpi_reply;
232 struct _sas_device *sas_device = NULL;
233 unsigned long flags;
234
235 spin_lock_irqsave(&ioc->sas_device_lock, flags);
236 sas_device = _ctl_sas_device_find_by_handle(ioc,
237 le16_to_cpu(scsi_reply->DevHandle));
238 if (sas_device) {
239 pr_warn(MPT3SAS_FMT "\tsas_address(0x%016llx), phy(%d)\n",
240 ioc->name, (unsigned long long)
241 sas_device->sas_address, sas_device->phy);
242 pr_warn(MPT3SAS_FMT
243 "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
244 ioc->name, (unsigned long long)
245 sas_device->enclosure_logical_id, sas_device->slot);
246 }
247 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
248 if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
249 pr_info(MPT3SAS_FMT
250 "\tscsi_state(0x%02x), scsi_status"
251 "(0x%02x)\n", ioc->name,
252 scsi_reply->SCSIState,
253 scsi_reply->SCSIStatus);
254 }
255}
256
257#endif
258
259/**
260 * mpt3sas_ctl_done - ctl module completion routine
261 * @ioc: per adapter object
262 * @smid: system request message index
263 * @msix_index: MSIX table index supplied by the OS
264 * @reply: reply message frame(lower 32bit addr)
265 * Context: none.
266 *
267 * The callback handler when using ioc->ctl_cb_idx.
268 *
269 * Return 1 meaning mf should be freed from _base_interrupt
270 * 0 means the mf is freed from this function.
271 */
272u8
273mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
274 u32 reply)
275{
276 MPI2DefaultReply_t *mpi_reply;
277 Mpi2SCSIIOReply_t *scsiio_reply;
278 const void *sense_data;
279 u32 sz;
280
281 if (ioc->ctl_cmds.status == MPT3_CMD_NOT_USED)
282 return 1;
283 if (ioc->ctl_cmds.smid != smid)
284 return 1;
285 ioc->ctl_cmds.status |= MPT3_CMD_COMPLETE;
286 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
287 if (mpi_reply) {
288 memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
289 ioc->ctl_cmds.status |= MPT3_CMD_REPLY_VALID;
290 /* get sense data */
291 if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
292 mpi_reply->Function ==
293 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
294 scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply;
295 if (scsiio_reply->SCSIState &
296 MPI2_SCSI_STATE_AUTOSENSE_VALID) {
297 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
298 le32_to_cpu(scsiio_reply->SenseCount));
299 sense_data = mpt3sas_base_get_sense_buffer(ioc,
300 smid);
301 memcpy(ioc->ctl_cmds.sense, sense_data, sz);
302 }
303 }
304 }
305#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
306 _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
307#endif
308 ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING;
309 complete(&ioc->ctl_cmds.done);
310 return 1;
311}
312
313/**
314 * _ctl_check_event_type - determines when an event needs logging
315 * @ioc: per adapter object
316 * @event: firmware event
317 *
318 * The bitmask in ioc->event_type[] indicates which events should be
319 * be saved in the driver event_log. This bitmask is set by application.
320 *
321 * Returns 1 when event should be captured, or zero means no match.
322 */
323static int
324_ctl_check_event_type(struct MPT3SAS_ADAPTER *ioc, u16 event)
325{
326 u16 i;
327 u32 desired_event;
328
329 if (event >= 128 || !event || !ioc->event_log)
330 return 0;
331
332 desired_event = (1 << (event % 32));
333 if (!desired_event)
334 desired_event = 1;
335 i = event / 32;
336 return desired_event & ioc->event_type[i];
337}
338
339/**
340 * mpt3sas_ctl_add_to_event_log - add event
341 * @ioc: per adapter object
342 * @mpi_reply: reply message frame
343 *
344 * Return nothing.
345 */
346void
347mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc,
348 Mpi2EventNotificationReply_t *mpi_reply)
349{
350 struct MPT3_IOCTL_EVENTS *event_log;
351 u16 event;
352 int i;
353 u32 sz, event_data_sz;
354 u8 send_aen = 0;
355
356 if (!ioc->event_log)
357 return;
358
359 event = le16_to_cpu(mpi_reply->Event);
360
361 if (_ctl_check_event_type(ioc, event)) {
362
363 /* insert entry into circular event_log */
364 i = ioc->event_context % MPT3SAS_CTL_EVENT_LOG_SIZE;
365 event_log = ioc->event_log;
366 event_log[i].event = event;
367 event_log[i].context = ioc->event_context++;
368
369 event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4;
370 sz = min_t(u32, event_data_sz, MPT3_EVENT_DATA_SIZE);
371 memset(event_log[i].data, 0, MPT3_EVENT_DATA_SIZE);
372 memcpy(event_log[i].data, mpi_reply->EventData, sz);
373 send_aen = 1;
374 }
375
376 /* This aen_event_read_flag flag is set until the
377 * application has read the event log.
378 * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify.
379 */
380 if (event == MPI2_EVENT_LOG_ENTRY_ADDED ||
381 (send_aen && !ioc->aen_event_read_flag)) {
382 ioc->aen_event_read_flag = 1;
383 wake_up_interruptible(&ctl_poll_wait);
384 if (async_queue)
385 kill_fasync(&async_queue, SIGIO, POLL_IN);
386 }
387}
388
389/**
390 * mpt3sas_ctl_event_callback - firmware event handler (called at ISR time)
391 * @ioc: per adapter object
392 * @msix_index: MSIX table index supplied by the OS
393 * @reply: reply message frame(lower 32bit addr)
394 * Context: interrupt.
395 *
396 * This function merely adds a new work task into ioc->firmware_event_thread.
397 * The tasks are worked from _firmware_event_work in user context.
398 *
399 * Return 1 meaning mf should be freed from _base_interrupt
400 * 0 means the mf is freed from this function.
401 */
402u8
403mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
404 u32 reply)
405{
406 Mpi2EventNotificationReply_t *mpi_reply;
407
408 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
409 mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
410 return 1;
411}
412
413/**
414 * _ctl_verify_adapter - validates ioc_number passed from application
415 * @ioc: per adapter object
416 * @iocpp: The ioc pointer is returned in this.
417 *
418 * Return (-1) means error, else ioc_number.
419 */
420static int
421_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp)
422{
423 struct MPT3SAS_ADAPTER *ioc;
424
425 list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
426 if (ioc->id != ioc_number)
427 continue;
428 *iocpp = ioc;
429 return ioc_number;
430 }
431 *iocpp = NULL;
432 return -1;
433}
434
435/**
436 * mpt3sas_ctl_reset_handler - reset callback handler (for ctl)
437 * @ioc: per adapter object
438 * @reset_phase: phase
439 *
440 * The handler for doing any required cleanup or initialization.
441 *
442 * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
443 * MPT3_IOC_DONE_RESET
444 */
445void
446mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
447{
448 int i;
449 u8 issue_reset;
450
451 switch (reset_phase) {
452 case MPT3_IOC_PRE_RESET:
453 dtmprintk(ioc, pr_info(MPT3SAS_FMT
454 "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
455 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
456 if (!(ioc->diag_buffer_status[i] &
457 MPT3_DIAG_BUFFER_IS_REGISTERED))
458 continue;
459 if ((ioc->diag_buffer_status[i] &
460 MPT3_DIAG_BUFFER_IS_RELEASED))
461 continue;
462 mpt3sas_send_diag_release(ioc, i, &issue_reset);
463 }
464 break;
465 case MPT3_IOC_AFTER_RESET:
466 dtmprintk(ioc, pr_info(MPT3SAS_FMT
467 "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
468 if (ioc->ctl_cmds.status & MPT3_CMD_PENDING) {
469 ioc->ctl_cmds.status |= MPT3_CMD_RESET;
470 mpt3sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
471 complete(&ioc->ctl_cmds.done);
472 }
473 break;
474 case MPT3_IOC_DONE_RESET:
475 dtmprintk(ioc, pr_info(MPT3SAS_FMT
476 "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
477
478 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
479 if (!(ioc->diag_buffer_status[i] &
480 MPT3_DIAG_BUFFER_IS_REGISTERED))
481 continue;
482 if ((ioc->diag_buffer_status[i] &
483 MPT3_DIAG_BUFFER_IS_RELEASED))
484 continue;
485 ioc->diag_buffer_status[i] |=
486 MPT3_DIAG_BUFFER_IS_DIAG_RESET;
487 }
488 break;
489 }
490}
491
492/**
493 * _ctl_fasync -
494 * @fd -
495 * @filep -
496 * @mode -
497 *
498 * Called when application request fasyn callback handler.
499 */
500static int
501_ctl_fasync(int fd, struct file *filep, int mode)
502{
503 return fasync_helper(fd, filep, mode, &async_queue);
504}
505
506/**
507 * _ctl_release -
508 * @inode -
509 * @filep -
510 *
511 * Called when application releases the fasyn callback handler.
512 */
513static int
514_ctl_release(struct inode *inode, struct file *filep)
515{
516 return fasync_helper(-1, filep, 0, &async_queue);
517}
518
519/**
520 * _ctl_poll -
521 * @file -
522 * @wait -
523 *
524 */
525static unsigned int
526_ctl_poll(struct file *filep, poll_table *wait)
527{
528 struct MPT3SAS_ADAPTER *ioc;
529
530 poll_wait(filep, &ctl_poll_wait, wait);
531
532 list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
533 if (ioc->aen_event_read_flag)
534 return POLLIN | POLLRDNORM;
535 }
536 return 0;
537}
538
539/**
540 * _ctl_set_task_mid - assign an active smid to tm request
541 * @ioc: per adapter object
542 * @karg - (struct mpt3_ioctl_command)
543 * @tm_request - pointer to mf from user space
544 *
545 * Returns 0 when an smid if found, else fail.
546 * during failure, the reply frame is filled.
547 */
548static int
549_ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg,
550 Mpi2SCSITaskManagementRequest_t *tm_request)
551{
552 u8 found = 0;
553 u16 i;
554 u16 handle;
555 struct scsi_cmnd *scmd;
556 struct MPT3SAS_DEVICE *priv_data;
557 unsigned long flags;
558 Mpi2SCSITaskManagementReply_t *tm_reply;
559 u32 sz;
560 u32 lun;
561 char *desc = NULL;
562
563 if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
564 desc = "abort_task";
565 else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK)
566 desc = "query_task";
567 else
568 return 0;
569
570 lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN);
571
572 handle = le16_to_cpu(tm_request->DevHandle);
573 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
574 for (i = ioc->scsiio_depth; i && !found; i--) {
575 scmd = ioc->scsi_lookup[i - 1].scmd;
576 if (scmd == NULL || scmd->device == NULL ||
577 scmd->device->hostdata == NULL)
578 continue;
579 if (lun != scmd->device->lun)
580 continue;
581 priv_data = scmd->device->hostdata;
582 if (priv_data->sas_target == NULL)
583 continue;
584 if (priv_data->sas_target->handle != handle)
585 continue;
586 tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid);
587 found = 1;
588 }
589 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
590
591 if (!found) {
592 dctlprintk(ioc, pr_info(MPT3SAS_FMT
593 "%s: handle(0x%04x), lun(%d), no active mid!!\n",
594 ioc->name,
595 desc, le16_to_cpu(tm_request->DevHandle), lun));
596 tm_reply = ioc->ctl_cmds.reply;
597 tm_reply->DevHandle = tm_request->DevHandle;
598 tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
599 tm_reply->TaskType = tm_request->TaskType;
600 tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4;
601 tm_reply->VP_ID = tm_request->VP_ID;
602 tm_reply->VF_ID = tm_request->VF_ID;
603 sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz);
604 if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply,
605 sz))
606 pr_err("failure at %s:%d/%s()!\n", __FILE__,
607 __LINE__, __func__);
608 return 1;
609 }
610
611 dctlprintk(ioc, pr_info(MPT3SAS_FMT
612 "%s: handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name,
613 desc, le16_to_cpu(tm_request->DevHandle), lun,
614 le16_to_cpu(tm_request->TaskMID)));
615 return 0;
616}
617
618/**
619 * _ctl_do_mpt_command - main handler for MPT3COMMAND opcode
620 * @ioc: per adapter object
621 * @karg - (struct mpt3_ioctl_command)
622 * @mf - pointer to mf in user space
623 */
624static long
625_ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
626 void __user *mf)
627{
628 MPI2RequestHeader_t *mpi_request = NULL, *request;
629 MPI2DefaultReply_t *mpi_reply;
630 u32 ioc_state;
631 u16 ioc_status;
632 u16 smid;
633 unsigned long timeout, timeleft;
634 u8 issue_reset;
635 u32 sz;
636 void *psge;
637 void *data_out = NULL;
638 dma_addr_t data_out_dma = 0;
639 size_t data_out_sz = 0;
640 void *data_in = NULL;
641 dma_addr_t data_in_dma = 0;
642 size_t data_in_sz = 0;
643 long ret;
644 u16 wait_state_count;
645
646 issue_reset = 0;
647
648 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
649 pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n",
650 ioc->name, __func__);
651 ret = -EAGAIN;
652 goto out;
653 }
654
655 wait_state_count = 0;
656 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
657 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
658 if (wait_state_count++ == 10) {
659 pr_err(MPT3SAS_FMT
660 "%s: failed due to ioc not operational\n",
661 ioc->name, __func__);
662 ret = -EFAULT;
663 goto out;
664 }
665 ssleep(1);
666 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
667 pr_info(MPT3SAS_FMT
668 "%s: waiting for operational state(count=%d)\n",
669 ioc->name,
670 __func__, wait_state_count);
671 }
672 if (wait_state_count)
673 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
674 ioc->name, __func__);
675
676 mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL);
677 if (!mpi_request) {
678 pr_err(MPT3SAS_FMT
679 "%s: failed obtaining a memory for mpi_request\n",
680 ioc->name, __func__);
681 ret = -ENOMEM;
682 goto out;
683 }
684
685 /* Check for overflow and wraparound */
686 if (karg.data_sge_offset * 4 > ioc->request_sz ||
687 karg.data_sge_offset > (UINT_MAX / 4)) {
688 ret = -EINVAL;
689 goto out;
690 }
691
692 /* copy in request message frame from user */
693 if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
694 pr_err("failure at %s:%d/%s()!\n", __FILE__, __LINE__,
695 __func__);
696 ret = -EFAULT;
697 goto out;
698 }
699
700 if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
701 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx);
702 if (!smid) {
703 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
704 ioc->name, __func__);
705 ret = -EAGAIN;
706 goto out;
707 }
708 } else {
709
710 smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
711 if (!smid) {
712 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
713 ioc->name, __func__);
714 ret = -EAGAIN;
715 goto out;
716 }
717 }
718
719 ret = 0;
720 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
721 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
722 request = mpt3sas_base_get_msg_frame(ioc, smid);
723 memcpy(request, mpi_request, karg.data_sge_offset*4);
724 ioc->ctl_cmds.smid = smid;
725 data_out_sz = karg.data_out_size;
726 data_in_sz = karg.data_in_size;
727
728 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
729 mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
730 if (!le16_to_cpu(mpi_request->FunctionDependent1) ||
731 le16_to_cpu(mpi_request->FunctionDependent1) >
732 ioc->facts.MaxDevHandle) {
733 ret = -EINVAL;
734 mpt3sas_base_free_smid(ioc, smid);
735 goto out;
736 }
737 }
738
739 /* obtain dma-able memory for data transfer */
740 if (data_out_sz) /* WRITE */ {
741 data_out = pci_alloc_consistent(ioc->pdev, data_out_sz,
742 &data_out_dma);
743 if (!data_out) {
744 pr_err("failure at %s:%d/%s()!\n", __FILE__,
745 __LINE__, __func__);
746 ret = -ENOMEM;
747 mpt3sas_base_free_smid(ioc, smid);
748 goto out;
749 }
750 if (copy_from_user(data_out, karg.data_out_buf_ptr,
751 data_out_sz)) {
752 pr_err("failure at %s:%d/%s()!\n", __FILE__,
753 __LINE__, __func__);
754 ret = -EFAULT;
755 mpt3sas_base_free_smid(ioc, smid);
756 goto out;
757 }
758 }
759
760 if (data_in_sz) /* READ */ {
761 data_in = pci_alloc_consistent(ioc->pdev, data_in_sz,
762 &data_in_dma);
763 if (!data_in) {
764 pr_err("failure at %s:%d/%s()!\n", __FILE__,
765 __LINE__, __func__);
766 ret = -ENOMEM;
767 mpt3sas_base_free_smid(ioc, smid);
768 goto out;
769 }
770 }
771
772 psge = (void *)request + (karg.data_sge_offset*4);
773
774 /* send command to firmware */
775#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
776 _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
777#endif
778
779 init_completion(&ioc->ctl_cmds.done);
780 switch (mpi_request->Function) {
781 case MPI2_FUNCTION_SCSI_IO_REQUEST:
782 case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
783 {
784 Mpi2SCSIIORequest_t *scsiio_request =
785 (Mpi2SCSIIORequest_t *)request;
786 scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
787 scsiio_request->SenseBufferLowAddress =
788 mpt3sas_base_get_sense_buffer_dma(ioc, smid);
789 memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE);
790 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
791 data_in_dma, data_in_sz);
792
793 if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
794 mpt3sas_base_put_smid_scsi_io(ioc, smid,
795 le16_to_cpu(mpi_request->FunctionDependent1));
796 else
797 mpt3sas_base_put_smid_default(ioc, smid);
798 break;
799 }
800 case MPI2_FUNCTION_SCSI_TASK_MGMT:
801 {
802 Mpi2SCSITaskManagementRequest_t *tm_request =
803 (Mpi2SCSITaskManagementRequest_t *)request;
804
805 dtmprintk(ioc, pr_info(MPT3SAS_FMT
806 "TASK_MGMT: handle(0x%04x), task_type(0x%02x)\n",
807 ioc->name,
808 le16_to_cpu(tm_request->DevHandle), tm_request->TaskType));
809
810 if (tm_request->TaskType ==
811 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK ||
812 tm_request->TaskType ==
813 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {
814 if (_ctl_set_task_mid(ioc, &karg, tm_request)) {
815 mpt3sas_base_free_smid(ioc, smid);
816 goto out;
817 }
818 }
819
820 mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu(
821 tm_request->DevHandle));
822 ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
823 data_in_dma, data_in_sz);
824 mpt3sas_base_put_smid_hi_priority(ioc, smid);
825 break;
826 }
827 case MPI2_FUNCTION_SMP_PASSTHROUGH:
828 {
829 Mpi2SmpPassthroughRequest_t *smp_request =
830 (Mpi2SmpPassthroughRequest_t *)mpi_request;
831 u8 *data;
832
833 /* ioc determines which port to use */
834 smp_request->PhysicalPort = 0xFF;
835 if (smp_request->PassthroughFlags &
836 MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
837 data = (u8 *)&smp_request->SGL;
838 else {
839 if (unlikely(data_out == NULL)) {
840 pr_err("failure at %s:%d/%s()!\n",
841 __FILE__, __LINE__, __func__);
842 mpt3sas_base_free_smid(ioc, smid);
843 ret = -EINVAL;
844 goto out;
845 }
846 data = data_out;
847 }
848
849 if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
850 ioc->ioc_link_reset_in_progress = 1;
851 ioc->ignore_loginfos = 1;
852 }
853 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
854 data_in_sz);
855 mpt3sas_base_put_smid_default(ioc, smid);
856 break;
857 }
858 case MPI2_FUNCTION_SATA_PASSTHROUGH:
859 case MPI2_FUNCTION_FW_DOWNLOAD:
860 case MPI2_FUNCTION_FW_UPLOAD:
861 {
862 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
863 data_in_sz);
864 mpt3sas_base_put_smid_default(ioc, smid);
865 break;
866 }
867 case MPI2_FUNCTION_TOOLBOX:
868 {
869 Mpi2ToolboxCleanRequest_t *toolbox_request =
870 (Mpi2ToolboxCleanRequest_t *)mpi_request;
871
872 if (toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL) {
873 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz,
874 data_in_dma, data_in_sz);
875 } else {
876 ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
877 data_in_dma, data_in_sz);
878 }
879 mpt3sas_base_put_smid_default(ioc, smid);
880 break;
881 }
882 case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
883 {
884 Mpi2SasIoUnitControlRequest_t *sasiounit_request =
885 (Mpi2SasIoUnitControlRequest_t *)mpi_request;
886
887 if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET
888 || sasiounit_request->Operation ==
889 MPI2_SAS_OP_PHY_LINK_RESET) {
890 ioc->ioc_link_reset_in_progress = 1;
891 ioc->ignore_loginfos = 1;
892 }
893 /* drop to default case for posting the request */
894 }
895 default:
896 ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
897 data_in_dma, data_in_sz);
898 mpt3sas_base_put_smid_default(ioc, smid);
899 break;
900 }
901
902 if (karg.timeout < MPT3_IOCTL_DEFAULT_TIMEOUT)
903 timeout = MPT3_IOCTL_DEFAULT_TIMEOUT;
904 else
905 timeout = karg.timeout;
906 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
907 timeout*HZ);
908 if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
909 Mpi2SCSITaskManagementRequest_t *tm_request =
910 (Mpi2SCSITaskManagementRequest_t *)mpi_request;
911 mpt3sas_scsih_clear_tm_flag(ioc, le16_to_cpu(
912 tm_request->DevHandle));
913 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
914 } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH ||
915 mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) &&
916 ioc->ioc_link_reset_in_progress) {
917 ioc->ioc_link_reset_in_progress = 0;
918 ioc->ignore_loginfos = 0;
919 }
920 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
921 pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name,
922 __func__);
923 _debug_dump_mf(mpi_request, karg.data_sge_offset);
924 if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET))
925 issue_reset = 1;
926 goto issue_host_reset;
927 }
928
929 mpi_reply = ioc->ctl_cmds.reply;
930 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
931
932#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
933 if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
934 (ioc->logging_level & MPT_DEBUG_TM)) {
935 Mpi2SCSITaskManagementReply_t *tm_reply =
936 (Mpi2SCSITaskManagementReply_t *)mpi_reply;
937
938 pr_info(MPT3SAS_FMT "TASK_MGMT: " \
939 "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
940 "TerminationCount(0x%08x)\n", ioc->name,
941 le16_to_cpu(tm_reply->IOCStatus),
942 le32_to_cpu(tm_reply->IOCLogInfo),
943 le32_to_cpu(tm_reply->TerminationCount));
944 }
945#endif
946 /* copy out xdata to user */
947 if (data_in_sz) {
948 if (copy_to_user(karg.data_in_buf_ptr, data_in,
949 data_in_sz)) {
950 pr_err("failure at %s:%d/%s()!\n", __FILE__,
951 __LINE__, __func__);
952 ret = -ENODATA;
953 goto out;
954 }
955 }
956
957 /* copy out reply message frame to user */
958 if (karg.max_reply_bytes) {
959 sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz);
960 if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply,
961 sz)) {
962 pr_err("failure at %s:%d/%s()!\n", __FILE__,
963 __LINE__, __func__);
964 ret = -ENODATA;
965 goto out;
966 }
967 }
968
969 /* copy out sense to user */
970 if (karg.max_sense_bytes && (mpi_request->Function ==
971 MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
972 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
973 sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
974 if (copy_to_user(karg.sense_data_ptr, ioc->ctl_cmds.sense,
975 sz)) {
976 pr_err("failure at %s:%d/%s()!\n", __FILE__,
977 __LINE__, __func__);
978 ret = -ENODATA;
979 goto out;
980 }
981 }
982
983 issue_host_reset:
984 if (issue_reset) {
985 ret = -ENODATA;
986 if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
987 mpi_request->Function ==
988 MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
989 mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) {
990 pr_info(MPT3SAS_FMT "issue target reset: handle = (0x%04x)\n",
991 ioc->name,
992 le16_to_cpu(mpi_request->FunctionDependent1));
993 mpt3sas_halt_firmware(ioc);
994 mpt3sas_scsih_issue_tm(ioc,
995 le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
996 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30,
997 0, TM_MUTEX_ON);
998 } else
999 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1000 FORCE_BIG_HAMMER);
1001 }
1002
1003 out:
1004
1005 /* free memory associated with sg buffers */
1006 if (data_in)
1007 pci_free_consistent(ioc->pdev, data_in_sz, data_in,
1008 data_in_dma);
1009
1010 if (data_out)
1011 pci_free_consistent(ioc->pdev, data_out_sz, data_out,
1012 data_out_dma);
1013
1014 kfree(mpi_request);
1015 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
1016 return ret;
1017}
1018
1019/**
1020 * _ctl_getiocinfo - main handler for MPT3IOCINFO opcode
1021 * @ioc: per adapter object
1022 * @arg - user space buffer containing ioctl content
1023 */
1024static long
1025_ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1026{
1027 struct mpt3_ioctl_iocinfo karg;
1028
1029 if (copy_from_user(&karg, arg, sizeof(karg))) {
1030 pr_err("failure at %s:%d/%s()!\n",
1031 __FILE__, __LINE__, __func__);
1032 return -EFAULT;
1033 }
1034
1035 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
1036 __func__));
1037
1038 memset(&karg, 0 , sizeof(karg));
1039 karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3;
1040 if (ioc->pfacts)
1041 karg.port_number = ioc->pfacts[0].PortNumber;
1042 karg.hw_rev = ioc->pdev->revision;
1043 karg.pci_id = ioc->pdev->device;
1044 karg.subsystem_device = ioc->pdev->subsystem_device;
1045 karg.subsystem_vendor = ioc->pdev->subsystem_vendor;
1046 karg.pci_information.u.bits.bus = ioc->pdev->bus->number;
1047 karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn);
1048 karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
1049 karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
1050 karg.firmware_version = ioc->facts.FWVersion.Word;
1051 strcpy(karg.driver_version, MPT3SAS_DRIVER_NAME);
1052 strcat(karg.driver_version, "-");
1053 strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION);
1054 karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
1055
1056 if (copy_to_user(arg, &karg, sizeof(karg))) {
1057 pr_err("failure at %s:%d/%s()!\n",
1058 __FILE__, __LINE__, __func__);
1059 return -EFAULT;
1060 }
1061 return 0;
1062}
1063
1064/**
1065 * _ctl_eventquery - main handler for MPT3EVENTQUERY opcode
1066 * @ioc: per adapter object
1067 * @arg - user space buffer containing ioctl content
1068 */
1069static long
1070_ctl_eventquery(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1071{
1072 struct mpt3_ioctl_eventquery karg;
1073
1074 if (copy_from_user(&karg, arg, sizeof(karg))) {
1075 pr_err("failure at %s:%d/%s()!\n",
1076 __FILE__, __LINE__, __func__);
1077 return -EFAULT;
1078 }
1079
1080 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
1081 __func__));
1082
1083 karg.event_entries = MPT3SAS_CTL_EVENT_LOG_SIZE;
1084 memcpy(karg.event_types, ioc->event_type,
1085 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
1086
1087 if (copy_to_user(arg, &karg, sizeof(karg))) {
1088 pr_err("failure at %s:%d/%s()!\n",
1089 __FILE__, __LINE__, __func__);
1090 return -EFAULT;
1091 }
1092 return 0;
1093}
1094
1095/**
1096 * _ctl_eventenable - main handler for MPT3EVENTENABLE opcode
1097 * @ioc: per adapter object
1098 * @arg - user space buffer containing ioctl content
1099 */
1100static long
1101_ctl_eventenable(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1102{
1103 struct mpt3_ioctl_eventenable karg;
1104
1105 if (copy_from_user(&karg, arg, sizeof(karg))) {
1106 pr_err("failure at %s:%d/%s()!\n",
1107 __FILE__, __LINE__, __func__);
1108 return -EFAULT;
1109 }
1110
1111 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
1112 __func__));
1113
1114 memcpy(ioc->event_type, karg.event_types,
1115 MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
1116 mpt3sas_base_validate_event_type(ioc, ioc->event_type);
1117
1118 if (ioc->event_log)
1119 return 0;
1120 /* initialize event_log */
1121 ioc->event_context = 0;
1122 ioc->aen_event_read_flag = 0;
1123 ioc->event_log = kcalloc(MPT3SAS_CTL_EVENT_LOG_SIZE,
1124 sizeof(struct MPT3_IOCTL_EVENTS), GFP_KERNEL);
1125 if (!ioc->event_log) {
1126 pr_err("failure at %s:%d/%s()!\n",
1127 __FILE__, __LINE__, __func__);
1128 return -ENOMEM;
1129 }
1130 return 0;
1131}
1132
1133/**
1134 * _ctl_eventreport - main handler for MPT3EVENTREPORT opcode
1135 * @ioc: per adapter object
1136 * @arg - user space buffer containing ioctl content
1137 */
1138static long
1139_ctl_eventreport(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1140{
1141 struct mpt3_ioctl_eventreport karg;
1142 u32 number_bytes, max_events, max;
1143 struct mpt3_ioctl_eventreport __user *uarg = arg;
1144
1145 if (copy_from_user(&karg, arg, sizeof(karg))) {
1146 pr_err("failure at %s:%d/%s()!\n",
1147 __FILE__, __LINE__, __func__);
1148 return -EFAULT;
1149 }
1150
1151 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
1152 __func__));
1153
1154 number_bytes = karg.hdr.max_data_size -
1155 sizeof(struct mpt3_ioctl_header);
1156 max_events = number_bytes/sizeof(struct MPT3_IOCTL_EVENTS);
1157 max = min_t(u32, MPT3SAS_CTL_EVENT_LOG_SIZE, max_events);
1158
1159 /* If fewer than 1 event is requested, there must have
1160 * been some type of error.
1161 */
1162 if (!max || !ioc->event_log)
1163 return -ENODATA;
1164
1165 number_bytes = max * sizeof(struct MPT3_IOCTL_EVENTS);
1166 if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) {
1167 pr_err("failure at %s:%d/%s()!\n",
1168 __FILE__, __LINE__, __func__);
1169 return -EFAULT;
1170 }
1171
1172 /* reset flag so SIGIO can restart */
1173 ioc->aen_event_read_flag = 0;
1174 return 0;
1175}
1176
1177/**
1178 * _ctl_do_reset - main handler for MPT3HARDRESET opcode
1179 * @ioc: per adapter object
1180 * @arg - user space buffer containing ioctl content
1181 */
1182static long
1183_ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1184{
1185 struct mpt3_ioctl_diag_reset karg;
1186 int retval;
1187
1188 if (copy_from_user(&karg, arg, sizeof(karg))) {
1189 pr_err("failure at %s:%d/%s()!\n",
1190 __FILE__, __LINE__, __func__);
1191 return -EFAULT;
1192 }
1193
1194 if (ioc->shost_recovery || ioc->pci_error_recovery ||
1195 ioc->is_driver_loading)
1196 return -EAGAIN;
1197
1198 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name,
1199 __func__));
1200
1201 retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1202 FORCE_BIG_HAMMER);
1203 pr_info(MPT3SAS_FMT "host reset: %s\n",
1204 ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
1205 return 0;
1206}
1207
1208/**
1209 * _ctl_btdh_search_sas_device - searching for sas device
1210 * @ioc: per adapter object
1211 * @btdh: btdh ioctl payload
1212 */
1213static int
1214_ctl_btdh_search_sas_device(struct MPT3SAS_ADAPTER *ioc,
1215 struct mpt3_ioctl_btdh_mapping *btdh)
1216{
1217 struct _sas_device *sas_device;
1218 unsigned long flags;
1219 int rc = 0;
1220
1221 if (list_empty(&ioc->sas_device_list))
1222 return rc;
1223
1224 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1225 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
1226 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1227 btdh->handle == sas_device->handle) {
1228 btdh->bus = sas_device->channel;
1229 btdh->id = sas_device->id;
1230 rc = 1;
1231 goto out;
1232 } else if (btdh->bus == sas_device->channel && btdh->id ==
1233 sas_device->id && btdh->handle == 0xFFFF) {
1234 btdh->handle = sas_device->handle;
1235 rc = 1;
1236 goto out;
1237 }
1238 }
1239 out:
1240 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1241 return rc;
1242}
1243
1244/**
1245 * _ctl_btdh_search_raid_device - searching for raid device
1246 * @ioc: per adapter object
1247 * @btdh: btdh ioctl payload
1248 */
1249static int
1250_ctl_btdh_search_raid_device(struct MPT3SAS_ADAPTER *ioc,
1251 struct mpt3_ioctl_btdh_mapping *btdh)
1252{
1253 struct _raid_device *raid_device;
1254 unsigned long flags;
1255 int rc = 0;
1256
1257 if (list_empty(&ioc->raid_device_list))
1258 return rc;
1259
1260 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1261 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
1262 if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
1263 btdh->handle == raid_device->handle) {
1264 btdh->bus = raid_device->channel;
1265 btdh->id = raid_device->id;
1266 rc = 1;
1267 goto out;
1268 } else if (btdh->bus == raid_device->channel && btdh->id ==
1269 raid_device->id && btdh->handle == 0xFFFF) {
1270 btdh->handle = raid_device->handle;
1271 rc = 1;
1272 goto out;
1273 }
1274 }
1275 out:
1276 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1277 return rc;
1278}
1279
1280/**
1281 * _ctl_btdh_mapping - main handler for MPT3BTDHMAPPING opcode
1282 * @ioc: per adapter object
1283 * @arg - user space buffer containing ioctl content
1284 */
1285static long
1286_ctl_btdh_mapping(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1287{
1288 struct mpt3_ioctl_btdh_mapping karg;
1289 int rc;
1290
1291 if (copy_from_user(&karg, arg, sizeof(karg))) {
1292 pr_err("failure at %s:%d/%s()!\n",
1293 __FILE__, __LINE__, __func__);
1294 return -EFAULT;
1295 }
1296
1297 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
1298 __func__));
1299
1300 rc = _ctl_btdh_search_sas_device(ioc, &karg);
1301 if (!rc)
1302 _ctl_btdh_search_raid_device(ioc, &karg);
1303
1304 if (copy_to_user(arg, &karg, sizeof(karg))) {
1305 pr_err("failure at %s:%d/%s()!\n",
1306 __FILE__, __LINE__, __func__);
1307 return -EFAULT;
1308 }
1309 return 0;
1310}
1311
1312/**
1313 * _ctl_diag_capability - return diag buffer capability
1314 * @ioc: per adapter object
1315 * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
1316 *
1317 * returns 1 when diag buffer support is enabled in firmware
1318 */
1319static u8
1320_ctl_diag_capability(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type)
1321{
1322 u8 rc = 0;
1323
1324 switch (buffer_type) {
1325 case MPI2_DIAG_BUF_TYPE_TRACE:
1326 if (ioc->facts.IOCCapabilities &
1327 MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
1328 rc = 1;
1329 break;
1330 case MPI2_DIAG_BUF_TYPE_SNAPSHOT:
1331 if (ioc->facts.IOCCapabilities &
1332 MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
1333 rc = 1;
1334 break;
1335 case MPI2_DIAG_BUF_TYPE_EXTENDED:
1336 if (ioc->facts.IOCCapabilities &
1337 MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
1338 rc = 1;
1339 }
1340
1341 return rc;
1342}
1343
1344
1345/**
1346 * _ctl_diag_register_2 - wrapper for registering diag buffer support
1347 * @ioc: per adapter object
1348 * @diag_register: the diag_register struct passed in from user space
1349 *
1350 */
1351static long
1352_ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc,
1353 struct mpt3_diag_register *diag_register)
1354{
1355 int rc, i;
1356 void *request_data = NULL;
1357 dma_addr_t request_data_dma;
1358 u32 request_data_sz = 0;
1359 Mpi2DiagBufferPostRequest_t *mpi_request;
1360 Mpi2DiagBufferPostReply_t *mpi_reply;
1361 u8 buffer_type;
1362 unsigned long timeleft;
1363 u16 smid;
1364 u16 ioc_status;
1365 u32 ioc_state;
1366 u8 issue_reset = 0;
1367
1368 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
1369 __func__));
1370
1371 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1372 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1373 pr_err(MPT3SAS_FMT
1374 "%s: failed due to ioc not operational\n",
1375 ioc->name, __func__);
1376 rc = -EAGAIN;
1377 goto out;
1378 }
1379
1380 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
1381 pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n",
1382 ioc->name, __func__);
1383 rc = -EAGAIN;
1384 goto out;
1385 }
1386
1387 buffer_type = diag_register->buffer_type;
1388 if (!_ctl_diag_capability(ioc, buffer_type)) {
1389 pr_err(MPT3SAS_FMT
1390 "%s: doesn't have capability for buffer_type(0x%02x)\n",
1391 ioc->name, __func__, buffer_type);
1392 return -EPERM;
1393 }
1394
1395 if (ioc->diag_buffer_status[buffer_type] &
1396 MPT3_DIAG_BUFFER_IS_REGISTERED) {
1397 pr_err(MPT3SAS_FMT
1398 "%s: already has a registered buffer for buffer_type(0x%02x)\n",
1399 ioc->name, __func__,
1400 buffer_type);
1401 return -EINVAL;
1402 }
1403
1404 if (diag_register->requested_buffer_size % 4) {
1405 pr_err(MPT3SAS_FMT
1406 "%s: the requested_buffer_size is not 4 byte aligned\n",
1407 ioc->name, __func__);
1408 return -EINVAL;
1409 }
1410
1411 smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1412 if (!smid) {
1413 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1414 ioc->name, __func__);
1415 rc = -EAGAIN;
1416 goto out;
1417 }
1418
1419 rc = 0;
1420 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
1421 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1422 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1423 ioc->ctl_cmds.smid = smid;
1424
1425 request_data = ioc->diag_buffer[buffer_type];
1426 request_data_sz = diag_register->requested_buffer_size;
1427 ioc->unique_id[buffer_type] = diag_register->unique_id;
1428 ioc->diag_buffer_status[buffer_type] = 0;
1429 memcpy(ioc->product_specific[buffer_type],
1430 diag_register->product_specific, MPT3_PRODUCT_SPECIFIC_DWORDS);
1431 ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
1432
1433 if (request_data) {
1434 request_data_dma = ioc->diag_buffer_dma[buffer_type];
1435 if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) {
1436 pci_free_consistent(ioc->pdev,
1437 ioc->diag_buffer_sz[buffer_type],
1438 request_data, request_data_dma);
1439 request_data = NULL;
1440 }
1441 }
1442
1443 if (request_data == NULL) {
1444 ioc->diag_buffer_sz[buffer_type] = 0;
1445 ioc->diag_buffer_dma[buffer_type] = 0;
1446 request_data = pci_alloc_consistent(
1447 ioc->pdev, request_data_sz, &request_data_dma);
1448 if (request_data == NULL) {
1449 pr_err(MPT3SAS_FMT "%s: failed allocating memory" \
1450 " for diag buffers, requested size(%d)\n",
1451 ioc->name, __func__, request_data_sz);
1452 mpt3sas_base_free_smid(ioc, smid);
1453 return -ENOMEM;
1454 }
1455 ioc->diag_buffer[buffer_type] = request_data;
1456 ioc->diag_buffer_sz[buffer_type] = request_data_sz;
1457 ioc->diag_buffer_dma[buffer_type] = request_data_dma;
1458 }
1459
1460 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
1461 mpi_request->BufferType = diag_register->buffer_type;
1462 mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags);
1463 mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
1464 mpi_request->BufferLength = cpu_to_le32(request_data_sz);
1465 mpi_request->VF_ID = 0; /* TODO */
1466 mpi_request->VP_ID = 0;
1467
1468 dctlprintk(ioc, pr_info(MPT3SAS_FMT
1469 "%s: diag_buffer(0x%p), dma(0x%llx), sz(%d)\n",
1470 ioc->name, __func__, request_data,
1471 (unsigned long long)request_data_dma,
1472 le32_to_cpu(mpi_request->BufferLength)));
1473
1474 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
1475 mpi_request->ProductSpecific[i] =
1476 cpu_to_le32(ioc->product_specific[buffer_type][i]);
1477
1478 init_completion(&ioc->ctl_cmds.done);
1479 mpt3sas_base_put_smid_default(ioc, smid);
1480 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
1481 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
1482
1483 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
1484 pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name,
1485 __func__);
1486 _debug_dump_mf(mpi_request,
1487 sizeof(Mpi2DiagBufferPostRequest_t)/4);
1488 if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET))
1489 issue_reset = 1;
1490 goto issue_host_reset;
1491 }
1492
1493 /* process the completed Reply Message Frame */
1494 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
1495 pr_err(MPT3SAS_FMT "%s: no reply message\n",
1496 ioc->name, __func__);
1497 rc = -EFAULT;
1498 goto out;
1499 }
1500
1501 mpi_reply = ioc->ctl_cmds.reply;
1502 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1503
1504 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1505 ioc->diag_buffer_status[buffer_type] |=
1506 MPT3_DIAG_BUFFER_IS_REGISTERED;
1507 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n",
1508 ioc->name, __func__));
1509 } else {
1510 pr_info(MPT3SAS_FMT
1511 "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
1512 ioc->name, __func__,
1513 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
1514 rc = -EFAULT;
1515 }
1516
1517 issue_host_reset:
1518 if (issue_reset)
1519 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1520 FORCE_BIG_HAMMER);
1521
1522 out:
1523
1524 if (rc && request_data)
1525 pci_free_consistent(ioc->pdev, request_data_sz,
1526 request_data, request_data_dma);
1527
1528 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
1529 return rc;
1530}
1531
1532/**
1533 * mpt3sas_enable_diag_buffer - enabling diag_buffers support driver load time
1534 * @ioc: per adapter object
1535 * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
1536 *
1537 * This is called when command line option diag_buffer_enable is enabled
1538 * at driver load time.
1539 */
1540void
1541mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
1542{
1543 struct mpt3_diag_register diag_register;
1544
1545 memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
1546
1547 if (bits_to_register & 1) {
1548 pr_info(MPT3SAS_FMT "registering trace buffer support\n",
1549 ioc->name);
1550 ioc->diag_trigger_master.MasterData =
1551 (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
1552 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
1553 /* register for 2MB buffers */
1554 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1555 diag_register.unique_id = 0x7075900;
1556 _ctl_diag_register_2(ioc, &diag_register);
1557 }
1558
1559 if (bits_to_register & 2) {
1560 pr_info(MPT3SAS_FMT "registering snapshot buffer support\n",
1561 ioc->name);
1562 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
1563 /* register for 2MB buffers */
1564 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1565 diag_register.unique_id = 0x7075901;
1566 _ctl_diag_register_2(ioc, &diag_register);
1567 }
1568
1569 if (bits_to_register & 4) {
1570 pr_info(MPT3SAS_FMT "registering extended buffer support\n",
1571 ioc->name);
1572 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED;
1573 /* register for 2MB buffers */
1574 diag_register.requested_buffer_size = 2 * (1024 * 1024);
1575 diag_register.unique_id = 0x7075901;
1576 _ctl_diag_register_2(ioc, &diag_register);
1577 }
1578}
1579
1580/**
1581 * _ctl_diag_register - application register with driver
1582 * @ioc: per adapter object
1583 * @arg - user space buffer containing ioctl content
1584 *
1585 * This will allow the driver to setup any required buffers that will be
1586 * needed by firmware to communicate with the driver.
1587 */
1588static long
1589_ctl_diag_register(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1590{
1591 struct mpt3_diag_register karg;
1592 long rc;
1593
1594 if (copy_from_user(&karg, arg, sizeof(karg))) {
1595 pr_err("failure at %s:%d/%s()!\n",
1596 __FILE__, __LINE__, __func__);
1597 return -EFAULT;
1598 }
1599
1600 rc = _ctl_diag_register_2(ioc, &karg);
1601 return rc;
1602}
1603
1604/**
1605 * _ctl_diag_unregister - application unregister with driver
1606 * @ioc: per adapter object
1607 * @arg - user space buffer containing ioctl content
1608 *
1609 * This will allow the driver to cleanup any memory allocated for diag
1610 * messages and to free up any resources.
1611 */
1612static long
1613_ctl_diag_unregister(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1614{
1615 struct mpt3_diag_unregister karg;
1616 void *request_data;
1617 dma_addr_t request_data_dma;
1618 u32 request_data_sz;
1619 u8 buffer_type;
1620
1621 if (copy_from_user(&karg, arg, sizeof(karg))) {
1622 pr_err("failure at %s:%d/%s()!\n",
1623 __FILE__, __LINE__, __func__);
1624 return -EFAULT;
1625 }
1626
1627 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
1628 __func__));
1629
1630 buffer_type = karg.unique_id & 0x000000ff;
1631 if (!_ctl_diag_capability(ioc, buffer_type)) {
1632 pr_err(MPT3SAS_FMT
1633 "%s: doesn't have capability for buffer_type(0x%02x)\n",
1634 ioc->name, __func__, buffer_type);
1635 return -EPERM;
1636 }
1637
1638 if ((ioc->diag_buffer_status[buffer_type] &
1639 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
1640 pr_err(MPT3SAS_FMT
1641 "%s: buffer_type(0x%02x) is not registered\n",
1642 ioc->name, __func__, buffer_type);
1643 return -EINVAL;
1644 }
1645 if ((ioc->diag_buffer_status[buffer_type] &
1646 MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
1647 pr_err(MPT3SAS_FMT
1648 "%s: buffer_type(0x%02x) has not been released\n",
1649 ioc->name, __func__, buffer_type);
1650 return -EINVAL;
1651 }
1652
1653 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1654 pr_err(MPT3SAS_FMT
1655 "%s: unique_id(0x%08x) is not registered\n",
1656 ioc->name, __func__, karg.unique_id);
1657 return -EINVAL;
1658 }
1659
1660 request_data = ioc->diag_buffer[buffer_type];
1661 if (!request_data) {
1662 pr_err(MPT3SAS_FMT
1663 "%s: doesn't have memory allocated for buffer_type(0x%02x)\n",
1664 ioc->name, __func__, buffer_type);
1665 return -ENOMEM;
1666 }
1667
1668 request_data_sz = ioc->diag_buffer_sz[buffer_type];
1669 request_data_dma = ioc->diag_buffer_dma[buffer_type];
1670 pci_free_consistent(ioc->pdev, request_data_sz,
1671 request_data, request_data_dma);
1672 ioc->diag_buffer[buffer_type] = NULL;
1673 ioc->diag_buffer_status[buffer_type] = 0;
1674 return 0;
1675}
1676
1677/**
1678 * _ctl_diag_query - query relevant info associated with diag buffers
1679 * @ioc: per adapter object
1680 * @arg - user space buffer containing ioctl content
1681 *
1682 * The application will send only buffer_type and unique_id. Driver will
1683 * inspect unique_id first, if valid, fill in all the info. If unique_id is
1684 * 0x00, the driver will return info specified by Buffer Type.
1685 */
1686static long
1687_ctl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1688{
1689 struct mpt3_diag_query karg;
1690 void *request_data;
1691 int i;
1692 u8 buffer_type;
1693
1694 if (copy_from_user(&karg, arg, sizeof(karg))) {
1695 pr_err("failure at %s:%d/%s()!\n",
1696 __FILE__, __LINE__, __func__);
1697 return -EFAULT;
1698 }
1699
1700 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
1701 __func__));
1702
1703 karg.application_flags = 0;
1704 buffer_type = karg.buffer_type;
1705
1706 if (!_ctl_diag_capability(ioc, buffer_type)) {
1707 pr_err(MPT3SAS_FMT
1708 "%s: doesn't have capability for buffer_type(0x%02x)\n",
1709 ioc->name, __func__, buffer_type);
1710 return -EPERM;
1711 }
1712
1713 if ((ioc->diag_buffer_status[buffer_type] &
1714 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
1715 pr_err(MPT3SAS_FMT
1716 "%s: buffer_type(0x%02x) is not registered\n",
1717 ioc->name, __func__, buffer_type);
1718 return -EINVAL;
1719 }
1720
1721 if (karg.unique_id & 0xffffff00) {
1722 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1723 pr_err(MPT3SAS_FMT
1724 "%s: unique_id(0x%08x) is not registered\n",
1725 ioc->name, __func__, karg.unique_id);
1726 return -EINVAL;
1727 }
1728 }
1729
1730 request_data = ioc->diag_buffer[buffer_type];
1731 if (!request_data) {
1732 pr_err(MPT3SAS_FMT
1733 "%s: doesn't have buffer for buffer_type(0x%02x)\n",
1734 ioc->name, __func__, buffer_type);
1735 return -ENOMEM;
1736 }
1737
1738 if (ioc->diag_buffer_status[buffer_type] & MPT3_DIAG_BUFFER_IS_RELEASED)
1739 karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
1740 MPT3_APP_FLAGS_BUFFER_VALID);
1741 else
1742 karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
1743 MPT3_APP_FLAGS_BUFFER_VALID |
1744 MPT3_APP_FLAGS_FW_BUFFER_ACCESS);
1745
1746 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
1747 karg.product_specific[i] =
1748 ioc->product_specific[buffer_type][i];
1749
1750 karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
1751 karg.driver_added_buffer_size = 0;
1752 karg.unique_id = ioc->unique_id[buffer_type];
1753 karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
1754
1755 if (copy_to_user(arg, &karg, sizeof(struct mpt3_diag_query))) {
1756 pr_err(MPT3SAS_FMT
1757 "%s: unable to write mpt3_diag_query data @ %p\n",
1758 ioc->name, __func__, arg);
1759 return -EFAULT;
1760 }
1761 return 0;
1762}
1763
1764/**
1765 * mpt3sas_send_diag_release - Diag Release Message
1766 * @ioc: per adapter object
1767 * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
1768 * @issue_reset - specifies whether host reset is required.
1769 *
1770 */
1771int
1772mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
1773 u8 *issue_reset)
1774{
1775 Mpi2DiagReleaseRequest_t *mpi_request;
1776 Mpi2DiagReleaseReply_t *mpi_reply;
1777 u16 smid;
1778 u16 ioc_status;
1779 u32 ioc_state;
1780 int rc;
1781 unsigned long timeleft;
1782
1783 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
1784 __func__));
1785
1786 rc = 0;
1787 *issue_reset = 0;
1788
1789 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1790 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1791 if (ioc->diag_buffer_status[buffer_type] &
1792 MPT3_DIAG_BUFFER_IS_REGISTERED)
1793 ioc->diag_buffer_status[buffer_type] |=
1794 MPT3_DIAG_BUFFER_IS_RELEASED;
1795 dctlprintk(ioc, pr_info(MPT3SAS_FMT
1796 "%s: skipping due to FAULT state\n", ioc->name,
1797 __func__));
1798 rc = -EAGAIN;
1799 goto out;
1800 }
1801
1802 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
1803 pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n",
1804 ioc->name, __func__);
1805 rc = -EAGAIN;
1806 goto out;
1807 }
1808
1809 smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
1810 if (!smid) {
1811 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1812 ioc->name, __func__);
1813 rc = -EAGAIN;
1814 goto out;
1815 }
1816
1817 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
1818 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
1819 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1820 ioc->ctl_cmds.smid = smid;
1821
1822 mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
1823 mpi_request->BufferType = buffer_type;
1824 mpi_request->VF_ID = 0; /* TODO */
1825 mpi_request->VP_ID = 0;
1826
1827 init_completion(&ioc->ctl_cmds.done);
1828 mpt3sas_base_put_smid_default(ioc, smid);
1829 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
1830 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
1831
1832 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
1833 pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name,
1834 __func__);
1835 _debug_dump_mf(mpi_request,
1836 sizeof(Mpi2DiagReleaseRequest_t)/4);
1837 if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET))
1838 *issue_reset = 1;
1839 rc = -EFAULT;
1840 goto out;
1841 }
1842
1843 /* process the completed Reply Message Frame */
1844 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
1845 pr_err(MPT3SAS_FMT "%s: no reply message\n",
1846 ioc->name, __func__);
1847 rc = -EFAULT;
1848 goto out;
1849 }
1850
1851 mpi_reply = ioc->ctl_cmds.reply;
1852 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1853
1854 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
1855 ioc->diag_buffer_status[buffer_type] |=
1856 MPT3_DIAG_BUFFER_IS_RELEASED;
1857 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n",
1858 ioc->name, __func__));
1859 } else {
1860 pr_info(MPT3SAS_FMT
1861 "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
1862 ioc->name, __func__,
1863 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
1864 rc = -EFAULT;
1865 }
1866
1867 out:
1868 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
1869 return rc;
1870}
1871
1872/**
1873 * _ctl_diag_release - request to send Diag Release Message to firmware
1874 * @arg - user space buffer containing ioctl content
1875 *
1876 * This allows ownership of the specified buffer to returned to the driver,
1877 * allowing an application to read the buffer without fear that firmware is
1878 * overwritting information in the buffer.
1879 */
1880static long
1881_ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1882{
1883 struct mpt3_diag_release karg;
1884 void *request_data;
1885 int rc;
1886 u8 buffer_type;
1887 u8 issue_reset = 0;
1888
1889 if (copy_from_user(&karg, arg, sizeof(karg))) {
1890 pr_err("failure at %s:%d/%s()!\n",
1891 __FILE__, __LINE__, __func__);
1892 return -EFAULT;
1893 }
1894
1895 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
1896 __func__));
1897
1898 buffer_type = karg.unique_id & 0x000000ff;
1899 if (!_ctl_diag_capability(ioc, buffer_type)) {
1900 pr_err(MPT3SAS_FMT
1901 "%s: doesn't have capability for buffer_type(0x%02x)\n",
1902 ioc->name, __func__, buffer_type);
1903 return -EPERM;
1904 }
1905
1906 if ((ioc->diag_buffer_status[buffer_type] &
1907 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
1908 pr_err(MPT3SAS_FMT
1909 "%s: buffer_type(0x%02x) is not registered\n",
1910 ioc->name, __func__, buffer_type);
1911 return -EINVAL;
1912 }
1913
1914 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1915 pr_err(MPT3SAS_FMT
1916 "%s: unique_id(0x%08x) is not registered\n",
1917 ioc->name, __func__, karg.unique_id);
1918 return -EINVAL;
1919 }
1920
1921 if (ioc->diag_buffer_status[buffer_type] &
1922 MPT3_DIAG_BUFFER_IS_RELEASED) {
1923 pr_err(MPT3SAS_FMT
1924 "%s: buffer_type(0x%02x) is already released\n",
1925 ioc->name, __func__,
1926 buffer_type);
1927 return 0;
1928 }
1929
1930 request_data = ioc->diag_buffer[buffer_type];
1931
1932 if (!request_data) {
1933 pr_err(MPT3SAS_FMT
1934 "%s: doesn't have memory allocated for buffer_type(0x%02x)\n",
1935 ioc->name, __func__, buffer_type);
1936 return -ENOMEM;
1937 }
1938
1939 /* buffers were released by due to host reset */
1940 if ((ioc->diag_buffer_status[buffer_type] &
1941 MPT3_DIAG_BUFFER_IS_DIAG_RESET)) {
1942 ioc->diag_buffer_status[buffer_type] |=
1943 MPT3_DIAG_BUFFER_IS_RELEASED;
1944 ioc->diag_buffer_status[buffer_type] &=
1945 ~MPT3_DIAG_BUFFER_IS_DIAG_RESET;
1946 pr_err(MPT3SAS_FMT
1947 "%s: buffer_type(0x%02x) was released due to host reset\n",
1948 ioc->name, __func__, buffer_type);
1949 return 0;
1950 }
1951
1952 rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset);
1953
1954 if (issue_reset)
1955 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1956 FORCE_BIG_HAMMER);
1957
1958 return rc;
1959}
1960
1961/**
1962 * _ctl_diag_read_buffer - request for copy of the diag buffer
1963 * @ioc: per adapter object
1964 * @arg - user space buffer containing ioctl content
1965 */
1966static long
1967_ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
1968{
1969 struct mpt3_diag_read_buffer karg;
1970 struct mpt3_diag_read_buffer __user *uarg = arg;
1971 void *request_data, *diag_data;
1972 Mpi2DiagBufferPostRequest_t *mpi_request;
1973 Mpi2DiagBufferPostReply_t *mpi_reply;
1974 int rc, i;
1975 u8 buffer_type;
1976 unsigned long timeleft, request_size, copy_size;
1977 u16 smid;
1978 u16 ioc_status;
1979 u8 issue_reset = 0;
1980
1981 if (copy_from_user(&karg, arg, sizeof(karg))) {
1982 pr_err("failure at %s:%d/%s()!\n",
1983 __FILE__, __LINE__, __func__);
1984 return -EFAULT;
1985 }
1986
1987 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
1988 __func__));
1989
1990 buffer_type = karg.unique_id & 0x000000ff;
1991 if (!_ctl_diag_capability(ioc, buffer_type)) {
1992 pr_err(MPT3SAS_FMT
1993 "%s: doesn't have capability for buffer_type(0x%02x)\n",
1994 ioc->name, __func__, buffer_type);
1995 return -EPERM;
1996 }
1997
1998 if (karg.unique_id != ioc->unique_id[buffer_type]) {
1999 pr_err(MPT3SAS_FMT
2000 "%s: unique_id(0x%08x) is not registered\n",
2001 ioc->name, __func__, karg.unique_id);
2002 return -EINVAL;
2003 }
2004
2005 request_data = ioc->diag_buffer[buffer_type];
2006 if (!request_data) {
2007 pr_err(MPT3SAS_FMT
2008 "%s: doesn't have buffer for buffer_type(0x%02x)\n",
2009 ioc->name, __func__, buffer_type);
2010 return -ENOMEM;
2011 }
2012
2013 request_size = ioc->diag_buffer_sz[buffer_type];
2014
2015 if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
2016 pr_err(MPT3SAS_FMT "%s: either the starting_offset " \
2017 "or bytes_to_read are not 4 byte aligned\n", ioc->name,
2018 __func__);
2019 return -EINVAL;
2020 }
2021
2022 if (karg.starting_offset > request_size)
2023 return -EINVAL;
2024
2025 diag_data = (void *)(request_data + karg.starting_offset);
2026 dctlprintk(ioc, pr_info(MPT3SAS_FMT
2027 "%s: diag_buffer(%p), offset(%d), sz(%d)\n",
2028 ioc->name, __func__,
2029 diag_data, karg.starting_offset, karg.bytes_to_read));
2030
2031 /* Truncate data on requests that are too large */
2032 if ((diag_data + karg.bytes_to_read < diag_data) ||
2033 (diag_data + karg.bytes_to_read > request_data + request_size))
2034 copy_size = request_size - karg.starting_offset;
2035 else
2036 copy_size = karg.bytes_to_read;
2037
2038 if (copy_to_user((void __user *)uarg->diagnostic_data,
2039 diag_data, copy_size)) {
2040 pr_err(MPT3SAS_FMT
2041 "%s: Unable to write mpt_diag_read_buffer_t data @ %p\n",
2042 ioc->name, __func__, diag_data);
2043 return -EFAULT;
2044 }
2045
2046 if ((karg.flags & MPT3_FLAGS_REREGISTER) == 0)
2047 return 0;
2048
2049 dctlprintk(ioc, pr_info(MPT3SAS_FMT
2050 "%s: Reregister buffer_type(0x%02x)\n",
2051 ioc->name, __func__, buffer_type));
2052 if ((ioc->diag_buffer_status[buffer_type] &
2053 MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
2054 dctlprintk(ioc, pr_info(MPT3SAS_FMT
2055 "%s: buffer_type(0x%02x) is still registered\n",
2056 ioc->name, __func__, buffer_type));
2057 return 0;
2058 }
2059 /* Get a free request frame and save the message context.
2060 */
2061
2062 if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) {
2063 pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n",
2064 ioc->name, __func__);
2065 rc = -EAGAIN;
2066 goto out;
2067 }
2068
2069 smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx);
2070 if (!smid) {
2071 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2072 ioc->name, __func__);
2073 rc = -EAGAIN;
2074 goto out;
2075 }
2076
2077 rc = 0;
2078 ioc->ctl_cmds.status = MPT3_CMD_PENDING;
2079 memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
2080 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2081 ioc->ctl_cmds.smid = smid;
2082
2083 mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
2084 mpi_request->BufferType = buffer_type;
2085 mpi_request->BufferLength =
2086 cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
2087 mpi_request->BufferAddress =
2088 cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
2089 for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
2090 mpi_request->ProductSpecific[i] =
2091 cpu_to_le32(ioc->product_specific[buffer_type][i]);
2092 mpi_request->VF_ID = 0; /* TODO */
2093 mpi_request->VP_ID = 0;
2094
2095 init_completion(&ioc->ctl_cmds.done);
2096 mpt3sas_base_put_smid_default(ioc, smid);
2097 timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
2098 MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
2099
2100 if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
2101 pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name,
2102 __func__);
2103 _debug_dump_mf(mpi_request,
2104 sizeof(Mpi2DiagBufferPostRequest_t)/4);
2105 if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET))
2106 issue_reset = 1;
2107 goto issue_host_reset;
2108 }
2109
2110 /* process the completed Reply Message Frame */
2111 if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) {
2112 pr_err(MPT3SAS_FMT "%s: no reply message\n",
2113 ioc->name, __func__);
2114 rc = -EFAULT;
2115 goto out;
2116 }
2117
2118 mpi_reply = ioc->ctl_cmds.reply;
2119 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
2120
2121 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
2122 ioc->diag_buffer_status[buffer_type] |=
2123 MPT3_DIAG_BUFFER_IS_REGISTERED;
2124 dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n",
2125 ioc->name, __func__));
2126 } else {
2127 pr_info(MPT3SAS_FMT
2128 "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
2129 ioc->name, __func__,
2130 ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
2131 rc = -EFAULT;
2132 }
2133
2134 issue_host_reset:
2135 if (issue_reset)
2136 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2137 FORCE_BIG_HAMMER);
2138
2139 out:
2140
2141 ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
2142 return rc;
2143}
2144
2145
2146
2147#ifdef CONFIG_COMPAT
2148/**
2149 * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
2150 * @ioc: per adapter object
2151 * @cmd - ioctl opcode
2152 * @arg - (struct mpt3_ioctl_command32)
2153 *
2154 * MPT3COMMAND32 - Handle 32bit applications running on 64bit os.
2155 */
2156static long
2157_ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd,
2158 void __user *arg)
2159{
2160 struct mpt3_ioctl_command32 karg32;
2161 struct mpt3_ioctl_command32 __user *uarg;
2162 struct mpt3_ioctl_command karg;
2163
2164 if (_IOC_SIZE(cmd) != sizeof(struct mpt3_ioctl_command32))
2165 return -EINVAL;
2166
2167 uarg = (struct mpt3_ioctl_command32 __user *) arg;
2168
2169 if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
2170 pr_err("failure at %s:%d/%s()!\n",
2171 __FILE__, __LINE__, __func__);
2172 return -EFAULT;
2173 }
2174
2175 memset(&karg, 0, sizeof(struct mpt3_ioctl_command));
2176 karg.hdr.ioc_number = karg32.hdr.ioc_number;
2177 karg.hdr.port_number = karg32.hdr.port_number;
2178 karg.hdr.max_data_size = karg32.hdr.max_data_size;
2179 karg.timeout = karg32.timeout;
2180 karg.max_reply_bytes = karg32.max_reply_bytes;
2181 karg.data_in_size = karg32.data_in_size;
2182 karg.data_out_size = karg32.data_out_size;
2183 karg.max_sense_bytes = karg32.max_sense_bytes;
2184 karg.data_sge_offset = karg32.data_sge_offset;
2185 karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
2186 karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
2187 karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
2188 karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
2189 return _ctl_do_mpt_command(ioc, karg, &uarg->mf);
2190}
2191#endif
2192
2193/**
2194 * _ctl_ioctl_main - main ioctl entry point
2195 * @file - (struct file)
2196 * @cmd - ioctl opcode
2197 * @arg -
2198 * compat - handles 32 bit applications in 64bit os
2199 */
2200static long
2201_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
2202 u8 compat)
2203{
2204 struct MPT3SAS_ADAPTER *ioc;
2205 struct mpt3_ioctl_header ioctl_header;
2206 enum block_state state;
2207 long ret = -EINVAL;
2208
2209 /* get IOCTL header */
2210 if (copy_from_user(&ioctl_header, (char __user *)arg,
2211 sizeof(struct mpt3_ioctl_header))) {
2212 pr_err("failure at %s:%d/%s()!\n",
2213 __FILE__, __LINE__, __func__);
2214 return -EFAULT;
2215 }
2216
2217 if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc)
2218 return -ENODEV;
2219
2220 if (ioc->shost_recovery || ioc->pci_error_recovery ||
2221 ioc->is_driver_loading)
2222 return -EAGAIN;
2223
2224 state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
2225 if (state == NON_BLOCKING) {
2226 if (!mutex_trylock(&ioc->ctl_cmds.mutex))
2227 return -EAGAIN;
2228 } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
2229 return -ERESTARTSYS;
2230
2231
2232 switch (cmd) {
2233 case MPT3IOCINFO:
2234 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_iocinfo))
2235 ret = _ctl_getiocinfo(ioc, arg);
2236 break;
2237#ifdef CONFIG_COMPAT
2238 case MPT3COMMAND32:
2239#endif
2240 case MPT3COMMAND:
2241 {
2242 struct mpt3_ioctl_command __user *uarg;
2243 struct mpt3_ioctl_command karg;
2244
2245#ifdef CONFIG_COMPAT
2246 if (compat) {
2247 ret = _ctl_compat_mpt_command(ioc, cmd, arg);
2248 break;
2249 }
2250#endif
2251 if (copy_from_user(&karg, arg, sizeof(karg))) {
2252 pr_err("failure at %s:%d/%s()!\n",
2253 __FILE__, __LINE__, __func__);
2254 ret = -EFAULT;
2255 break;
2256 }
2257
2258 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_command)) {
2259 uarg = arg;
2260 ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf);
2261 }
2262 break;
2263 }
2264 case MPT3EVENTQUERY:
2265 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventquery))
2266 ret = _ctl_eventquery(ioc, arg);
2267 break;
2268 case MPT3EVENTENABLE:
2269 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventenable))
2270 ret = _ctl_eventenable(ioc, arg);
2271 break;
2272 case MPT3EVENTREPORT:
2273 ret = _ctl_eventreport(ioc, arg);
2274 break;
2275 case MPT3HARDRESET:
2276 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_diag_reset))
2277 ret = _ctl_do_reset(ioc, arg);
2278 break;
2279 case MPT3BTDHMAPPING:
2280 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_btdh_mapping))
2281 ret = _ctl_btdh_mapping(ioc, arg);
2282 break;
2283 case MPT3DIAGREGISTER:
2284 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_register))
2285 ret = _ctl_diag_register(ioc, arg);
2286 break;
2287 case MPT3DIAGUNREGISTER:
2288 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_unregister))
2289 ret = _ctl_diag_unregister(ioc, arg);
2290 break;
2291 case MPT3DIAGQUERY:
2292 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_query))
2293 ret = _ctl_diag_query(ioc, arg);
2294 break;
2295 case MPT3DIAGRELEASE:
2296 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_release))
2297 ret = _ctl_diag_release(ioc, arg);
2298 break;
2299 case MPT3DIAGREADBUFFER:
2300 if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer))
2301 ret = _ctl_diag_read_buffer(ioc, arg);
2302 break;
2303 default:
2304 dctlprintk(ioc, pr_info(MPT3SAS_FMT
2305 "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
2306 break;
2307 }
2308
2309 mutex_unlock(&ioc->ctl_cmds.mutex);
2310 return ret;
2311}
2312
2313/**
2314 * _ctl_ioctl - main ioctl entry point (unlocked)
2315 * @file - (struct file)
2316 * @cmd - ioctl opcode
2317 * @arg -
2318 */
2319static long
2320_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2321{
2322 long ret;
2323
2324 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0);
2325 return ret;
2326}
2327
2328#ifdef CONFIG_COMPAT
2329/**
2330 * _ctl_ioctl_compat - main ioctl entry point (compat)
2331 * @file -
2332 * @cmd -
2333 * @arg -
2334 *
2335 * This routine handles 32 bit applications in 64bit os.
2336 */
2337static long
2338_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
2339{
2340 long ret;
2341
2342 ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1);
2343 return ret;
2344}
2345#endif
2346
2347/* scsi host attributes */
2348/**
2349 * _ctl_version_fw_show - firmware version
2350 * @cdev - pointer to embedded class device
2351 * @buf - the buffer returned
2352 *
2353 * A sysfs 'read-only' shost attribute.
2354 */
2355static ssize_t
2356_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr,
2357 char *buf)
2358{
2359 struct Scsi_Host *shost = class_to_shost(cdev);
2360 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2361
2362 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2363 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
2364 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
2365 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
2366 ioc->facts.FWVersion.Word & 0x000000FF);
2367}
2368static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL);
2369
2370/**
2371 * _ctl_version_bios_show - bios version
2372 * @cdev - pointer to embedded class device
2373 * @buf - the buffer returned
2374 *
2375 * A sysfs 'read-only' shost attribute.
2376 */
2377static ssize_t
2378_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr,
2379 char *buf)
2380{
2381 struct Scsi_Host *shost = class_to_shost(cdev);
2382 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2383
2384 u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
2385
2386 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
2387 (version & 0xFF000000) >> 24,
2388 (version & 0x00FF0000) >> 16,
2389 (version & 0x0000FF00) >> 8,
2390 version & 0x000000FF);
2391}
2392static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL);
2393
2394/**
2395 * _ctl_version_mpi_show - MPI (message passing interface) version
2396 * @cdev - pointer to embedded class device
2397 * @buf - the buffer returned
2398 *
2399 * A sysfs 'read-only' shost attribute.
2400 */
2401static ssize_t
2402_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr,
2403 char *buf)
2404{
2405 struct Scsi_Host *shost = class_to_shost(cdev);
2406 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2407
2408 return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
2409 ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
2410}
2411static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL);
2412
2413/**
2414 * _ctl_version_product_show - product name
2415 * @cdev - pointer to embedded class device
2416 * @buf - the buffer returned
2417 *
2418 * A sysfs 'read-only' shost attribute.
2419 */
2420static ssize_t
2421_ctl_version_product_show(struct device *cdev, struct device_attribute *attr,
2422 char *buf)
2423{
2424 struct Scsi_Host *shost = class_to_shost(cdev);
2425 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2426
2427 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
2428}
2429static DEVICE_ATTR(version_product, S_IRUGO, _ctl_version_product_show, NULL);
2430
2431/**
2432 * _ctl_version_nvdata_persistent_show - ndvata persistent version
2433 * @cdev - pointer to embedded class device
2434 * @buf - the buffer returned
2435 *
2436 * A sysfs 'read-only' shost attribute.
2437 */
2438static ssize_t
2439_ctl_version_nvdata_persistent_show(struct device *cdev,
2440 struct device_attribute *attr, char *buf)
2441{
2442 struct Scsi_Host *shost = class_to_shost(cdev);
2443 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2444
2445 return snprintf(buf, PAGE_SIZE, "%08xh\n",
2446 le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
2447}
2448static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
2449 _ctl_version_nvdata_persistent_show, NULL);
2450
2451/**
2452 * _ctl_version_nvdata_default_show - nvdata default version
2453 * @cdev - pointer to embedded class device
2454 * @buf - the buffer returned
2455 *
2456 * A sysfs 'read-only' shost attribute.
2457 */
2458static ssize_t
2459_ctl_version_nvdata_default_show(struct device *cdev, struct device_attribute
2460 *attr, char *buf)
2461{
2462 struct Scsi_Host *shost = class_to_shost(cdev);
2463 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2464
2465 return snprintf(buf, PAGE_SIZE, "%08xh\n",
2466 le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
2467}
2468static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
2469 _ctl_version_nvdata_default_show, NULL);
2470
2471/**
2472 * _ctl_board_name_show - board name
2473 * @cdev - pointer to embedded class device
2474 * @buf - the buffer returned
2475 *
2476 * A sysfs 'read-only' shost attribute.
2477 */
2478static ssize_t
2479_ctl_board_name_show(struct device *cdev, struct device_attribute *attr,
2480 char *buf)
2481{
2482 struct Scsi_Host *shost = class_to_shost(cdev);
2483 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2484
2485 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
2486}
2487static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL);
2488
2489/**
2490 * _ctl_board_assembly_show - board assembly name
2491 * @cdev - pointer to embedded class device
2492 * @buf - the buffer returned
2493 *
2494 * A sysfs 'read-only' shost attribute.
2495 */
2496static ssize_t
2497_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr,
2498 char *buf)
2499{
2500 struct Scsi_Host *shost = class_to_shost(cdev);
2501 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2502
2503 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
2504}
2505static DEVICE_ATTR(board_assembly, S_IRUGO, _ctl_board_assembly_show, NULL);
2506
2507/**
2508 * _ctl_board_tracer_show - board tracer number
2509 * @cdev - pointer to embedded class device
2510 * @buf - the buffer returned
2511 *
2512 * A sysfs 'read-only' shost attribute.
2513 */
2514static ssize_t
2515_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr,
2516 char *buf)
2517{
2518 struct Scsi_Host *shost = class_to_shost(cdev);
2519 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2520
2521 return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
2522}
2523static DEVICE_ATTR(board_tracer, S_IRUGO, _ctl_board_tracer_show, NULL);
2524
2525/**
2526 * _ctl_io_delay_show - io missing delay
2527 * @cdev - pointer to embedded class device
2528 * @buf - the buffer returned
2529 *
2530 * This is for firmware implemention for deboucing device
2531 * removal events.
2532 *
2533 * A sysfs 'read-only' shost attribute.
2534 */
2535static ssize_t
2536_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr,
2537 char *buf)
2538{
2539 struct Scsi_Host *shost = class_to_shost(cdev);
2540 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2541
2542 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
2543}
2544static DEVICE_ATTR(io_delay, S_IRUGO, _ctl_io_delay_show, NULL);
2545
2546/**
2547 * _ctl_device_delay_show - device missing delay
2548 * @cdev - pointer to embedded class device
2549 * @buf - the buffer returned
2550 *
2551 * This is for firmware implemention for deboucing device
2552 * removal events.
2553 *
2554 * A sysfs 'read-only' shost attribute.
2555 */
2556static ssize_t
2557_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr,
2558 char *buf)
2559{
2560 struct Scsi_Host *shost = class_to_shost(cdev);
2561 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2562
2563 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
2564}
2565static DEVICE_ATTR(device_delay, S_IRUGO, _ctl_device_delay_show, NULL);
2566
2567/**
2568 * _ctl_fw_queue_depth_show - global credits
2569 * @cdev - pointer to embedded class device
2570 * @buf - the buffer returned
2571 *
2572 * This is firmware queue depth limit
2573 *
2574 * A sysfs 'read-only' shost attribute.
2575 */
2576static ssize_t
2577_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
2578 char *buf)
2579{
2580 struct Scsi_Host *shost = class_to_shost(cdev);
2581 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2582
2583 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
2584}
2585static DEVICE_ATTR(fw_queue_depth, S_IRUGO, _ctl_fw_queue_depth_show, NULL);
2586
2587/**
2588 * _ctl_sas_address_show - sas address
2589 * @cdev - pointer to embedded class device
2590 * @buf - the buffer returned
2591 *
2592 * This is the controller sas address
2593 *
2594 * A sysfs 'read-only' shost attribute.
2595 */
2596static ssize_t
2597_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr,
2598 char *buf)
2599
2600{
2601 struct Scsi_Host *shost = class_to_shost(cdev);
2602 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2603
2604 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
2605 (unsigned long long)ioc->sas_hba.sas_address);
2606}
2607static DEVICE_ATTR(host_sas_address, S_IRUGO,
2608 _ctl_host_sas_address_show, NULL);
2609
2610/**
2611 * _ctl_logging_level_show - logging level
2612 * @cdev - pointer to embedded class device
2613 * @buf - the buffer returned
2614 *
2615 * A sysfs 'read/write' shost attribute.
2616 */
2617static ssize_t
2618_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr,
2619 char *buf)
2620{
2621 struct Scsi_Host *shost = class_to_shost(cdev);
2622 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2623
2624 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
2625}
2626static ssize_t
2627_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
2628 const char *buf, size_t count)
2629{
2630 struct Scsi_Host *shost = class_to_shost(cdev);
2631 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2632 int val = 0;
2633
2634 if (sscanf(buf, "%x", &val) != 1)
2635 return -EINVAL;
2636
2637 ioc->logging_level = val;
2638 pr_info(MPT3SAS_FMT "logging_level=%08xh\n", ioc->name,
2639 ioc->logging_level);
2640 return strlen(buf);
2641}
2642static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, _ctl_logging_level_show,
2643 _ctl_logging_level_store);
2644
2645/**
2646 * _ctl_fwfault_debug_show - show/store fwfault_debug
2647 * @cdev - pointer to embedded class device
2648 * @buf - the buffer returned
2649 *
2650 * mpt3sas_fwfault_debug is command line option
2651 * A sysfs 'read/write' shost attribute.
2652 */
2653static ssize_t
2654_ctl_fwfault_debug_show(struct device *cdev, struct device_attribute *attr,
2655 char *buf)
2656{
2657 struct Scsi_Host *shost = class_to_shost(cdev);
2658 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2659
2660 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug);
2661}
2662static ssize_t
2663_ctl_fwfault_debug_store(struct device *cdev, struct device_attribute *attr,
2664 const char *buf, size_t count)
2665{
2666 struct Scsi_Host *shost = class_to_shost(cdev);
2667 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2668 int val = 0;
2669
2670 if (sscanf(buf, "%d", &val) != 1)
2671 return -EINVAL;
2672
2673 ioc->fwfault_debug = val;
2674 pr_info(MPT3SAS_FMT "fwfault_debug=%d\n", ioc->name,
2675 ioc->fwfault_debug);
2676 return strlen(buf);
2677}
2678static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR,
2679 _ctl_fwfault_debug_show, _ctl_fwfault_debug_store);
2680
2681/**
2682 * _ctl_ioc_reset_count_show - ioc reset count
2683 * @cdev - pointer to embedded class device
2684 * @buf - the buffer returned
2685 *
2686 * This is firmware queue depth limit
2687 *
2688 * A sysfs 'read-only' shost attribute.
2689 */
2690static ssize_t
2691_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
2692 char *buf)
2693{
2694 struct Scsi_Host *shost = class_to_shost(cdev);
2695 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2696
2697 return snprintf(buf, PAGE_SIZE, "%d\n", ioc->ioc_reset_count);
2698}
2699static DEVICE_ATTR(ioc_reset_count, S_IRUGO, _ctl_ioc_reset_count_show, NULL);
2700
2701/**
2702 * _ctl_ioc_reply_queue_count_show - number of reply queues
2703 * @cdev - pointer to embedded class device
2704 * @buf - the buffer returned
2705 *
2706 * This is number of reply queues
2707 *
2708 * A sysfs 'read-only' shost attribute.
2709 */
2710static ssize_t
2711_ctl_ioc_reply_queue_count_show(struct device *cdev,
2712 struct device_attribute *attr, char *buf)
2713{
2714 u8 reply_queue_count;
2715 struct Scsi_Host *shost = class_to_shost(cdev);
2716 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2717
2718 if ((ioc->facts.IOCCapabilities &
2719 MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable)
2720 reply_queue_count = ioc->reply_queue_count;
2721 else
2722 reply_queue_count = 1;
2723
2724 return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count);
2725}
2726static DEVICE_ATTR(reply_queue_count, S_IRUGO, _ctl_ioc_reply_queue_count_show,
2727 NULL);
2728
2729struct DIAG_BUFFER_START {
2730 __le32 Size;
2731 __le32 DiagVersion;
2732 u8 BufferType;
2733 u8 Reserved[3];
2734 __le32 Reserved1;
2735 __le32 Reserved2;
2736 __le32 Reserved3;
2737};
2738
2739/**
2740 * _ctl_host_trace_buffer_size_show - host buffer size (trace only)
2741 * @cdev - pointer to embedded class device
2742 * @buf - the buffer returned
2743 *
2744 * A sysfs 'read-only' shost attribute.
2745 */
2746static ssize_t
2747_ctl_host_trace_buffer_size_show(struct device *cdev,
2748 struct device_attribute *attr, char *buf)
2749{
2750 struct Scsi_Host *shost = class_to_shost(cdev);
2751 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2752 u32 size = 0;
2753 struct DIAG_BUFFER_START *request_data;
2754
2755 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
2756 pr_err(MPT3SAS_FMT
2757 "%s: host_trace_buffer is not registered\n",
2758 ioc->name, __func__);
2759 return 0;
2760 }
2761
2762 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2763 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
2764 pr_err(MPT3SAS_FMT
2765 "%s: host_trace_buffer is not registered\n",
2766 ioc->name, __func__);
2767 return 0;
2768 }
2769
2770 request_data = (struct DIAG_BUFFER_START *)
2771 ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
2772 if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
2773 le32_to_cpu(request_data->DiagVersion) == 0x01000000 ||
2774 le32_to_cpu(request_data->DiagVersion) == 0x01010000) &&
2775 le32_to_cpu(request_data->Reserved3) == 0x4742444c)
2776 size = le32_to_cpu(request_data->Size);
2777
2778 ioc->ring_buffer_sz = size;
2779 return snprintf(buf, PAGE_SIZE, "%d\n", size);
2780}
2781static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO,
2782 _ctl_host_trace_buffer_size_show, NULL);
2783
2784/**
2785 * _ctl_host_trace_buffer_show - firmware ring buffer (trace only)
2786 * @cdev - pointer to embedded class device
2787 * @buf - the buffer returned
2788 *
2789 * A sysfs 'read/write' shost attribute.
2790 *
2791 * You will only be able to read 4k bytes of ring buffer at a time.
2792 * In order to read beyond 4k bytes, you will have to write out the
2793 * offset to the same attribute, it will move the pointer.
2794 */
2795static ssize_t
2796_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
2797 char *buf)
2798{
2799 struct Scsi_Host *shost = class_to_shost(cdev);
2800 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2801 void *request_data;
2802 u32 size;
2803
2804 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
2805 pr_err(MPT3SAS_FMT
2806 "%s: host_trace_buffer is not registered\n",
2807 ioc->name, __func__);
2808 return 0;
2809 }
2810
2811 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2812 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
2813 pr_err(MPT3SAS_FMT
2814 "%s: host_trace_buffer is not registered\n",
2815 ioc->name, __func__);
2816 return 0;
2817 }
2818
2819 if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
2820 return 0;
2821
2822 size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
2823 size = (size >= PAGE_SIZE) ? (PAGE_SIZE - 1) : size;
2824 request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
2825 memcpy(buf, request_data, size);
2826 return size;
2827}
2828
2829static ssize_t
2830_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
2831 const char *buf, size_t count)
2832{
2833 struct Scsi_Host *shost = class_to_shost(cdev);
2834 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2835 int val = 0;
2836
2837 if (sscanf(buf, "%d", &val) != 1)
2838 return -EINVAL;
2839
2840 ioc->ring_buffer_offset = val;
2841 return strlen(buf);
2842}
2843static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR,
2844 _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store);
2845
2846
2847/*****************************************/
2848
2849/**
2850 * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only)
2851 * @cdev - pointer to embedded class device
2852 * @buf - the buffer returned
2853 *
2854 * A sysfs 'read/write' shost attribute.
2855 *
2856 * This is a mechnism to post/release host_trace_buffers
2857 */
2858static ssize_t
2859_ctl_host_trace_buffer_enable_show(struct device *cdev,
2860 struct device_attribute *attr, char *buf)
2861{
2862 struct Scsi_Host *shost = class_to_shost(cdev);
2863 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2864
2865 if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
2866 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2867 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0))
2868 return snprintf(buf, PAGE_SIZE, "off\n");
2869 else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2870 MPT3_DIAG_BUFFER_IS_RELEASED))
2871 return snprintf(buf, PAGE_SIZE, "release\n");
2872 else
2873 return snprintf(buf, PAGE_SIZE, "post\n");
2874}
2875
2876static ssize_t
2877_ctl_host_trace_buffer_enable_store(struct device *cdev,
2878 struct device_attribute *attr, const char *buf, size_t count)
2879{
2880 struct Scsi_Host *shost = class_to_shost(cdev);
2881 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2882 char str[10] = "";
2883 struct mpt3_diag_register diag_register;
2884 u8 issue_reset = 0;
2885
2886 /* don't allow post/release occurr while recovery is active */
2887 if (ioc->shost_recovery || ioc->remove_host ||
2888 ioc->pci_error_recovery || ioc->is_driver_loading)
2889 return -EBUSY;
2890
2891 if (sscanf(buf, "%9s", str) != 1)
2892 return -EINVAL;
2893
2894 if (!strcmp(str, "post")) {
2895 /* exit out if host buffers are already posted */
2896 if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
2897 (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2898 MPT3_DIAG_BUFFER_IS_REGISTERED) &&
2899 ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2900 MPT3_DIAG_BUFFER_IS_RELEASED) == 0))
2901 goto out;
2902 memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
2903 pr_info(MPT3SAS_FMT "posting host trace buffers\n",
2904 ioc->name);
2905 diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
2906 diag_register.requested_buffer_size = (1024 * 1024);
2907 diag_register.unique_id = 0x7075900;
2908 ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
2909 _ctl_diag_register_2(ioc, &diag_register);
2910 } else if (!strcmp(str, "release")) {
2911 /* exit out if host buffers are already released */
2912 if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
2913 goto out;
2914 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2915 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0)
2916 goto out;
2917 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
2918 MPT3_DIAG_BUFFER_IS_RELEASED))
2919 goto out;
2920 pr_info(MPT3SAS_FMT "releasing host trace buffer\n",
2921 ioc->name);
2922 mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
2923 &issue_reset);
2924 }
2925
2926 out:
2927 return strlen(buf);
2928}
2929static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR,
2930 _ctl_host_trace_buffer_enable_show,
2931 _ctl_host_trace_buffer_enable_store);
2932
2933/*********** diagnostic trigger suppport *********************************/
2934
2935/**
2936 * _ctl_diag_trigger_master_show - show the diag_trigger_master attribute
2937 * @cdev - pointer to embedded class device
2938 * @buf - the buffer returned
2939 *
2940 * A sysfs 'read/write' shost attribute.
2941 */
2942static ssize_t
2943_ctl_diag_trigger_master_show(struct device *cdev,
2944 struct device_attribute *attr, char *buf)
2945
2946{
2947 struct Scsi_Host *shost = class_to_shost(cdev);
2948 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2949 unsigned long flags;
2950 ssize_t rc;
2951
2952 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
2953 rc = sizeof(struct SL_WH_MASTER_TRIGGER_T);
2954 memcpy(buf, &ioc->diag_trigger_master, rc);
2955 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
2956 return rc;
2957}
2958
2959/**
2960 * _ctl_diag_trigger_master_store - store the diag_trigger_master attribute
2961 * @cdev - pointer to embedded class device
2962 * @buf - the buffer returned
2963 *
2964 * A sysfs 'read/write' shost attribute.
2965 */
2966static ssize_t
2967_ctl_diag_trigger_master_store(struct device *cdev,
2968 struct device_attribute *attr, const char *buf, size_t count)
2969
2970{
2971 struct Scsi_Host *shost = class_to_shost(cdev);
2972 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2973 unsigned long flags;
2974 ssize_t rc;
2975
2976 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
2977 rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count);
2978 memset(&ioc->diag_trigger_master, 0,
2979 sizeof(struct SL_WH_MASTER_TRIGGER_T));
2980 memcpy(&ioc->diag_trigger_master, buf, rc);
2981 ioc->diag_trigger_master.MasterData |=
2982 (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
2983 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
2984 return rc;
2985}
2986static DEVICE_ATTR(diag_trigger_master, S_IRUGO | S_IWUSR,
2987 _ctl_diag_trigger_master_show, _ctl_diag_trigger_master_store);
2988
2989
2990/**
2991 * _ctl_diag_trigger_event_show - show the diag_trigger_event attribute
2992 * @cdev - pointer to embedded class device
2993 * @buf - the buffer returned
2994 *
2995 * A sysfs 'read/write' shost attribute.
2996 */
2997static ssize_t
2998_ctl_diag_trigger_event_show(struct device *cdev,
2999 struct device_attribute *attr, char *buf)
3000{
3001 struct Scsi_Host *shost = class_to_shost(cdev);
3002 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3003 unsigned long flags;
3004 ssize_t rc;
3005
3006 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3007 rc = sizeof(struct SL_WH_EVENT_TRIGGERS_T);
3008 memcpy(buf, &ioc->diag_trigger_event, rc);
3009 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3010 return rc;
3011}
3012
3013/**
3014 * _ctl_diag_trigger_event_store - store the diag_trigger_event attribute
3015 * @cdev - pointer to embedded class device
3016 * @buf - the buffer returned
3017 *
3018 * A sysfs 'read/write' shost attribute.
3019 */
3020static ssize_t
3021_ctl_diag_trigger_event_store(struct device *cdev,
3022 struct device_attribute *attr, const char *buf, size_t count)
3023
3024{
3025 struct Scsi_Host *shost = class_to_shost(cdev);
3026 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3027 unsigned long flags;
3028 ssize_t sz;
3029
3030 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3031 sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count);
3032 memset(&ioc->diag_trigger_event, 0,
3033 sizeof(struct SL_WH_EVENT_TRIGGERS_T));
3034 memcpy(&ioc->diag_trigger_event, buf, sz);
3035 if (ioc->diag_trigger_event.ValidEntries > NUM_VALID_ENTRIES)
3036 ioc->diag_trigger_event.ValidEntries = NUM_VALID_ENTRIES;
3037 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3038 return sz;
3039}
3040static DEVICE_ATTR(diag_trigger_event, S_IRUGO | S_IWUSR,
3041 _ctl_diag_trigger_event_show, _ctl_diag_trigger_event_store);
3042
3043
3044/**
3045 * _ctl_diag_trigger_scsi_show - show the diag_trigger_scsi attribute
3046 * @cdev - pointer to embedded class device
3047 * @buf - the buffer returned
3048 *
3049 * A sysfs 'read/write' shost attribute.
3050 */
3051static ssize_t
3052_ctl_diag_trigger_scsi_show(struct device *cdev,
3053 struct device_attribute *attr, char *buf)
3054{
3055 struct Scsi_Host *shost = class_to_shost(cdev);
3056 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3057 unsigned long flags;
3058 ssize_t rc;
3059
3060 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3061 rc = sizeof(struct SL_WH_SCSI_TRIGGERS_T);
3062 memcpy(buf, &ioc->diag_trigger_scsi, rc);
3063 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3064 return rc;
3065}
3066
3067/**
3068 * _ctl_diag_trigger_scsi_store - store the diag_trigger_scsi attribute
3069 * @cdev - pointer to embedded class device
3070 * @buf - the buffer returned
3071 *
3072 * A sysfs 'read/write' shost attribute.
3073 */
3074static ssize_t
3075_ctl_diag_trigger_scsi_store(struct device *cdev,
3076 struct device_attribute *attr, const char *buf, size_t count)
3077{
3078 struct Scsi_Host *shost = class_to_shost(cdev);
3079 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3080 unsigned long flags;
3081 ssize_t sz;
3082
3083 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3084 sz = min(sizeof(struct SL_WH_SCSI_TRIGGERS_T), count);
3085 memset(&ioc->diag_trigger_scsi, 0,
3086 sizeof(struct SL_WH_EVENT_TRIGGERS_T));
3087 memcpy(&ioc->diag_trigger_scsi, buf, sz);
3088 if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES)
3089 ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES;
3090 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3091 return sz;
3092}
3093static DEVICE_ATTR(diag_trigger_scsi, S_IRUGO | S_IWUSR,
3094 _ctl_diag_trigger_scsi_show, _ctl_diag_trigger_scsi_store);
3095
3096
3097/**
3098 * _ctl_diag_trigger_scsi_show - show the diag_trigger_mpi attribute
3099 * @cdev - pointer to embedded class device
3100 * @buf - the buffer returned
3101 *
3102 * A sysfs 'read/write' shost attribute.
3103 */
3104static ssize_t
3105_ctl_diag_trigger_mpi_show(struct device *cdev,
3106 struct device_attribute *attr, char *buf)
3107{
3108 struct Scsi_Host *shost = class_to_shost(cdev);
3109 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3110 unsigned long flags;
3111 ssize_t rc;
3112
3113 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3114 rc = sizeof(struct SL_WH_MPI_TRIGGERS_T);
3115 memcpy(buf, &ioc->diag_trigger_mpi, rc);
3116 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3117 return rc;
3118}
3119
3120/**
3121 * _ctl_diag_trigger_mpi_store - store the diag_trigger_mpi attribute
3122 * @cdev - pointer to embedded class device
3123 * @buf - the buffer returned
3124 *
3125 * A sysfs 'read/write' shost attribute.
3126 */
3127static ssize_t
3128_ctl_diag_trigger_mpi_store(struct device *cdev,
3129 struct device_attribute *attr, const char *buf, size_t count)
3130{
3131 struct Scsi_Host *shost = class_to_shost(cdev);
3132 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
3133 unsigned long flags;
3134 ssize_t sz;
3135
3136 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
3137 sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count);
3138 memset(&ioc->diag_trigger_mpi, 0,
3139 sizeof(struct SL_WH_EVENT_TRIGGERS_T));
3140 memcpy(&ioc->diag_trigger_mpi, buf, sz);
3141 if (ioc->diag_trigger_mpi.ValidEntries > NUM_VALID_ENTRIES)
3142 ioc->diag_trigger_mpi.ValidEntries = NUM_VALID_ENTRIES;
3143 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
3144 return sz;
3145}
3146
3147static DEVICE_ATTR(diag_trigger_mpi, S_IRUGO | S_IWUSR,
3148 _ctl_diag_trigger_mpi_show, _ctl_diag_trigger_mpi_store);
3149
3150/*********** diagnostic trigger suppport *** END ****************************/
3151
3152
3153
3154/*****************************************/
3155
3156struct device_attribute *mpt3sas_host_attrs[] = {
3157 &dev_attr_version_fw,
3158 &dev_attr_version_bios,
3159 &dev_attr_version_mpi,
3160 &dev_attr_version_product,
3161 &dev_attr_version_nvdata_persistent,
3162 &dev_attr_version_nvdata_default,
3163 &dev_attr_board_name,
3164 &dev_attr_board_assembly,
3165 &dev_attr_board_tracer,
3166 &dev_attr_io_delay,
3167 &dev_attr_device_delay,
3168 &dev_attr_logging_level,
3169 &dev_attr_fwfault_debug,
3170 &dev_attr_fw_queue_depth,
3171 &dev_attr_host_sas_address,
3172 &dev_attr_ioc_reset_count,
3173 &dev_attr_host_trace_buffer_size,
3174 &dev_attr_host_trace_buffer,
3175 &dev_attr_host_trace_buffer_enable,
3176 &dev_attr_reply_queue_count,
3177 &dev_attr_diag_trigger_master,
3178 &dev_attr_diag_trigger_event,
3179 &dev_attr_diag_trigger_scsi,
3180 &dev_attr_diag_trigger_mpi,
3181 NULL,
3182};
3183
3184/* device attributes */
3185
3186/**
3187 * _ctl_device_sas_address_show - sas address
3188 * @cdev - pointer to embedded class device
3189 * @buf - the buffer returned
3190 *
3191 * This is the sas address for the target
3192 *
3193 * A sysfs 'read-only' shost attribute.
3194 */
3195static ssize_t
3196_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr,
3197 char *buf)
3198{
3199 struct scsi_device *sdev = to_scsi_device(dev);
3200 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3201
3202 return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
3203 (unsigned long long)sas_device_priv_data->sas_target->sas_address);
3204}
3205static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL);
3206
3207/**
3208 * _ctl_device_handle_show - device handle
3209 * @cdev - pointer to embedded class device
3210 * @buf - the buffer returned
3211 *
3212 * This is the firmware assigned device handle
3213 *
3214 * A sysfs 'read-only' shost attribute.
3215 */
3216static ssize_t
3217_ctl_device_handle_show(struct device *dev, struct device_attribute *attr,
3218 char *buf)
3219{
3220 struct scsi_device *sdev = to_scsi_device(dev);
3221 struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
3222
3223 return snprintf(buf, PAGE_SIZE, "0x%04x\n",
3224 sas_device_priv_data->sas_target->handle);
3225}
3226static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL);
3227
3228struct device_attribute *mpt3sas_dev_attrs[] = {
3229 &dev_attr_sas_address,
3230 &dev_attr_sas_device_handle,
3231 NULL,
3232};
3233
3234static const struct file_operations ctl_fops = {
3235 .owner = THIS_MODULE,
3236 .unlocked_ioctl = _ctl_ioctl,
3237 .release = _ctl_release,
3238 .poll = _ctl_poll,
3239 .fasync = _ctl_fasync,
3240#ifdef CONFIG_COMPAT
3241 .compat_ioctl = _ctl_ioctl_compat,
3242#endif
3243};
3244
3245static struct miscdevice ctl_dev = {
3246 .minor = MPT3SAS_MINOR,
3247 .name = MPT3SAS_DEV_NAME,
3248 .fops = &ctl_fops,
3249};
3250
3251/**
3252 * mpt3sas_ctl_init - main entry point for ctl.
3253 *
3254 */
3255void
3256mpt3sas_ctl_init(void)
3257{
3258 async_queue = NULL;
3259 if (misc_register(&ctl_dev) < 0)
3260 pr_err("%s can't register misc device [minor=%d]\n",
3261 MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR);
3262
3263 init_waitqueue_head(&ctl_poll_wait);
3264}
3265
3266/**
3267 * mpt3sas_ctl_exit - exit point for ctl
3268 *
3269 */
3270void
3271mpt3sas_ctl_exit(void)
3272{
3273 struct MPT3SAS_ADAPTER *ioc;
3274 int i;
3275
3276 list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
3277
3278 /* free memory associated to diag buffers */
3279 for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
3280 if (!ioc->diag_buffer[i])
3281 continue;
3282 if (!(ioc->diag_buffer_status[i] &
3283 MPT3_DIAG_BUFFER_IS_REGISTERED))
3284 continue;
3285 if ((ioc->diag_buffer_status[i] &
3286 MPT3_DIAG_BUFFER_IS_RELEASED))
3287 continue;
3288 pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i],
3289 ioc->diag_buffer[i], ioc->diag_buffer_dma[i]);
3290 ioc->diag_buffer[i] = NULL;
3291 ioc->diag_buffer_status[i] = 0;
3292 }
3293
3294 kfree(ioc->event_log);
3295 }
3296 misc_deregister(&ctl_dev);
3297}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
new file mode 100644
index 000000000000..bd89f4f00550
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
@@ -0,0 +1,418 @@
1/*
2 * Management Module Support for MPT (Message Passing Technology) based
3 * controllers
4 *
5 * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.h
6 * Copyright (C) 2012 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 MPT3SAS_CTL_H_INCLUDED
46#define MPT3SAS_CTL_H_INCLUDED
47
48#ifdef __KERNEL__
49#include <linux/miscdevice.h>
50#endif
51
52
53#ifndef MPT3SAS_MINOR
54#define MPT3SAS_MINOR (MPT_MINOR + 2)
55#endif
56#define MPT3SAS_DEV_NAME "mpt3ctl"
57#define MPT3_MAGIC_NUMBER 'L'
58#define MPT3_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
59
60/**
61 * IOCTL opcodes
62 */
63#define MPT3IOCINFO _IOWR(MPT3_MAGIC_NUMBER, 17, \
64 struct mpt3_ioctl_iocinfo)
65#define MPT3COMMAND _IOWR(MPT3_MAGIC_NUMBER, 20, \
66 struct mpt3_ioctl_command)
67#ifdef CONFIG_COMPAT
68#define MPT3COMMAND32 _IOWR(MPT3_MAGIC_NUMBER, 20, \
69 struct mpt3_ioctl_command32)
70#endif
71#define MPT3EVENTQUERY _IOWR(MPT3_MAGIC_NUMBER, 21, \
72 struct mpt3_ioctl_eventquery)
73#define MPT3EVENTENABLE _IOWR(MPT3_MAGIC_NUMBER, 22, \
74 struct mpt3_ioctl_eventenable)
75#define MPT3EVENTREPORT _IOWR(MPT3_MAGIC_NUMBER, 23, \
76 struct mpt3_ioctl_eventreport)
77#define MPT3HARDRESET _IOWR(MPT3_MAGIC_NUMBER, 24, \
78 struct mpt3_ioctl_diag_reset)
79#define MPT3BTDHMAPPING _IOWR(MPT3_MAGIC_NUMBER, 31, \
80 struct mpt3_ioctl_btdh_mapping)
81
82/* diag buffer support */
83#define MPT3DIAGREGISTER _IOWR(MPT3_MAGIC_NUMBER, 26, \
84 struct mpt3_diag_register)
85#define MPT3DIAGRELEASE _IOWR(MPT3_MAGIC_NUMBER, 27, \
86 struct mpt3_diag_release)
87#define MPT3DIAGUNREGISTER _IOWR(MPT3_MAGIC_NUMBER, 28, \
88 struct mpt3_diag_unregister)
89#define MPT3DIAGQUERY _IOWR(MPT3_MAGIC_NUMBER, 29, \
90 struct mpt3_diag_query)
91#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \
92 struct mpt3_diag_read_buffer)
93
94/**
95 * struct mpt3_ioctl_header - main header structure
96 * @ioc_number - IOC unit number
97 * @port_number - IOC port number
98 * @max_data_size - maximum number bytes to transfer on read
99 */
100struct mpt3_ioctl_header {
101 uint32_t ioc_number;
102 uint32_t port_number;
103 uint32_t max_data_size;
104};
105
106/**
107 * struct mpt3_ioctl_diag_reset - diagnostic reset
108 * @hdr - generic header
109 */
110struct mpt3_ioctl_diag_reset {
111 struct mpt3_ioctl_header hdr;
112};
113
114
115/**
116 * struct mpt3_ioctl_pci_info - pci device info
117 * @device - pci device id
118 * @function - pci function id
119 * @bus - pci bus id
120 * @segment_id - pci segment id
121 */
122struct mpt3_ioctl_pci_info {
123 union {
124 struct {
125 uint32_t device:5;
126 uint32_t function:3;
127 uint32_t bus:24;
128 } bits;
129 uint32_t word;
130 } u;
131 uint32_t segment_id;
132};
133
134
135#define MPT2_IOCTL_INTERFACE_SCSI (0x00)
136#define MPT2_IOCTL_INTERFACE_FC (0x01)
137#define MPT2_IOCTL_INTERFACE_FC_IP (0x02)
138#define MPT2_IOCTL_INTERFACE_SAS (0x03)
139#define MPT2_IOCTL_INTERFACE_SAS2 (0x04)
140#define MPT3_IOCTL_INTERFACE_SAS3 (0x06)
141#define MPT2_IOCTL_VERSION_LENGTH (32)
142
143/**
144 * struct mpt3_ioctl_iocinfo - generic controller info
145 * @hdr - generic header
146 * @adapter_type - type of adapter (spi, fc, sas)
147 * @port_number - port number
148 * @pci_id - PCI Id
149 * @hw_rev - hardware revision
150 * @sub_system_device - PCI subsystem Device ID
151 * @sub_system_vendor - PCI subsystem Vendor ID
152 * @rsvd0 - reserved
153 * @firmware_version - firmware version
154 * @bios_version - BIOS version
155 * @driver_version - driver version - 32 ASCII characters
156 * @rsvd1 - reserved
157 * @scsi_id - scsi id of adapter 0
158 * @rsvd2 - reserved
159 * @pci_information - pci info (2nd revision)
160 */
161struct mpt3_ioctl_iocinfo {
162 struct mpt3_ioctl_header hdr;
163 uint32_t adapter_type;
164 uint32_t port_number;
165 uint32_t pci_id;
166 uint32_t hw_rev;
167 uint32_t subsystem_device;
168 uint32_t subsystem_vendor;
169 uint32_t rsvd0;
170 uint32_t firmware_version;
171 uint32_t bios_version;
172 uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH];
173 uint8_t rsvd1;
174 uint8_t scsi_id;
175 uint16_t rsvd2;
176 struct mpt3_ioctl_pci_info pci_information;
177};
178
179
180/* number of event log entries */
181#define MPT3SAS_CTL_EVENT_LOG_SIZE (50)
182
183/**
184 * struct mpt3_ioctl_eventquery - query event count and type
185 * @hdr - generic header
186 * @event_entries - number of events returned by get_event_report
187 * @rsvd - reserved
188 * @event_types - type of events currently being captured
189 */
190struct mpt3_ioctl_eventquery {
191 struct mpt3_ioctl_header hdr;
192 uint16_t event_entries;
193 uint16_t rsvd;
194 uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
195};
196
197/**
198 * struct mpt3_ioctl_eventenable - enable/disable event capturing
199 * @hdr - generic header
200 * @event_types - toggle off/on type of events to be captured
201 */
202struct mpt3_ioctl_eventenable {
203 struct mpt3_ioctl_header hdr;
204 uint32_t event_types[4];
205};
206
207#define MPT3_EVENT_DATA_SIZE (192)
208/**
209 * struct MPT3_IOCTL_EVENTS -
210 * @event - the event that was reported
211 * @context - unique value for each event assigned by driver
212 * @data - event data returned in fw reply message
213 */
214struct MPT3_IOCTL_EVENTS {
215 uint32_t event;
216 uint32_t context;
217 uint8_t data[MPT3_EVENT_DATA_SIZE];
218};
219
220/**
221 * struct mpt3_ioctl_eventreport - returing event log
222 * @hdr - generic header
223 * @event_data - (see struct MPT3_IOCTL_EVENTS)
224 */
225struct mpt3_ioctl_eventreport {
226 struct mpt3_ioctl_header hdr;
227 struct MPT3_IOCTL_EVENTS event_data[1];
228};
229
230/**
231 * struct mpt3_ioctl_command - generic mpt firmware passthru ioctl
232 * @hdr - generic header
233 * @timeout - command timeout in seconds. (if zero then use driver default
234 * value).
235 * @reply_frame_buf_ptr - reply location
236 * @data_in_buf_ptr - destination for read
237 * @data_out_buf_ptr - data source for write
238 * @sense_data_ptr - sense data location
239 * @max_reply_bytes - maximum number of reply bytes to be sent to app.
240 * @data_in_size - number bytes for data transfer in (read)
241 * @data_out_size - number bytes for data transfer out (write)
242 * @max_sense_bytes - maximum number of bytes for auto sense buffers
243 * @data_sge_offset - offset in words from the start of the request message to
244 * the first SGL
245 * @mf[1];
246 */
247struct mpt3_ioctl_command {
248 struct mpt3_ioctl_header hdr;
249 uint32_t timeout;
250 void __user *reply_frame_buf_ptr;
251 void __user *data_in_buf_ptr;
252 void __user *data_out_buf_ptr;
253 void __user *sense_data_ptr;
254 uint32_t max_reply_bytes;
255 uint32_t data_in_size;
256 uint32_t data_out_size;
257 uint32_t max_sense_bytes;
258 uint32_t data_sge_offset;
259 uint8_t mf[1];
260};
261
262#ifdef CONFIG_COMPAT
263struct mpt3_ioctl_command32 {
264 struct mpt3_ioctl_header hdr;
265 uint32_t timeout;
266 uint32_t reply_frame_buf_ptr;
267 uint32_t data_in_buf_ptr;
268 uint32_t data_out_buf_ptr;
269 uint32_t sense_data_ptr;
270 uint32_t max_reply_bytes;
271 uint32_t data_in_size;
272 uint32_t data_out_size;
273 uint32_t max_sense_bytes;
274 uint32_t data_sge_offset;
275 uint8_t mf[1];
276};
277#endif
278
279/**
280 * struct mpt3_ioctl_btdh_mapping - mapping info
281 * @hdr - generic header
282 * @id - target device identification number
283 * @bus - SCSI bus number that the target device exists on
284 * @handle - device handle for the target device
285 * @rsvd - reserved
286 *
287 * To obtain a bus/id the application sets
288 * handle to valid handle, and bus/id to 0xFFFF.
289 *
290 * To obtain the device handle the application sets
291 * bus/id valid value, and the handle to 0xFFFF.
292 */
293struct mpt3_ioctl_btdh_mapping {
294 struct mpt3_ioctl_header hdr;
295 uint32_t id;
296 uint32_t bus;
297 uint16_t handle;
298 uint16_t rsvd;
299};
300
301
302
303/* application flags for mpt3_diag_register, mpt3_diag_query */
304#define MPT3_APP_FLAGS_APP_OWNED (0x0001)
305#define MPT3_APP_FLAGS_BUFFER_VALID (0x0002)
306#define MPT3_APP_FLAGS_FW_BUFFER_ACCESS (0x0004)
307
308/* flags for mpt3_diag_read_buffer */
309#define MPT3_FLAGS_REREGISTER (0x0001)
310
311#define MPT3_PRODUCT_SPECIFIC_DWORDS 23
312
313/**
314 * struct mpt3_diag_register - application register with driver
315 * @hdr - generic header
316 * @reserved -
317 * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
318 * @application_flags - misc flags
319 * @diagnostic_flags - specifies flags affecting command processing
320 * @product_specific - product specific information
321 * @requested_buffer_size - buffers size in bytes
322 * @unique_id - tag specified by application that is used to signal ownership
323 * of the buffer.
324 *
325 * This will allow the driver to setup any required buffers that will be
326 * needed by firmware to communicate with the driver.
327 */
328struct mpt3_diag_register {
329 struct mpt3_ioctl_header hdr;
330 uint8_t reserved;
331 uint8_t buffer_type;
332 uint16_t application_flags;
333 uint32_t diagnostic_flags;
334 uint32_t product_specific[MPT3_PRODUCT_SPECIFIC_DWORDS];
335 uint32_t requested_buffer_size;
336 uint32_t unique_id;
337};
338
339/**
340 * struct mpt3_diag_unregister - application unregister with driver
341 * @hdr - generic header
342 * @unique_id - tag uniquely identifies the buffer to be unregistered
343 *
344 * This will allow the driver to cleanup any memory allocated for diag
345 * messages and to free up any resources.
346 */
347struct mpt3_diag_unregister {
348 struct mpt3_ioctl_header hdr;
349 uint32_t unique_id;
350};
351
352/**
353 * struct mpt3_diag_query - query relevant info associated with diag buffers
354 * @hdr - generic header
355 * @reserved -
356 * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
357 * @application_flags - misc flags
358 * @diagnostic_flags - specifies flags affecting command processing
359 * @product_specific - product specific information
360 * @total_buffer_size - diag buffer size in bytes
361 * @driver_added_buffer_size - size of extra space appended to end of buffer
362 * @unique_id - unique id associated with this buffer.
363 *
364 * The application will send only buffer_type and unique_id. Driver will
365 * inspect unique_id first, if valid, fill in all the info. If unique_id is
366 * 0x00, the driver will return info specified by Buffer Type.
367 */
368struct mpt3_diag_query {
369 struct mpt3_ioctl_header hdr;
370 uint8_t reserved;
371 uint8_t buffer_type;
372 uint16_t application_flags;
373 uint32_t diagnostic_flags;
374 uint32_t product_specific[MPT3_PRODUCT_SPECIFIC_DWORDS];
375 uint32_t total_buffer_size;
376 uint32_t driver_added_buffer_size;
377 uint32_t unique_id;
378};
379
380/**
381 * struct mpt3_diag_release - request to send Diag Release Message to firmware
382 * @hdr - generic header
383 * @unique_id - tag uniquely identifies the buffer to be released
384 *
385 * This allows ownership of the specified buffer to returned to the driver,
386 * allowing an application to read the buffer without fear that firmware is
387 * overwritting information in the buffer.
388 */
389struct mpt3_diag_release {
390 struct mpt3_ioctl_header hdr;
391 uint32_t unique_id;
392};
393
394/**
395 * struct mpt3_diag_read_buffer - request for copy of the diag buffer
396 * @hdr - generic header
397 * @status -
398 * @reserved -
399 * @flags - misc flags
400 * @starting_offset - starting offset within drivers buffer where to start
401 * reading data at into the specified application buffer
402 * @bytes_to_read - number of bytes to copy from the drivers buffer into the
403 * application buffer starting at starting_offset.
404 * @unique_id - unique id associated with this buffer.
405 * @diagnostic_data - data payload
406 */
407struct mpt3_diag_read_buffer {
408 struct mpt3_ioctl_header hdr;
409 uint8_t status;
410 uint8_t reserved;
411 uint16_t flags;
412 uint32_t starting_offset;
413 uint32_t bytes_to_read;
414 uint32_t unique_id;
415 uint32_t diagnostic_data[1];
416};
417
418#endif /* MPT3SAS_CTL_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_debug.h b/drivers/scsi/mpt3sas/mpt3sas_debug.h
new file mode 100644
index 000000000000..35405e7044f8
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_debug.h
@@ -0,0 +1,219 @@
1/*
2 * Logging Support for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt3sas/mpt3sas_debug.c
5 * Copyright (C) 2012 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 MPT3SAS_DEBUG_H_INCLUDED
45#define MPT3SAS_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_SAS 0x00020000
64#define MPT_DEBUG_TRANSPORT 0x00040000
65#define MPT_DEBUG_TASK_SET_FULL 0x00080000
66
67#define MPT_DEBUG_TRIGGER_DIAG 0x00200000
68
69
70/*
71 * CONFIG_SCSI_MPT3SAS_LOGGING - enabled in Kconfig
72 */
73
74#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
75#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \
76{ \
77 if (IOC->logging_level & BITS) \
78 CMD; \
79}
80#else
81#define MPT_CHECK_LOGGING(IOC, CMD, BITS)
82#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */
83
84
85/*
86 * debug macros
87 */
88
89#define dprintk(IOC, CMD) \
90 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG)
91
92#define dsgprintk(IOC, CMD) \
93 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG)
94
95#define devtprintk(IOC, CMD) \
96 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS)
97
98#define dewtprintk(IOC, CMD) \
99 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK)
100
101#define dinitprintk(IOC, CMD) \
102 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT)
103
104#define dexitprintk(IOC, CMD) \
105 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT)
106
107#define dfailprintk(IOC, CMD) \
108 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL)
109
110#define dtmprintk(IOC, CMD) \
111 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM)
112
113#define dreplyprintk(IOC, CMD) \
114 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY)
115
116#define dhsprintk(IOC, CMD) \
117 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE)
118
119#define dcprintk(IOC, CMD) \
120 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG)
121
122#define ddlprintk(IOC, CMD) \
123 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL)
124
125#define drsprintk(IOC, CMD) \
126 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET)
127
128#define dsprintk(IOC, CMD) \
129 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI)
130
131#define dctlprintk(IOC, CMD) \
132 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL)
133
134#define dsasprintk(IOC, CMD) \
135 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS)
136
137#define dsastransport(IOC, CMD) \
138 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
139
140#define dmfprintk(IOC, CMD) \
141 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME)
142
143#define dtsfprintk(IOC, CMD) \
144 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL)
145
146#define dtransportprintk(IOC, CMD) \
147 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT)
148
149#define dTriggerDiagPrintk(IOC, CMD) \
150 MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRIGGER_DIAG)
151
152
153
154/* inline functions for dumping debug data*/
155#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
156/**
157 * _debug_dump_mf - print message frame contents
158 * @mpi_request: pointer to message frame
159 * @sz: number of dwords
160 */
161static inline void
162_debug_dump_mf(void *mpi_request, int sz)
163{
164 int i;
165 __le32 *mfp = (__le32 *)mpi_request;
166
167 pr_info("mf:\n\t");
168 for (i = 0; i < sz; i++) {
169 if (i && ((i % 8) == 0))
170 pr_info("\n\t");
171 pr_info("%08x ", le32_to_cpu(mfp[i]));
172 }
173 pr_info("\n");
174}
175/**
176 * _debug_dump_reply - print message frame contents
177 * @mpi_request: pointer to message frame
178 * @sz: number of dwords
179 */
180static inline void
181_debug_dump_reply(void *mpi_request, int sz)
182{
183 int i;
184 __le32 *mfp = (__le32 *)mpi_request;
185
186 pr_info("reply:\n\t");
187 for (i = 0; i < sz; i++) {
188 if (i && ((i % 8) == 0))
189 pr_info("\n\t");
190 pr_info("%08x ", le32_to_cpu(mfp[i]));
191 }
192 pr_info("\n");
193}
194/**
195 * _debug_dump_config - print config page contents
196 * @mpi_request: pointer to message frame
197 * @sz: number of dwords
198 */
199static inline void
200_debug_dump_config(void *mpi_request, int sz)
201{
202 int i;
203 __le32 *mfp = (__le32 *)mpi_request;
204
205 pr_info("config:\n\t");
206 for (i = 0; i < sz; i++) {
207 if (i && ((i % 8) == 0))
208 pr_info("\n\t");
209 pr_info("%08x ", le32_to_cpu(mfp[i]));
210 }
211 pr_info("\n");
212}
213#else
214#define _debug_dump_mf(mpi_request, sz)
215#define _debug_dump_reply(mpi_request, sz)
216#define _debug_dump_config(mpi_request, sz)
217#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */
218
219#endif /* MPT3SAS_DEBUG_H_INCLUDED */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
new file mode 100644
index 000000000000..05f80450ac7e
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -0,0 +1,8167 @@
1/*
2 * Scsi Host Layer for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt3sas/mpt3sas_scsih.c
5 * Copyright (C) 2012 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#include <linux/aer.h>
56#include <linux/raid_class.h>
57
58#include "mpt3sas_base.h"
59
60MODULE_AUTHOR(MPT3SAS_AUTHOR);
61MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION);
62MODULE_LICENSE("GPL");
63MODULE_VERSION(MPT3SAS_DRIVER_VERSION);
64
65#define RAID_CHANNEL 1
66/* forward proto's */
67static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
68 struct _sas_node *sas_expander);
69static void _firmware_event_work(struct work_struct *work);
70
71static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
72 struct _sas_device *sas_device);
73static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
74 u8 retry_count, u8 is_pd);
75
76static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
77
78static void _scsih_scan_start(struct Scsi_Host *shost);
79static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
80
81/* global parameters */
82LIST_HEAD(mpt3sas_ioc_list);
83
84/* local parameters */
85static u8 scsi_io_cb_idx = -1;
86static u8 tm_cb_idx = -1;
87static u8 ctl_cb_idx = -1;
88static u8 base_cb_idx = -1;
89static u8 port_enable_cb_idx = -1;
90static u8 transport_cb_idx = -1;
91static u8 scsih_cb_idx = -1;
92static u8 config_cb_idx = -1;
93static int mpt_ids;
94
95static u8 tm_tr_cb_idx = -1 ;
96static u8 tm_tr_volume_cb_idx = -1 ;
97static u8 tm_sas_control_cb_idx = -1;
98
99/* command line options */
100static u32 logging_level;
101MODULE_PARM_DESC(logging_level,
102 " bits for enabling additional logging info (default=0)");
103
104
105static ushort max_sectors = 0xFFFF;
106module_param(max_sectors, ushort, 0);
107MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767");
108
109
110static int missing_delay[2] = {-1, -1};
111module_param_array(missing_delay, int, NULL, 0);
112MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
113
114/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
115#define MPT3SAS_MAX_LUN (16895)
116static int max_lun = MPT3SAS_MAX_LUN;
117module_param(max_lun, int, 0);
118MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
119
120
121
122
123/* diag_buffer_enable is bitwise
124 * bit 0 set = TRACE
125 * bit 1 set = SNAPSHOT
126 * bit 2 set = EXTENDED
127 *
128 * Either bit can be set, or both
129 */
130static int diag_buffer_enable = -1;
131module_param(diag_buffer_enable, int, 0);
132MODULE_PARM_DESC(diag_buffer_enable,
133 " post diag buffers (TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
134static int disable_discovery = -1;
135module_param(disable_discovery, int, 0);
136MODULE_PARM_DESC(disable_discovery, " disable discovery ");
137
138
139/* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
140static int prot_mask = -1;
141module_param(prot_mask, int, 0);
142MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
143
144
145/* raid transport support */
146
147static struct raid_template *mpt3sas_raid_template;
148
149
150/**
151 * struct sense_info - common structure for obtaining sense keys
152 * @skey: sense key
153 * @asc: additional sense code
154 * @ascq: additional sense code qualifier
155 */
156struct sense_info {
157 u8 skey;
158 u8 asc;
159 u8 ascq;
160};
161
162#define MPT3SAS_PROCESS_TRIGGER_DIAG (0xFFFB)
163#define MPT3SAS_TURN_ON_FAULT_LED (0xFFFC)
164#define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD)
165#define MPT3SAS_ABRT_TASK_SET (0xFFFE)
166#define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
167/**
168 * struct fw_event_work - firmware event struct
169 * @list: link list framework
170 * @work: work object (ioc->fault_reset_work_q)
171 * @cancel_pending_work: flag set during reset handling
172 * @ioc: per adapter object
173 * @device_handle: device handle
174 * @VF_ID: virtual function id
175 * @VP_ID: virtual port id
176 * @ignore: flag meaning this event has been marked to ignore
177 * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
178 * @event_data: reply event data payload follows
179 *
180 * This object stored on ioc->fw_event_list.
181 */
182struct fw_event_work {
183 struct list_head list;
184 struct work_struct work;
185 u8 cancel_pending_work;
186 struct delayed_work delayed_work;
187
188 struct MPT3SAS_ADAPTER *ioc;
189 u16 device_handle;
190 u8 VF_ID;
191 u8 VP_ID;
192 u8 ignore;
193 u16 event;
194 void *event_data;
195};
196
197/* raid transport support */
198static struct raid_template *mpt3sas_raid_template;
199
200/**
201 * struct _scsi_io_transfer - scsi io transfer
202 * @handle: sas device handle (assigned by firmware)
203 * @is_raid: flag set for hidden raid components
204 * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
205 * @data_length: data transfer length
206 * @data_dma: dma pointer to data
207 * @sense: sense data
208 * @lun: lun number
209 * @cdb_length: cdb length
210 * @cdb: cdb contents
211 * @timeout: timeout for this command
212 * @VF_ID: virtual function id
213 * @VP_ID: virtual port id
214 * @valid_reply: flag set for reply message
215 * @sense_length: sense length
216 * @ioc_status: ioc status
217 * @scsi_state: scsi state
218 * @scsi_status: scsi staus
219 * @log_info: log information
220 * @transfer_length: data length transfer when there is a reply message
221 *
222 * Used for sending internal scsi commands to devices within this module.
223 * Refer to _scsi_send_scsi_io().
224 */
225struct _scsi_io_transfer {
226 u16 handle;
227 u8 is_raid;
228 enum dma_data_direction dir;
229 u32 data_length;
230 dma_addr_t data_dma;
231 u8 sense[SCSI_SENSE_BUFFERSIZE];
232 u32 lun;
233 u8 cdb_length;
234 u8 cdb[32];
235 u8 timeout;
236 u8 VF_ID;
237 u8 VP_ID;
238 u8 valid_reply;
239 /* the following bits are only valid when 'valid_reply = 1' */
240 u32 sense_length;
241 u16 ioc_status;
242 u8 scsi_state;
243 u8 scsi_status;
244 u32 log_info;
245 u32 transfer_length;
246};
247
248/*
249 * The pci device ids are defined in mpi/mpi2_cnfg.h.
250 */
251static DEFINE_PCI_DEVICE_TABLE(scsih_pci_table) = {
252 /* Fury ~ 3004 and 3008 */
253 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
254 PCI_ANY_ID, PCI_ANY_ID },
255 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
256 PCI_ANY_ID, PCI_ANY_ID },
257 /* Invader ~ 3108 */
258 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
259 PCI_ANY_ID, PCI_ANY_ID },
260 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
261 PCI_ANY_ID, PCI_ANY_ID },
262 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
263 PCI_ANY_ID, PCI_ANY_ID },
264 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
265 PCI_ANY_ID, PCI_ANY_ID },
266 {0} /* Terminating entry */
267};
268MODULE_DEVICE_TABLE(pci, scsih_pci_table);
269
270/**
271 * _scsih_set_debug_level - global setting of ioc->logging_level.
272 *
273 * Note: The logging levels are defined in mpt3sas_debug.h.
274 */
275static int
276_scsih_set_debug_level(const char *val, struct kernel_param *kp)
277{
278 int ret = param_set_int(val, kp);
279 struct MPT3SAS_ADAPTER *ioc;
280
281 if (ret)
282 return ret;
283
284 pr_info("setting logging_level(0x%08x)\n", logging_level);
285 list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
286 ioc->logging_level = logging_level;
287 return 0;
288}
289module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
290 &logging_level, 0644);
291
292/**
293 * _scsih_srch_boot_sas_address - search based on sas_address
294 * @sas_address: sas address
295 * @boot_device: boot device object from bios page 2
296 *
297 * Returns 1 when there's a match, 0 means no match.
298 */
299static inline int
300_scsih_srch_boot_sas_address(u64 sas_address,
301 Mpi2BootDeviceSasWwid_t *boot_device)
302{
303 return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0;
304}
305
306/**
307 * _scsih_srch_boot_device_name - search based on device name
308 * @device_name: device name specified in INDENTIFY fram
309 * @boot_device: boot device object from bios page 2
310 *
311 * Returns 1 when there's a match, 0 means no match.
312 */
313static inline int
314_scsih_srch_boot_device_name(u64 device_name,
315 Mpi2BootDeviceDeviceName_t *boot_device)
316{
317 return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
318}
319
320/**
321 * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
322 * @enclosure_logical_id: enclosure logical id
323 * @slot_number: slot number
324 * @boot_device: boot device object from bios page 2
325 *
326 * Returns 1 when there's a match, 0 means no match.
327 */
328static inline int
329_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
330 Mpi2BootDeviceEnclosureSlot_t *boot_device)
331{
332 return (enclosure_logical_id == le64_to_cpu(boot_device->
333 EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
334 SlotNumber)) ? 1 : 0;
335}
336
337/**
338 * _scsih_is_boot_device - search for matching boot device.
339 * @sas_address: sas address
340 * @device_name: device name specified in INDENTIFY fram
341 * @enclosure_logical_id: enclosure logical id
342 * @slot_number: slot number
343 * @form: specifies boot device form
344 * @boot_device: boot device object from bios page 2
345 *
346 * Returns 1 when there's a match, 0 means no match.
347 */
348static int
349_scsih_is_boot_device(u64 sas_address, u64 device_name,
350 u64 enclosure_logical_id, u16 slot, u8 form,
351 Mpi2BiosPage2BootDevice_t *boot_device)
352{
353 int rc = 0;
354
355 switch (form) {
356 case MPI2_BIOSPAGE2_FORM_SAS_WWID:
357 if (!sas_address)
358 break;
359 rc = _scsih_srch_boot_sas_address(
360 sas_address, &boot_device->SasWwid);
361 break;
362 case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
363 if (!enclosure_logical_id)
364 break;
365 rc = _scsih_srch_boot_encl_slot(
366 enclosure_logical_id,
367 slot, &boot_device->EnclosureSlot);
368 break;
369 case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
370 if (!device_name)
371 break;
372 rc = _scsih_srch_boot_device_name(
373 device_name, &boot_device->DeviceName);
374 break;
375 case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
376 break;
377 }
378
379 return rc;
380}
381
382/**
383 * _scsih_get_sas_address - set the sas_address for given device handle
384 * @handle: device handle
385 * @sas_address: sas address
386 *
387 * Returns 0 success, non-zero when failure
388 */
389static int
390_scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle,
391 u64 *sas_address)
392{
393 Mpi2SasDevicePage0_t sas_device_pg0;
394 Mpi2ConfigReply_t mpi_reply;
395 u32 ioc_status;
396
397 *sas_address = 0;
398
399 if (handle <= ioc->sas_hba.num_phys) {
400 *sas_address = ioc->sas_hba.sas_address;
401 return 0;
402 }
403
404 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
405 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
406 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
407 __FILE__, __LINE__, __func__);
408 return -ENXIO;
409 }
410
411 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
412 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
413 *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
414 return 0;
415 }
416
417 /* we hit this becuase the given parent handle doesn't exist */
418 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
419 return -ENXIO;
420
421 /* else error case */
422 pr_err(MPT3SAS_FMT
423 "handle(0x%04x), ioc_status(0x%04x), failure at %s:%d/%s()!\n",
424 ioc->name, handle, ioc_status,
425 __FILE__, __LINE__, __func__);
426 return -EIO;
427}
428
429/**
430 * _scsih_determine_boot_device - determine boot device.
431 * @ioc: per adapter object
432 * @device: either sas_device or raid_device object
433 * @is_raid: [flag] 1 = raid object, 0 = sas object
434 *
435 * Determines whether this device should be first reported device to
436 * to scsi-ml or sas transport, this purpose is for persistent boot device.
437 * There are primary, alternate, and current entries in bios page 2. The order
438 * priority is primary, alternate, then current. This routine saves
439 * the corresponding device object and is_raid flag in the ioc object.
440 * The saved data to be used later in _scsih_probe_boot_devices().
441 */
442static void
443_scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
444 void *device, u8 is_raid)
445{
446 struct _sas_device *sas_device;
447 struct _raid_device *raid_device;
448 u64 sas_address;
449 u64 device_name;
450 u64 enclosure_logical_id;
451 u16 slot;
452
453 /* only process this function when driver loads */
454 if (!ioc->is_driver_loading)
455 return;
456
457 /* no Bios, return immediately */
458 if (!ioc->bios_pg3.BiosVersion)
459 return;
460
461 if (!is_raid) {
462 sas_device = device;
463 sas_address = sas_device->sas_address;
464 device_name = sas_device->device_name;
465 enclosure_logical_id = sas_device->enclosure_logical_id;
466 slot = sas_device->slot;
467 } else {
468 raid_device = device;
469 sas_address = raid_device->wwid;
470 device_name = 0;
471 enclosure_logical_id = 0;
472 slot = 0;
473 }
474
475 if (!ioc->req_boot_device.device) {
476 if (_scsih_is_boot_device(sas_address, device_name,
477 enclosure_logical_id, slot,
478 (ioc->bios_pg2.ReqBootDeviceForm &
479 MPI2_BIOSPAGE2_FORM_MASK),
480 &ioc->bios_pg2.RequestedBootDevice)) {
481 dinitprintk(ioc, pr_info(MPT3SAS_FMT
482 "%s: req_boot_device(0x%016llx)\n",
483 ioc->name, __func__,
484 (unsigned long long)sas_address));
485 ioc->req_boot_device.device = device;
486 ioc->req_boot_device.is_raid = is_raid;
487 }
488 }
489
490 if (!ioc->req_alt_boot_device.device) {
491 if (_scsih_is_boot_device(sas_address, device_name,
492 enclosure_logical_id, slot,
493 (ioc->bios_pg2.ReqAltBootDeviceForm &
494 MPI2_BIOSPAGE2_FORM_MASK),
495 &ioc->bios_pg2.RequestedAltBootDevice)) {
496 dinitprintk(ioc, pr_info(MPT3SAS_FMT
497 "%s: req_alt_boot_device(0x%016llx)\n",
498 ioc->name, __func__,
499 (unsigned long long)sas_address));
500 ioc->req_alt_boot_device.device = device;
501 ioc->req_alt_boot_device.is_raid = is_raid;
502 }
503 }
504
505 if (!ioc->current_boot_device.device) {
506 if (_scsih_is_boot_device(sas_address, device_name,
507 enclosure_logical_id, slot,
508 (ioc->bios_pg2.CurrentBootDeviceForm &
509 MPI2_BIOSPAGE2_FORM_MASK),
510 &ioc->bios_pg2.CurrentBootDevice)) {
511 dinitprintk(ioc, pr_info(MPT3SAS_FMT
512 "%s: current_boot_device(0x%016llx)\n",
513 ioc->name, __func__,
514 (unsigned long long)sas_address));
515 ioc->current_boot_device.device = device;
516 ioc->current_boot_device.is_raid = is_raid;
517 }
518 }
519}
520
521/**
522 * mpt3sas_scsih_sas_device_find_by_sas_address - sas device search
523 * @ioc: per adapter object
524 * @sas_address: sas address
525 * Context: Calling function should acquire ioc->sas_device_lock
526 *
527 * This searches for sas_device based on sas_address, then return sas_device
528 * object.
529 */
530struct _sas_device *
531mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
532 u64 sas_address)
533{
534 struct _sas_device *sas_device;
535
536 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
537 if (sas_device->sas_address == sas_address)
538 return sas_device;
539
540 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
541 if (sas_device->sas_address == sas_address)
542 return sas_device;
543
544 return NULL;
545}
546
547/**
548 * _scsih_sas_device_find_by_handle - sas device search
549 * @ioc: per adapter object
550 * @handle: sas device handle (assigned by firmware)
551 * Context: Calling function should acquire ioc->sas_device_lock
552 *
553 * This searches for sas_device based on sas_address, then return sas_device
554 * object.
555 */
556static struct _sas_device *
557_scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
558{
559 struct _sas_device *sas_device;
560
561 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
562 if (sas_device->handle == handle)
563 return sas_device;
564
565 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
566 if (sas_device->handle == handle)
567 return sas_device;
568
569 return NULL;
570}
571
572/**
573 * _scsih_sas_device_remove - remove sas_device from list.
574 * @ioc: per adapter object
575 * @sas_device: the sas_device object
576 * Context: This function will acquire ioc->sas_device_lock.
577 *
578 * Removing object and freeing associated memory from the ioc->sas_device_list.
579 */
580static void
581_scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
582 struct _sas_device *sas_device)
583{
584 unsigned long flags;
585
586 if (!sas_device)
587 return;
588
589 spin_lock_irqsave(&ioc->sas_device_lock, flags);
590 list_del(&sas_device->list);
591 kfree(sas_device);
592 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
593}
594
595/**
596 * _scsih_device_remove_by_handle - removing device object by handle
597 * @ioc: per adapter object
598 * @handle: device handle
599 *
600 * Return nothing.
601 */
602static void
603_scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
604{
605 struct _sas_device *sas_device;
606 unsigned long flags;
607
608 if (ioc->shost_recovery)
609 return;
610
611 spin_lock_irqsave(&ioc->sas_device_lock, flags);
612 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
613 if (sas_device)
614 list_del(&sas_device->list);
615 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
616 if (sas_device)
617 _scsih_remove_device(ioc, sas_device);
618}
619
620/**
621 * mpt3sas_device_remove_by_sas_address - removing device object by sas address
622 * @ioc: per adapter object
623 * @sas_address: device sas_address
624 *
625 * Return nothing.
626 */
627void
628mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
629 u64 sas_address)
630{
631 struct _sas_device *sas_device;
632 unsigned long flags;
633
634 if (ioc->shost_recovery)
635 return;
636
637 spin_lock_irqsave(&ioc->sas_device_lock, flags);
638 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
639 sas_address);
640 if (sas_device)
641 list_del(&sas_device->list);
642 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
643 if (sas_device)
644 _scsih_remove_device(ioc, sas_device);
645}
646
647/**
648 * _scsih_sas_device_add - insert sas_device to the list.
649 * @ioc: per adapter object
650 * @sas_device: the sas_device object
651 * Context: This function will acquire ioc->sas_device_lock.
652 *
653 * Adding new object to the ioc->sas_device_list.
654 */
655static void
656_scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
657 struct _sas_device *sas_device)
658{
659 unsigned long flags;
660
661 dewtprintk(ioc, pr_info(MPT3SAS_FMT
662 "%s: handle(0x%04x), sas_addr(0x%016llx)\n",
663 ioc->name, __func__, sas_device->handle,
664 (unsigned long long)sas_device->sas_address));
665
666 spin_lock_irqsave(&ioc->sas_device_lock, flags);
667 list_add_tail(&sas_device->list, &ioc->sas_device_list);
668 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
669
670 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
671 sas_device->sas_address_parent)) {
672 _scsih_sas_device_remove(ioc, sas_device);
673 } else if (!sas_device->starget) {
674 /*
675 * When asyn scanning is enabled, its not possible to remove
676 * devices while scanning is turned on due to an oops in
677 * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start()
678 */
679 if (!ioc->is_driver_loading)
680 mpt3sas_transport_port_remove(ioc,
681 sas_device->sas_address,
682 sas_device->sas_address_parent);
683 _scsih_sas_device_remove(ioc, sas_device);
684 }
685}
686
687/**
688 * _scsih_sas_device_init_add - insert sas_device to the list.
689 * @ioc: per adapter object
690 * @sas_device: the sas_device object
691 * Context: This function will acquire ioc->sas_device_lock.
692 *
693 * Adding new object at driver load time to the ioc->sas_device_init_list.
694 */
695static void
696_scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc,
697 struct _sas_device *sas_device)
698{
699 unsigned long flags;
700
701 dewtprintk(ioc, pr_info(MPT3SAS_FMT
702 "%s: handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
703 __func__, sas_device->handle,
704 (unsigned long long)sas_device->sas_address));
705
706 spin_lock_irqsave(&ioc->sas_device_lock, flags);
707 list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
708 _scsih_determine_boot_device(ioc, sas_device, 0);
709 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
710}
711
712/**
713 * _scsih_raid_device_find_by_id - raid device search
714 * @ioc: per adapter object
715 * @id: sas device target id
716 * @channel: sas device channel
717 * Context: Calling function should acquire ioc->raid_device_lock
718 *
719 * This searches for raid_device based on target id, then return raid_device
720 * object.
721 */
722static struct _raid_device *
723_scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
724{
725 struct _raid_device *raid_device, *r;
726
727 r = NULL;
728 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
729 if (raid_device->id == id && raid_device->channel == channel) {
730 r = raid_device;
731 goto out;
732 }
733 }
734
735 out:
736 return r;
737}
738
739/**
740 * _scsih_raid_device_find_by_handle - raid device search
741 * @ioc: per adapter object
742 * @handle: sas device handle (assigned by firmware)
743 * Context: Calling function should acquire ioc->raid_device_lock
744 *
745 * This searches for raid_device based on handle, then return raid_device
746 * object.
747 */
748static struct _raid_device *
749_scsih_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
750{
751 struct _raid_device *raid_device, *r;
752
753 r = NULL;
754 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
755 if (raid_device->handle != handle)
756 continue;
757 r = raid_device;
758 goto out;
759 }
760
761 out:
762 return r;
763}
764
765/**
766 * _scsih_raid_device_find_by_wwid - raid device search
767 * @ioc: per adapter object
768 * @handle: sas device handle (assigned by firmware)
769 * Context: Calling function should acquire ioc->raid_device_lock
770 *
771 * This searches for raid_device based on wwid, then return raid_device
772 * object.
773 */
774static struct _raid_device *
775_scsih_raid_device_find_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid)
776{
777 struct _raid_device *raid_device, *r;
778
779 r = NULL;
780 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
781 if (raid_device->wwid != wwid)
782 continue;
783 r = raid_device;
784 goto out;
785 }
786
787 out:
788 return r;
789}
790
791/**
792 * _scsih_raid_device_add - add raid_device object
793 * @ioc: per adapter object
794 * @raid_device: raid_device object
795 *
796 * This is added to the raid_device_list link list.
797 */
798static void
799_scsih_raid_device_add(struct MPT3SAS_ADAPTER *ioc,
800 struct _raid_device *raid_device)
801{
802 unsigned long flags;
803
804 dewtprintk(ioc, pr_info(MPT3SAS_FMT
805 "%s: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
806 raid_device->handle, (unsigned long long)raid_device->wwid));
807
808 spin_lock_irqsave(&ioc->raid_device_lock, flags);
809 list_add_tail(&raid_device->list, &ioc->raid_device_list);
810 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
811}
812
813/**
814 * _scsih_raid_device_remove - delete raid_device object
815 * @ioc: per adapter object
816 * @raid_device: raid_device object
817 *
818 */
819static void
820_scsih_raid_device_remove(struct MPT3SAS_ADAPTER *ioc,
821 struct _raid_device *raid_device)
822{
823 unsigned long flags;
824
825 spin_lock_irqsave(&ioc->raid_device_lock, flags);
826 list_del(&raid_device->list);
827 kfree(raid_device);
828 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
829}
830
831/**
832 * mpt3sas_scsih_expander_find_by_handle - expander device search
833 * @ioc: per adapter object
834 * @handle: expander handle (assigned by firmware)
835 * Context: Calling function should acquire ioc->sas_device_lock
836 *
837 * This searches for expander device based on handle, then returns the
838 * sas_node object.
839 */
840struct _sas_node *
841mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
842{
843 struct _sas_node *sas_expander, *r;
844
845 r = NULL;
846 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
847 if (sas_expander->handle != handle)
848 continue;
849 r = sas_expander;
850 goto out;
851 }
852 out:
853 return r;
854}
855
856/**
857 * mpt3sas_scsih_expander_find_by_sas_address - expander device search
858 * @ioc: per adapter object
859 * @sas_address: sas address
860 * Context: Calling function should acquire ioc->sas_node_lock.
861 *
862 * This searches for expander device based on sas_address, then returns the
863 * sas_node object.
864 */
865struct _sas_node *
866mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
867 u64 sas_address)
868{
869 struct _sas_node *sas_expander, *r;
870
871 r = NULL;
872 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
873 if (sas_expander->sas_address != sas_address)
874 continue;
875 r = sas_expander;
876 goto out;
877 }
878 out:
879 return r;
880}
881
882/**
883 * _scsih_expander_node_add - insert expander device to the list.
884 * @ioc: per adapter object
885 * @sas_expander: the sas_device object
886 * Context: This function will acquire ioc->sas_node_lock.
887 *
888 * Adding new object to the ioc->sas_expander_list.
889 *
890 * Return nothing.
891 */
892static void
893_scsih_expander_node_add(struct MPT3SAS_ADAPTER *ioc,
894 struct _sas_node *sas_expander)
895{
896 unsigned long flags;
897
898 spin_lock_irqsave(&ioc->sas_node_lock, flags);
899 list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
900 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
901}
902
903/**
904 * _scsih_is_end_device - determines if device is an end device
905 * @device_info: bitfield providing information about the device.
906 * Context: none
907 *
908 * Returns 1 if end device.
909 */
910static int
911_scsih_is_end_device(u32 device_info)
912{
913 if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
914 ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
915 (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
916 (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
917 return 1;
918 else
919 return 0;
920}
921
922/**
923 * _scsih_scsi_lookup_get - returns scmd entry
924 * @ioc: per adapter object
925 * @smid: system request message index
926 *
927 * Returns the smid stored scmd pointer.
928 */
929static struct scsi_cmnd *
930_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
931{
932 return ioc->scsi_lookup[smid - 1].scmd;
933}
934
935/**
936 * _scsih_scsi_lookup_get_clear - returns scmd entry
937 * @ioc: per adapter object
938 * @smid: system request message index
939 *
940 * Returns the smid stored scmd pointer.
941 * Then will derefrence the stored scmd pointer.
942 */
943static inline struct scsi_cmnd *
944_scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid)
945{
946 unsigned long flags;
947 struct scsi_cmnd *scmd;
948
949 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
950 scmd = ioc->scsi_lookup[smid - 1].scmd;
951 ioc->scsi_lookup[smid - 1].scmd = NULL;
952 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
953
954 return scmd;
955}
956
957/**
958 * _scsih_scsi_lookup_find_by_scmd - scmd lookup
959 * @ioc: per adapter object
960 * @smid: system request message index
961 * @scmd: pointer to scsi command object
962 * Context: This function will acquire ioc->scsi_lookup_lock.
963 *
964 * This will search for a scmd pointer in the scsi_lookup array,
965 * returning the revelent smid. A returned value of zero means invalid.
966 */
967static u16
968_scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd
969 *scmd)
970{
971 u16 smid;
972 unsigned long flags;
973 int i;
974
975 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
976 smid = 0;
977 for (i = 0; i < ioc->scsiio_depth; i++) {
978 if (ioc->scsi_lookup[i].scmd == scmd) {
979 smid = ioc->scsi_lookup[i].smid;
980 goto out;
981 }
982 }
983 out:
984 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
985 return smid;
986}
987
988/**
989 * _scsih_scsi_lookup_find_by_target - search for matching channel:id
990 * @ioc: per adapter object
991 * @id: target id
992 * @channel: channel
993 * Context: This function will acquire ioc->scsi_lookup_lock.
994 *
995 * This will search for a matching channel:id in the scsi_lookup array,
996 * returning 1 if found.
997 */
998static u8
999_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id,
1000 int channel)
1001{
1002 u8 found;
1003 unsigned long flags;
1004 int i;
1005
1006 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1007 found = 0;
1008 for (i = 0 ; i < ioc->scsiio_depth; i++) {
1009 if (ioc->scsi_lookup[i].scmd &&
1010 (ioc->scsi_lookup[i].scmd->device->id == id &&
1011 ioc->scsi_lookup[i].scmd->device->channel == channel)) {
1012 found = 1;
1013 goto out;
1014 }
1015 }
1016 out:
1017 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1018 return found;
1019}
1020
1021/**
1022 * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
1023 * @ioc: per adapter object
1024 * @id: target id
1025 * @lun: lun number
1026 * @channel: channel
1027 * Context: This function will acquire ioc->scsi_lookup_lock.
1028 *
1029 * This will search for a matching channel:id:lun in the scsi_lookup array,
1030 * returning 1 if found.
1031 */
1032static u8
1033_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
1034 unsigned int lun, int channel)
1035{
1036 u8 found;
1037 unsigned long flags;
1038 int i;
1039
1040 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1041 found = 0;
1042 for (i = 0 ; i < ioc->scsiio_depth; i++) {
1043 if (ioc->scsi_lookup[i].scmd &&
1044 (ioc->scsi_lookup[i].scmd->device->id == id &&
1045 ioc->scsi_lookup[i].scmd->device->channel == channel &&
1046 ioc->scsi_lookup[i].scmd->device->lun == lun)) {
1047 found = 1;
1048 goto out;
1049 }
1050 }
1051 out:
1052 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1053 return found;
1054}
1055
1056
1057static void
1058_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
1059{
1060 struct Scsi_Host *shost = sdev->host;
1061 int max_depth;
1062 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1063 struct MPT3SAS_DEVICE *sas_device_priv_data;
1064 struct MPT3SAS_TARGET *sas_target_priv_data;
1065 struct _sas_device *sas_device;
1066 unsigned long flags;
1067
1068 max_depth = shost->can_queue;
1069
1070 /* limit max device queue for SATA to 32 */
1071 sas_device_priv_data = sdev->hostdata;
1072 if (!sas_device_priv_data)
1073 goto not_sata;
1074 sas_target_priv_data = sas_device_priv_data->sas_target;
1075 if (!sas_target_priv_data)
1076 goto not_sata;
1077 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
1078 goto not_sata;
1079 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1080 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1081 sas_device_priv_data->sas_target->sas_address);
1082 if (sas_device && sas_device->device_info &
1083 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1084 max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
1085 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1086
1087 not_sata:
1088
1089 if (!sdev->tagged_supported)
1090 max_depth = 1;
1091 if (qdepth > max_depth)
1092 qdepth = max_depth;
1093 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
1094}
1095
1096/**
1097 * _scsih_change_queue_depth - setting device queue depth
1098 * @sdev: scsi device struct
1099 * @qdepth: requested queue depth
1100 * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
1101 * (see include/scsi/scsi_host.h for definition)
1102 *
1103 * Returns queue depth.
1104 */
1105static int
1106_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
1107{
1108 if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
1109 _scsih_adjust_queue_depth(sdev, qdepth);
1110 else if (reason == SCSI_QDEPTH_QFULL)
1111 scsi_track_queue_full(sdev, qdepth);
1112 else
1113 return -EOPNOTSUPP;
1114
1115 if (sdev->inquiry_len > 7)
1116 sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " \
1117 "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
1118 sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
1119 sdev->ordered_tags, sdev->scsi_level,
1120 (sdev->inquiry[7] & 2) >> 1);
1121
1122 return sdev->queue_depth;
1123}
1124
1125/**
1126 * _scsih_change_queue_type - changing device queue tag type
1127 * @sdev: scsi device struct
1128 * @tag_type: requested tag type
1129 *
1130 * Returns queue tag type.
1131 */
1132static int
1133_scsih_change_queue_type(struct scsi_device *sdev, int tag_type)
1134{
1135 if (sdev->tagged_supported) {
1136 scsi_set_tag_type(sdev, tag_type);
1137 if (tag_type)
1138 scsi_activate_tcq(sdev, sdev->queue_depth);
1139 else
1140 scsi_deactivate_tcq(sdev, sdev->queue_depth);
1141 } else
1142 tag_type = 0;
1143
1144 return tag_type;
1145}
1146
1147
1148/**
1149 * _scsih_target_alloc - target add routine
1150 * @starget: scsi target struct
1151 *
1152 * Returns 0 if ok. Any other return is assumed to be an error and
1153 * the device is ignored.
1154 */
1155static int
1156_scsih_target_alloc(struct scsi_target *starget)
1157{
1158 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1159 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1160 struct MPT3SAS_TARGET *sas_target_priv_data;
1161 struct _sas_device *sas_device;
1162 struct _raid_device *raid_device;
1163 unsigned long flags;
1164 struct sas_rphy *rphy;
1165
1166 sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
1167 if (!sas_target_priv_data)
1168 return -ENOMEM;
1169
1170 starget->hostdata = sas_target_priv_data;
1171 sas_target_priv_data->starget = starget;
1172 sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
1173
1174 /* RAID volumes */
1175 if (starget->channel == RAID_CHANNEL) {
1176 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1177 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1178 starget->channel);
1179 if (raid_device) {
1180 sas_target_priv_data->handle = raid_device->handle;
1181 sas_target_priv_data->sas_address = raid_device->wwid;
1182 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
1183 raid_device->starget = starget;
1184 }
1185 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1186 return 0;
1187 }
1188
1189 /* sas/sata devices */
1190 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1191 rphy = dev_to_rphy(starget->dev.parent);
1192 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1193 rphy->identify.sas_address);
1194
1195 if (sas_device) {
1196 sas_target_priv_data->handle = sas_device->handle;
1197 sas_target_priv_data->sas_address = sas_device->sas_address;
1198 sas_device->starget = starget;
1199 sas_device->id = starget->id;
1200 sas_device->channel = starget->channel;
1201 if (test_bit(sas_device->handle, ioc->pd_handles))
1202 sas_target_priv_data->flags |=
1203 MPT_TARGET_FLAGS_RAID_COMPONENT;
1204 if (sas_device->fast_path)
1205 sas_target_priv_data->flags |= MPT_TARGET_FASTPATH_IO;
1206 }
1207 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1208
1209 return 0;
1210}
1211
1212/**
1213 * _scsih_target_destroy - target destroy routine
1214 * @starget: scsi target struct
1215 *
1216 * Returns nothing.
1217 */
1218static void
1219_scsih_target_destroy(struct scsi_target *starget)
1220{
1221 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1222 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1223 struct MPT3SAS_TARGET *sas_target_priv_data;
1224 struct _sas_device *sas_device;
1225 struct _raid_device *raid_device;
1226 unsigned long flags;
1227 struct sas_rphy *rphy;
1228
1229 sas_target_priv_data = starget->hostdata;
1230 if (!sas_target_priv_data)
1231 return;
1232
1233 if (starget->channel == RAID_CHANNEL) {
1234 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1235 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1236 starget->channel);
1237 if (raid_device) {
1238 raid_device->starget = NULL;
1239 raid_device->sdev = NULL;
1240 }
1241 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1242 goto out;
1243 }
1244
1245 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1246 rphy = dev_to_rphy(starget->dev.parent);
1247 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1248 rphy->identify.sas_address);
1249 if (sas_device && (sas_device->starget == starget) &&
1250 (sas_device->id == starget->id) &&
1251 (sas_device->channel == starget->channel))
1252 sas_device->starget = NULL;
1253
1254 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1255
1256 out:
1257 kfree(sas_target_priv_data);
1258 starget->hostdata = NULL;
1259}
1260
1261/**
1262 * _scsih_slave_alloc - device add routine
1263 * @sdev: scsi device struct
1264 *
1265 * Returns 0 if ok. Any other return is assumed to be an error and
1266 * the device is ignored.
1267 */
1268static int
1269_scsih_slave_alloc(struct scsi_device *sdev)
1270{
1271 struct Scsi_Host *shost;
1272 struct MPT3SAS_ADAPTER *ioc;
1273 struct MPT3SAS_TARGET *sas_target_priv_data;
1274 struct MPT3SAS_DEVICE *sas_device_priv_data;
1275 struct scsi_target *starget;
1276 struct _raid_device *raid_device;
1277 unsigned long flags;
1278
1279 sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
1280 if (!sas_device_priv_data)
1281 return -ENOMEM;
1282
1283 sas_device_priv_data->lun = sdev->lun;
1284 sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
1285
1286 starget = scsi_target(sdev);
1287 sas_target_priv_data = starget->hostdata;
1288 sas_target_priv_data->num_luns++;
1289 sas_device_priv_data->sas_target = sas_target_priv_data;
1290 sdev->hostdata = sas_device_priv_data;
1291 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
1292 sdev->no_uld_attach = 1;
1293
1294 shost = dev_to_shost(&starget->dev);
1295 ioc = shost_priv(shost);
1296 if (starget->channel == RAID_CHANNEL) {
1297 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1298 raid_device = _scsih_raid_device_find_by_id(ioc,
1299 starget->id, starget->channel);
1300 if (raid_device)
1301 raid_device->sdev = sdev; /* raid is single lun */
1302 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1303 }
1304
1305 return 0;
1306}
1307
1308/**
1309 * _scsih_slave_destroy - device destroy routine
1310 * @sdev: scsi device struct
1311 *
1312 * Returns nothing.
1313 */
1314static void
1315_scsih_slave_destroy(struct scsi_device *sdev)
1316{
1317 struct MPT3SAS_TARGET *sas_target_priv_data;
1318 struct scsi_target *starget;
1319 struct Scsi_Host *shost;
1320 struct MPT3SAS_ADAPTER *ioc;
1321 struct _sas_device *sas_device;
1322 unsigned long flags;
1323
1324 if (!sdev->hostdata)
1325 return;
1326
1327 starget = scsi_target(sdev);
1328 sas_target_priv_data = starget->hostdata;
1329 sas_target_priv_data->num_luns--;
1330
1331 shost = dev_to_shost(&starget->dev);
1332 ioc = shost_priv(shost);
1333
1334 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1335 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1336 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1337 sas_target_priv_data->sas_address);
1338 if (sas_device && !sas_target_priv_data->num_luns)
1339 sas_device->starget = NULL;
1340 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1341 }
1342
1343 kfree(sdev->hostdata);
1344 sdev->hostdata = NULL;
1345}
1346
1347/**
1348 * _scsih_display_sata_capabilities - sata capabilities
1349 * @ioc: per adapter object
1350 * @handle: device handle
1351 * @sdev: scsi device struct
1352 */
1353static void
1354_scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
1355 u16 handle, struct scsi_device *sdev)
1356{
1357 Mpi2ConfigReply_t mpi_reply;
1358 Mpi2SasDevicePage0_t sas_device_pg0;
1359 u32 ioc_status;
1360 u16 flags;
1361 u32 device_info;
1362
1363 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
1364 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
1365 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1366 ioc->name, __FILE__, __LINE__, __func__);
1367 return;
1368 }
1369
1370 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1371 MPI2_IOCSTATUS_MASK;
1372 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1373 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1374 ioc->name, __FILE__, __LINE__, __func__);
1375 return;
1376 }
1377
1378 flags = le16_to_cpu(sas_device_pg0.Flags);
1379 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
1380
1381 sdev_printk(KERN_INFO, sdev,
1382 "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
1383 "sw_preserve(%s)\n",
1384 (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
1385 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
1386 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
1387 "n",
1388 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
1389 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
1390 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
1391}
1392
1393/*
1394 * raid transport support -
1395 * Enabled for SLES11 and newer, in older kernels the driver will panic when
1396 * unloading the driver followed by a load - I beleive that the subroutine
1397 * raid_class_release() is not cleaning up properly.
1398 */
1399
1400/**
1401 * _scsih_is_raid - return boolean indicating device is raid volume
1402 * @dev the device struct object
1403 */
1404static int
1405_scsih_is_raid(struct device *dev)
1406{
1407 struct scsi_device *sdev = to_scsi_device(dev);
1408
1409 return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
1410}
1411
1412/**
1413 * _scsih_get_resync - get raid volume resync percent complete
1414 * @dev the device struct object
1415 */
1416static void
1417_scsih_get_resync(struct device *dev)
1418{
1419 struct scsi_device *sdev = to_scsi_device(dev);
1420 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
1421 static struct _raid_device *raid_device;
1422 unsigned long flags;
1423 Mpi2RaidVolPage0_t vol_pg0;
1424 Mpi2ConfigReply_t mpi_reply;
1425 u32 volume_status_flags;
1426 u8 percent_complete;
1427 u16 handle;
1428
1429 percent_complete = 0;
1430 handle = 0;
1431 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1432 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1433 sdev->channel);
1434 if (raid_device) {
1435 handle = raid_device->handle;
1436 percent_complete = raid_device->percent_complete;
1437 }
1438 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1439
1440 if (!handle)
1441 goto out;
1442
1443 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1444 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
1445 sizeof(Mpi2RaidVolPage0_t))) {
1446 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1447 ioc->name, __FILE__, __LINE__, __func__);
1448 percent_complete = 0;
1449 goto out;
1450 }
1451
1452 volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1453 if (!(volume_status_flags &
1454 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
1455 percent_complete = 0;
1456
1457 out:
1458 raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
1459}
1460
1461/**
1462 * _scsih_get_state - get raid volume level
1463 * @dev the device struct object
1464 */
1465static void
1466_scsih_get_state(struct device *dev)
1467{
1468 struct scsi_device *sdev = to_scsi_device(dev);
1469 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
1470 static struct _raid_device *raid_device;
1471 unsigned long flags;
1472 Mpi2RaidVolPage0_t vol_pg0;
1473 Mpi2ConfigReply_t mpi_reply;
1474 u32 volstate;
1475 enum raid_state state = RAID_STATE_UNKNOWN;
1476 u16 handle = 0;
1477
1478 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1479 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1480 sdev->channel);
1481 if (raid_device)
1482 handle = raid_device->handle;
1483 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1484
1485 if (!raid_device)
1486 goto out;
1487
1488 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1489 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
1490 sizeof(Mpi2RaidVolPage0_t))) {
1491 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1492 ioc->name, __FILE__, __LINE__, __func__);
1493 goto out;
1494 }
1495
1496 volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1497 if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
1498 state = RAID_STATE_RESYNCING;
1499 goto out;
1500 }
1501
1502 switch (vol_pg0.VolumeState) {
1503 case MPI2_RAID_VOL_STATE_OPTIMAL:
1504 case MPI2_RAID_VOL_STATE_ONLINE:
1505 state = RAID_STATE_ACTIVE;
1506 break;
1507 case MPI2_RAID_VOL_STATE_DEGRADED:
1508 state = RAID_STATE_DEGRADED;
1509 break;
1510 case MPI2_RAID_VOL_STATE_FAILED:
1511 case MPI2_RAID_VOL_STATE_MISSING:
1512 state = RAID_STATE_OFFLINE;
1513 break;
1514 }
1515 out:
1516 raid_set_state(mpt3sas_raid_template, dev, state);
1517}
1518
1519/**
1520 * _scsih_set_level - set raid level
1521 * @sdev: scsi device struct
1522 * @volume_type: volume type
1523 */
1524static void
1525_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
1526{
1527 enum raid_level level = RAID_LEVEL_UNKNOWN;
1528
1529 switch (volume_type) {
1530 case MPI2_RAID_VOL_TYPE_RAID0:
1531 level = RAID_LEVEL_0;
1532 break;
1533 case MPI2_RAID_VOL_TYPE_RAID10:
1534 level = RAID_LEVEL_10;
1535 break;
1536 case MPI2_RAID_VOL_TYPE_RAID1E:
1537 level = RAID_LEVEL_1E;
1538 break;
1539 case MPI2_RAID_VOL_TYPE_RAID1:
1540 level = RAID_LEVEL_1;
1541 break;
1542 }
1543
1544 raid_set_level(mpt3sas_raid_template, &sdev->sdev_gendev, level);
1545}
1546
1547
1548/**
1549 * _scsih_get_volume_capabilities - volume capabilities
1550 * @ioc: per adapter object
1551 * @sas_device: the raid_device object
1552 *
1553 * Returns 0 for success, else 1
1554 */
1555static int
1556_scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
1557 struct _raid_device *raid_device)
1558{
1559 Mpi2RaidVolPage0_t *vol_pg0;
1560 Mpi2RaidPhysDiskPage0_t pd_pg0;
1561 Mpi2SasDevicePage0_t sas_device_pg0;
1562 Mpi2ConfigReply_t mpi_reply;
1563 u16 sz;
1564 u8 num_pds;
1565
1566 if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle,
1567 &num_pds)) || !num_pds) {
1568 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1569 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1570 __func__));
1571 return 1;
1572 }
1573
1574 raid_device->num_pds = num_pds;
1575 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1576 sizeof(Mpi2RaidVol0PhysDisk_t));
1577 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1578 if (!vol_pg0) {
1579 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1580 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1581 __func__));
1582 return 1;
1583 }
1584
1585 if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1586 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
1587 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1588 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1589 __func__));
1590 kfree(vol_pg0);
1591 return 1;
1592 }
1593
1594 raid_device->volume_type = vol_pg0->VolumeType;
1595
1596 /* figure out what the underlying devices are by
1597 * obtaining the device_info bits for the 1st device
1598 */
1599 if (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1600 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1601 vol_pg0->PhysDisk[0].PhysDiskNum))) {
1602 if (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
1603 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1604 le16_to_cpu(pd_pg0.DevHandle)))) {
1605 raid_device->device_info =
1606 le32_to_cpu(sas_device_pg0.DeviceInfo);
1607 }
1608 }
1609
1610 kfree(vol_pg0);
1611 return 0;
1612}
1613
1614
1615
1616/**
1617 * _scsih_enable_tlr - setting TLR flags
1618 * @ioc: per adapter object
1619 * @sdev: scsi device struct
1620 *
1621 * Enabling Transaction Layer Retries for tape devices when
1622 * vpd page 0x90 is present
1623 *
1624 */
1625static void
1626_scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
1627{
1628
1629 /* only for TAPE */
1630 if (sdev->type != TYPE_TAPE)
1631 return;
1632
1633 if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
1634 return;
1635
1636 sas_enable_tlr(sdev);
1637 sdev_printk(KERN_INFO, sdev, "TLR %s\n",
1638 sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
1639 return;
1640
1641}
1642
1643/**
1644 * _scsih_slave_configure - device configure routine.
1645 * @sdev: scsi device struct
1646 *
1647 * Returns 0 if ok. Any other return is assumed to be an error and
1648 * the device is ignored.
1649 */
1650static int
1651_scsih_slave_configure(struct scsi_device *sdev)
1652{
1653 struct Scsi_Host *shost = sdev->host;
1654 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1655 struct MPT3SAS_DEVICE *sas_device_priv_data;
1656 struct MPT3SAS_TARGET *sas_target_priv_data;
1657 struct _sas_device *sas_device;
1658 struct _raid_device *raid_device;
1659 unsigned long flags;
1660 int qdepth;
1661 u8 ssp_target = 0;
1662 char *ds = "";
1663 char *r_level = "";
1664 u16 handle, volume_handle = 0;
1665 u64 volume_wwid = 0;
1666
1667 qdepth = 1;
1668 sas_device_priv_data = sdev->hostdata;
1669 sas_device_priv_data->configured_lun = 1;
1670 sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
1671 sas_target_priv_data = sas_device_priv_data->sas_target;
1672 handle = sas_target_priv_data->handle;
1673
1674 /* raid volume handling */
1675 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
1676
1677 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1678 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
1679 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1680 if (!raid_device) {
1681 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1682 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1683 __LINE__, __func__));
1684 return 1;
1685 }
1686
1687 if (_scsih_get_volume_capabilities(ioc, raid_device)) {
1688 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1689 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1690 __LINE__, __func__));
1691 return 1;
1692 }
1693
1694
1695 /* RAID Queue Depth Support
1696 * IS volume = underlying qdepth of drive type, either
1697 * MPT3SAS_SAS_QUEUE_DEPTH or MPT3SAS_SATA_QUEUE_DEPTH
1698 * IM/IME/R10 = 128 (MPT3SAS_RAID_QUEUE_DEPTH)
1699 */
1700 if (raid_device->device_info &
1701 MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1702 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
1703 ds = "SSP";
1704 } else {
1705 qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
1706 if (raid_device->device_info &
1707 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1708 ds = "SATA";
1709 else
1710 ds = "STP";
1711 }
1712
1713 switch (raid_device->volume_type) {
1714 case MPI2_RAID_VOL_TYPE_RAID0:
1715 r_level = "RAID0";
1716 break;
1717 case MPI2_RAID_VOL_TYPE_RAID1E:
1718 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1719 if (ioc->manu_pg10.OEMIdentifier &&
1720 (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
1721 MFG10_GF0_R10_DISPLAY) &&
1722 !(raid_device->num_pds % 2))
1723 r_level = "RAID10";
1724 else
1725 r_level = "RAID1E";
1726 break;
1727 case MPI2_RAID_VOL_TYPE_RAID1:
1728 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1729 r_level = "RAID1";
1730 break;
1731 case MPI2_RAID_VOL_TYPE_RAID10:
1732 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1733 r_level = "RAID10";
1734 break;
1735 case MPI2_RAID_VOL_TYPE_UNKNOWN:
1736 default:
1737 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1738 r_level = "RAIDX";
1739 break;
1740 }
1741
1742 sdev_printk(KERN_INFO, sdev,
1743 "%s: handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n",
1744 r_level, raid_device->handle,
1745 (unsigned long long)raid_device->wwid,
1746 raid_device->num_pds, ds);
1747
1748
1749 _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
1750
1751/* raid transport support */
1752 _scsih_set_level(sdev, raid_device->volume_type);
1753 return 0;
1754 }
1755
1756 /* non-raid handling */
1757 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1758 if (mpt3sas_config_get_volume_handle(ioc, handle,
1759 &volume_handle)) {
1760 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1761 "failure at %s:%d/%s()!\n", ioc->name,
1762 __FILE__, __LINE__, __func__));
1763 return 1;
1764 }
1765 if (volume_handle && mpt3sas_config_get_volume_wwid(ioc,
1766 volume_handle, &volume_wwid)) {
1767 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1768 "failure at %s:%d/%s()!\n", ioc->name,
1769 __FILE__, __LINE__, __func__));
1770 return 1;
1771 }
1772 }
1773
1774 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1775 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1776 sas_device_priv_data->sas_target->sas_address);
1777 if (!sas_device) {
1778 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1779 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1780 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1781 __func__));
1782 return 1;
1783 }
1784
1785 sas_device->volume_handle = volume_handle;
1786 sas_device->volume_wwid = volume_wwid;
1787 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1788 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
1789 ssp_target = 1;
1790 ds = "SSP";
1791 } else {
1792 qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
1793 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
1794 ds = "STP";
1795 else if (sas_device->device_info &
1796 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1797 ds = "SATA";
1798 }
1799
1800 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " \
1801 "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
1802 ds, handle, (unsigned long long)sas_device->sas_address,
1803 sas_device->phy, (unsigned long long)sas_device->device_name);
1804 sdev_printk(KERN_INFO, sdev,
1805 "%s: enclosure_logical_id(0x%016llx), slot(%d)\n",
1806 ds, (unsigned long long)
1807 sas_device->enclosure_logical_id, sas_device->slot);
1808
1809 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1810
1811 if (!ssp_target)
1812 _scsih_display_sata_capabilities(ioc, handle, sdev);
1813
1814
1815 _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
1816
1817 if (ssp_target) {
1818 sas_read_port_mode_page(sdev);
1819 _scsih_enable_tlr(ioc, sdev);
1820 }
1821
1822 return 0;
1823}
1824
1825/**
1826 * _scsih_bios_param - fetch head, sector, cylinder info for a disk
1827 * @sdev: scsi device struct
1828 * @bdev: pointer to block device context
1829 * @capacity: device size (in 512 byte sectors)
1830 * @params: three element array to place output:
1831 * params[0] number of heads (max 255)
1832 * params[1] number of sectors (max 63)
1833 * params[2] number of cylinders
1834 *
1835 * Return nothing.
1836 */
1837static int
1838_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
1839 sector_t capacity, int params[])
1840{
1841 int heads;
1842 int sectors;
1843 sector_t cylinders;
1844 ulong dummy;
1845
1846 heads = 64;
1847 sectors = 32;
1848
1849 dummy = heads * sectors;
1850 cylinders = capacity;
1851 sector_div(cylinders, dummy);
1852
1853 /*
1854 * Handle extended translation size for logical drives
1855 * > 1Gb
1856 */
1857 if ((ulong)capacity >= 0x200000) {
1858 heads = 255;
1859 sectors = 63;
1860 dummy = heads * sectors;
1861 cylinders = capacity;
1862 sector_div(cylinders, dummy);
1863 }
1864
1865 /* return result */
1866 params[0] = heads;
1867 params[1] = sectors;
1868 params[2] = cylinders;
1869
1870 return 0;
1871}
1872
1873/**
1874 * _scsih_response_code - translation of device response code
1875 * @ioc: per adapter object
1876 * @response_code: response code returned by the device
1877 *
1878 * Return nothing.
1879 */
1880static void
1881_scsih_response_code(struct MPT3SAS_ADAPTER *ioc, u8 response_code)
1882{
1883 char *desc;
1884
1885 switch (response_code) {
1886 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
1887 desc = "task management request completed";
1888 break;
1889 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
1890 desc = "invalid frame";
1891 break;
1892 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
1893 desc = "task management request not supported";
1894 break;
1895 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
1896 desc = "task management request failed";
1897 break;
1898 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
1899 desc = "task management request succeeded";
1900 break;
1901 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
1902 desc = "invalid lun";
1903 break;
1904 case 0xA:
1905 desc = "overlapped tag attempted";
1906 break;
1907 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
1908 desc = "task queued, however not sent to target";
1909 break;
1910 default:
1911 desc = "unknown";
1912 break;
1913 }
1914 pr_warn(MPT3SAS_FMT "response_code(0x%01x): %s\n",
1915 ioc->name, response_code, desc);
1916}
1917
1918/**
1919 * _scsih_tm_done - tm completion routine
1920 * @ioc: per adapter object
1921 * @smid: system request message index
1922 * @msix_index: MSIX table index supplied by the OS
1923 * @reply: reply message frame(lower 32bit addr)
1924 * Context: none.
1925 *
1926 * The callback handler when using scsih_issue_tm.
1927 *
1928 * Return 1 meaning mf should be freed from _base_interrupt
1929 * 0 means the mf is freed from this function.
1930 */
1931static u8
1932_scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
1933{
1934 MPI2DefaultReply_t *mpi_reply;
1935
1936 if (ioc->tm_cmds.status == MPT3_CMD_NOT_USED)
1937 return 1;
1938 if (ioc->tm_cmds.smid != smid)
1939 return 1;
1940 mpt3sas_base_flush_reply_queues(ioc);
1941 ioc->tm_cmds.status |= MPT3_CMD_COMPLETE;
1942 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
1943 if (mpi_reply) {
1944 memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
1945 ioc->tm_cmds.status |= MPT3_CMD_REPLY_VALID;
1946 }
1947 ioc->tm_cmds.status &= ~MPT3_CMD_PENDING;
1948 complete(&ioc->tm_cmds.done);
1949 return 1;
1950}
1951
1952/**
1953 * mpt3sas_scsih_set_tm_flag - set per target tm_busy
1954 * @ioc: per adapter object
1955 * @handle: device handle
1956 *
1957 * During taskmangement request, we need to freeze the device queue.
1958 */
1959void
1960mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
1961{
1962 struct MPT3SAS_DEVICE *sas_device_priv_data;
1963 struct scsi_device *sdev;
1964 u8 skip = 0;
1965
1966 shost_for_each_device(sdev, ioc->shost) {
1967 if (skip)
1968 continue;
1969 sas_device_priv_data = sdev->hostdata;
1970 if (!sas_device_priv_data)
1971 continue;
1972 if (sas_device_priv_data->sas_target->handle == handle) {
1973 sas_device_priv_data->sas_target->tm_busy = 1;
1974 skip = 1;
1975 ioc->ignore_loginfos = 1;
1976 }
1977 }
1978}
1979
1980/**
1981 * mpt3sas_scsih_clear_tm_flag - clear per target tm_busy
1982 * @ioc: per adapter object
1983 * @handle: device handle
1984 *
1985 * During taskmangement request, we need to freeze the device queue.
1986 */
1987void
1988mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
1989{
1990 struct MPT3SAS_DEVICE *sas_device_priv_data;
1991 struct scsi_device *sdev;
1992 u8 skip = 0;
1993
1994 shost_for_each_device(sdev, ioc->shost) {
1995 if (skip)
1996 continue;
1997 sas_device_priv_data = sdev->hostdata;
1998 if (!sas_device_priv_data)
1999 continue;
2000 if (sas_device_priv_data->sas_target->handle == handle) {
2001 sas_device_priv_data->sas_target->tm_busy = 0;
2002 skip = 1;
2003 ioc->ignore_loginfos = 0;
2004 }
2005 }
2006}
2007
2008/**
2009 * mpt3sas_scsih_issue_tm - main routine for sending tm requests
2010 * @ioc: per adapter struct
2011 * @device_handle: device handle
2012 * @channel: the channel assigned by the OS
2013 * @id: the id assigned by the OS
2014 * @lun: lun number
2015 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
2016 * @smid_task: smid assigned to the task
2017 * @timeout: timeout in seconds
2018 * @serial_number: the serial_number from scmd
2019 * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
2020 * Context: user
2021 *
2022 * A generic API for sending task management requests to firmware.
2023 *
2024 * The callback index is set inside `ioc->tm_cb_idx`.
2025 *
2026 * Return SUCCESS or FAILED.
2027 */
2028int
2029mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
2030 uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
2031 unsigned long serial_number, enum mutex_type m_type)
2032{
2033 Mpi2SCSITaskManagementRequest_t *mpi_request;
2034 Mpi2SCSITaskManagementReply_t *mpi_reply;
2035 u16 smid = 0;
2036 u32 ioc_state;
2037 unsigned long timeleft;
2038 struct scsiio_tracker *scsi_lookup = NULL;
2039 int rc;
2040
2041 if (m_type == TM_MUTEX_ON)
2042 mutex_lock(&ioc->tm_cmds.mutex);
2043 if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) {
2044 pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n",
2045 __func__, ioc->name);
2046 rc = FAILED;
2047 goto err_out;
2048 }
2049
2050 if (ioc->shost_recovery || ioc->remove_host ||
2051 ioc->pci_error_recovery) {
2052 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
2053 __func__, ioc->name);
2054 rc = FAILED;
2055 goto err_out;
2056 }
2057
2058 ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
2059 if (ioc_state & MPI2_DOORBELL_USED) {
2060 dhsprintk(ioc, pr_info(MPT3SAS_FMT
2061 "unexpected doorbell active!\n", ioc->name));
2062 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2063 FORCE_BIG_HAMMER);
2064 rc = (!rc) ? SUCCESS : FAILED;
2065 goto err_out;
2066 }
2067
2068 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
2069 mpt3sas_base_fault_info(ioc, ioc_state &
2070 MPI2_DOORBELL_DATA_MASK);
2071 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2072 FORCE_BIG_HAMMER);
2073 rc = (!rc) ? SUCCESS : FAILED;
2074 goto err_out;
2075 }
2076
2077 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
2078 if (!smid) {
2079 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2080 ioc->name, __func__);
2081 rc = FAILED;
2082 goto err_out;
2083 }
2084
2085 if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2086 scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
2087
2088 dtmprintk(ioc, pr_info(MPT3SAS_FMT
2089 "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
2090 ioc->name, handle, type, smid_task));
2091 ioc->tm_cmds.status = MPT3_CMD_PENDING;
2092 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2093 ioc->tm_cmds.smid = smid;
2094 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
2095 memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
2096 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
2097 mpi_request->DevHandle = cpu_to_le16(handle);
2098 mpi_request->TaskType = type;
2099 mpi_request->TaskMID = cpu_to_le16(smid_task);
2100 int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
2101 mpt3sas_scsih_set_tm_flag(ioc, handle);
2102 init_completion(&ioc->tm_cmds.done);
2103 mpt3sas_base_put_smid_hi_priority(ioc, smid);
2104 timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
2105 if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
2106 pr_err(MPT3SAS_FMT "%s: timeout\n",
2107 ioc->name, __func__);
2108 _debug_dump_mf(mpi_request,
2109 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2110 if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) {
2111 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2112 FORCE_BIG_HAMMER);
2113 rc = (!rc) ? SUCCESS : FAILED;
2114 ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
2115 mpt3sas_scsih_clear_tm_flag(ioc, handle);
2116 goto err_out;
2117 }
2118 }
2119
2120 if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) {
2121 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
2122 mpi_reply = ioc->tm_cmds.reply;
2123 dtmprintk(ioc, pr_info(MPT3SAS_FMT "complete tm: " \
2124 "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
2125 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
2126 le32_to_cpu(mpi_reply->IOCLogInfo),
2127 le32_to_cpu(mpi_reply->TerminationCount)));
2128 if (ioc->logging_level & MPT_DEBUG_TM) {
2129 _scsih_response_code(ioc, mpi_reply->ResponseCode);
2130 if (mpi_reply->IOCStatus)
2131 _debug_dump_mf(mpi_request,
2132 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2133 }
2134 }
2135
2136 switch (type) {
2137 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2138 rc = SUCCESS;
2139 if (scsi_lookup->scmd == NULL)
2140 break;
2141 rc = FAILED;
2142 break;
2143
2144 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2145 if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
2146 rc = FAILED;
2147 else
2148 rc = SUCCESS;
2149 break;
2150 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
2151 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
2152 if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
2153 rc = FAILED;
2154 else
2155 rc = SUCCESS;
2156 break;
2157 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
2158 rc = SUCCESS;
2159 break;
2160 default:
2161 rc = FAILED;
2162 break;
2163 }
2164
2165 mpt3sas_scsih_clear_tm_flag(ioc, handle);
2166 ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
2167 if (m_type == TM_MUTEX_ON)
2168 mutex_unlock(&ioc->tm_cmds.mutex);
2169
2170 return rc;
2171
2172 err_out:
2173 if (m_type == TM_MUTEX_ON)
2174 mutex_unlock(&ioc->tm_cmds.mutex);
2175 return rc;
2176}
2177
2178/**
2179 * _scsih_tm_display_info - displays info about the device
2180 * @ioc: per adapter struct
2181 * @scmd: pointer to scsi command object
2182 *
2183 * Called by task management callback handlers.
2184 */
2185static void
2186_scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
2187{
2188 struct scsi_target *starget = scmd->device->sdev_target;
2189 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
2190 struct _sas_device *sas_device = NULL;
2191 unsigned long flags;
2192 char *device_str = NULL;
2193
2194 if (!priv_target)
2195 return;
2196 device_str = "volume";
2197
2198 scsi_print_command(scmd);
2199 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2200 starget_printk(KERN_INFO, starget,
2201 "%s handle(0x%04x), %s wwid(0x%016llx)\n",
2202 device_str, priv_target->handle,
2203 device_str, (unsigned long long)priv_target->sas_address);
2204 } else {
2205 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2206 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
2207 priv_target->sas_address);
2208 if (sas_device) {
2209 if (priv_target->flags &
2210 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2211 starget_printk(KERN_INFO, starget,
2212 "volume handle(0x%04x), "
2213 "volume wwid(0x%016llx)\n",
2214 sas_device->volume_handle,
2215 (unsigned long long)sas_device->volume_wwid);
2216 }
2217 starget_printk(KERN_INFO, starget,
2218 "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
2219 sas_device->handle,
2220 (unsigned long long)sas_device->sas_address,
2221 sas_device->phy);
2222 starget_printk(KERN_INFO, starget,
2223 "enclosure_logical_id(0x%016llx), slot(%d)\n",
2224 (unsigned long long)sas_device->enclosure_logical_id,
2225 sas_device->slot);
2226 }
2227 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2228 }
2229}
2230
2231/**
2232 * _scsih_abort - eh threads main abort routine
2233 * @scmd: pointer to scsi command object
2234 *
2235 * Returns SUCCESS if command aborted else FAILED
2236 */
2237static int
2238_scsih_abort(struct scsi_cmnd *scmd)
2239{
2240 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2241 struct MPT3SAS_DEVICE *sas_device_priv_data;
2242 u16 smid;
2243 u16 handle;
2244 int r;
2245
2246 sdev_printk(KERN_INFO, scmd->device,
2247 "attempting task abort! scmd(%p)\n", scmd);
2248 _scsih_tm_display_info(ioc, scmd);
2249
2250 sas_device_priv_data = scmd->device->hostdata;
2251 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2252 sdev_printk(KERN_INFO, scmd->device,
2253 "device been deleted! scmd(%p)\n", scmd);
2254 scmd->result = DID_NO_CONNECT << 16;
2255 scmd->scsi_done(scmd);
2256 r = SUCCESS;
2257 goto out;
2258 }
2259
2260 /* search for the command */
2261 smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
2262 if (!smid) {
2263 scmd->result = DID_RESET << 16;
2264 r = SUCCESS;
2265 goto out;
2266 }
2267
2268 /* for hidden raid components and volumes this is not supported */
2269 if (sas_device_priv_data->sas_target->flags &
2270 MPT_TARGET_FLAGS_RAID_COMPONENT ||
2271 sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2272 scmd->result = DID_RESET << 16;
2273 r = FAILED;
2274 goto out;
2275 }
2276
2277 mpt3sas_halt_firmware(ioc);
2278
2279 handle = sas_device_priv_data->sas_target->handle;
2280 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2281 scmd->device->id, scmd->device->lun,
2282 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
2283 scmd->serial_number, TM_MUTEX_ON);
2284
2285 out:
2286 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
2287 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2288 return r;
2289}
2290
2291/**
2292 * _scsih_dev_reset - eh threads main device reset routine
2293 * @scmd: pointer to scsi command object
2294 *
2295 * Returns SUCCESS if command aborted else FAILED
2296 */
2297static int
2298_scsih_dev_reset(struct scsi_cmnd *scmd)
2299{
2300 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2301 struct MPT3SAS_DEVICE *sas_device_priv_data;
2302 struct _sas_device *sas_device;
2303 unsigned long flags;
2304 u16 handle;
2305 int r;
2306
2307 sdev_printk(KERN_INFO, scmd->device,
2308 "attempting device reset! scmd(%p)\n", scmd);
2309 _scsih_tm_display_info(ioc, scmd);
2310
2311 sas_device_priv_data = scmd->device->hostdata;
2312 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2313 sdev_printk(KERN_INFO, scmd->device,
2314 "device been deleted! scmd(%p)\n", scmd);
2315 scmd->result = DID_NO_CONNECT << 16;
2316 scmd->scsi_done(scmd);
2317 r = SUCCESS;
2318 goto out;
2319 }
2320
2321 /* for hidden raid components obtain the volume_handle */
2322 handle = 0;
2323 if (sas_device_priv_data->sas_target->flags &
2324 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2325 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2326 sas_device = _scsih_sas_device_find_by_handle(ioc,
2327 sas_device_priv_data->sas_target->handle);
2328 if (sas_device)
2329 handle = sas_device->volume_handle;
2330 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2331 } else
2332 handle = sas_device_priv_data->sas_target->handle;
2333
2334 if (!handle) {
2335 scmd->result = DID_RESET << 16;
2336 r = FAILED;
2337 goto out;
2338 }
2339
2340 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2341 scmd->device->id, scmd->device->lun,
2342 MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0,
2343 TM_MUTEX_ON);
2344
2345 out:
2346 sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
2347 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2348 return r;
2349}
2350
2351/**
2352 * _scsih_target_reset - eh threads main target reset routine
2353 * @scmd: pointer to scsi command object
2354 *
2355 * Returns SUCCESS if command aborted else FAILED
2356 */
2357static int
2358_scsih_target_reset(struct scsi_cmnd *scmd)
2359{
2360 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2361 struct MPT3SAS_DEVICE *sas_device_priv_data;
2362 struct _sas_device *sas_device;
2363 unsigned long flags;
2364 u16 handle;
2365 int r;
2366 struct scsi_target *starget = scmd->device->sdev_target;
2367
2368 starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n",
2369 scmd);
2370 _scsih_tm_display_info(ioc, scmd);
2371
2372 sas_device_priv_data = scmd->device->hostdata;
2373 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2374 starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n",
2375 scmd);
2376 scmd->result = DID_NO_CONNECT << 16;
2377 scmd->scsi_done(scmd);
2378 r = SUCCESS;
2379 goto out;
2380 }
2381
2382 /* for hidden raid components obtain the volume_handle */
2383 handle = 0;
2384 if (sas_device_priv_data->sas_target->flags &
2385 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2386 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2387 sas_device = _scsih_sas_device_find_by_handle(ioc,
2388 sas_device_priv_data->sas_target->handle);
2389 if (sas_device)
2390 handle = sas_device->volume_handle;
2391 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2392 } else
2393 handle = sas_device_priv_data->sas_target->handle;
2394
2395 if (!handle) {
2396 scmd->result = DID_RESET << 16;
2397 r = FAILED;
2398 goto out;
2399 }
2400
2401 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2402 scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
2403 30, 0, TM_MUTEX_ON);
2404
2405 out:
2406 starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
2407 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2408 return r;
2409}
2410
2411
2412/**
2413 * _scsih_host_reset - eh threads main host reset routine
2414 * @scmd: pointer to scsi command object
2415 *
2416 * Returns SUCCESS if command aborted else FAILED
2417 */
2418static int
2419_scsih_host_reset(struct scsi_cmnd *scmd)
2420{
2421 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2422 int r, retval;
2423
2424 pr_info(MPT3SAS_FMT "attempting host reset! scmd(%p)\n",
2425 ioc->name, scmd);
2426 scsi_print_command(scmd);
2427
2428 retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2429 FORCE_BIG_HAMMER);
2430 r = (retval < 0) ? FAILED : SUCCESS;
2431 pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n",
2432 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2433
2434 return r;
2435}
2436
2437/**
2438 * _scsih_fw_event_add - insert and queue up fw_event
2439 * @ioc: per adapter object
2440 * @fw_event: object describing the event
2441 * Context: This function will acquire ioc->fw_event_lock.
2442 *
2443 * This adds the firmware event object into link list, then queues it up to
2444 * be processed from user context.
2445 *
2446 * Return nothing.
2447 */
2448static void
2449_scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
2450{
2451 unsigned long flags;
2452
2453 if (ioc->firmware_event_thread == NULL)
2454 return;
2455
2456 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2457 INIT_LIST_HEAD(&fw_event->list);
2458 list_add_tail(&fw_event->list, &ioc->fw_event_list);
2459 INIT_WORK(&fw_event->work, _firmware_event_work);
2460 queue_work(ioc->firmware_event_thread, &fw_event->work);
2461 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2462}
2463
2464/**
2465 * _scsih_fw_event_free - delete fw_event
2466 * @ioc: per adapter object
2467 * @fw_event: object describing the event
2468 * Context: This function will acquire ioc->fw_event_lock.
2469 *
2470 * This removes firmware event object from link list, frees associated memory.
2471 *
2472 * Return nothing.
2473 */
2474static void
2475_scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
2476 *fw_event)
2477{
2478 unsigned long flags;
2479
2480 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2481 list_del(&fw_event->list);
2482 kfree(fw_event->event_data);
2483 kfree(fw_event);
2484 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2485}
2486
2487
2488 /**
2489 * mpt3sas_send_trigger_data_event - send event for processing trigger data
2490 * @ioc: per adapter object
2491 * @event_data: trigger event data
2492 *
2493 * Return nothing.
2494 */
2495void
2496mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
2497 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
2498{
2499 struct fw_event_work *fw_event;
2500
2501 if (ioc->is_driver_loading)
2502 return;
2503 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2504 if (!fw_event)
2505 return;
2506 fw_event->event_data = kzalloc(sizeof(*event_data), GFP_ATOMIC);
2507 if (!fw_event->event_data)
2508 return;
2509 fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
2510 fw_event->ioc = ioc;
2511 memcpy(fw_event->event_data, event_data, sizeof(*event_data));
2512 _scsih_fw_event_add(ioc, fw_event);
2513}
2514
2515/**
2516 * _scsih_error_recovery_delete_devices - remove devices not responding
2517 * @ioc: per adapter object
2518 *
2519 * Return nothing.
2520 */
2521static void
2522_scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc)
2523{
2524 struct fw_event_work *fw_event;
2525
2526 if (ioc->is_driver_loading)
2527 return;
2528 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2529 if (!fw_event)
2530 return;
2531 fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
2532 fw_event->ioc = ioc;
2533 _scsih_fw_event_add(ioc, fw_event);
2534}
2535
2536/**
2537 * mpt3sas_port_enable_complete - port enable completed (fake event)
2538 * @ioc: per adapter object
2539 *
2540 * Return nothing.
2541 */
2542void
2543mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
2544{
2545 struct fw_event_work *fw_event;
2546
2547 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2548 if (!fw_event)
2549 return;
2550 fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE;
2551 fw_event->ioc = ioc;
2552 _scsih_fw_event_add(ioc, fw_event);
2553}
2554
2555/**
2556 * _scsih_fw_event_cleanup_queue - cleanup event queue
2557 * @ioc: per adapter object
2558 *
2559 * Walk the firmware event queue, either killing timers, or waiting
2560 * for outstanding events to complete
2561 *
2562 * Return nothing.
2563 */
2564static void
2565_scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
2566{
2567 struct fw_event_work *fw_event, *next;
2568
2569 if (list_empty(&ioc->fw_event_list) ||
2570 !ioc->firmware_event_thread || in_interrupt())
2571 return;
2572
2573 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
2574 if (cancel_delayed_work(&fw_event->delayed_work)) {
2575 _scsih_fw_event_free(ioc, fw_event);
2576 continue;
2577 }
2578 fw_event->cancel_pending_work = 1;
2579 }
2580}
2581
2582/**
2583 * _scsih_ublock_io_all_device - unblock every device
2584 * @ioc: per adapter object
2585 *
2586 * change the device state from block to running
2587 */
2588static void
2589_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
2590{
2591 struct MPT3SAS_DEVICE *sas_device_priv_data;
2592 struct scsi_device *sdev;
2593
2594 shost_for_each_device(sdev, ioc->shost) {
2595 sas_device_priv_data = sdev->hostdata;
2596 if (!sas_device_priv_data)
2597 continue;
2598 if (!sas_device_priv_data->block)
2599 continue;
2600
2601 sas_device_priv_data->block = 0;
2602 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2603 "device_running, handle(0x%04x)\n",
2604 sas_device_priv_data->sas_target->handle));
2605 scsi_internal_device_unblock(sdev, SDEV_RUNNING);
2606 }
2607}
2608
2609
2610/**
2611 * _scsih_ublock_io_device - prepare device to be deleted
2612 * @ioc: per adapter object
2613 * @sas_addr: sas address
2614 *
2615 * unblock then put device in offline state
2616 */
2617static void
2618_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
2619{
2620 struct MPT3SAS_DEVICE *sas_device_priv_data;
2621 struct scsi_device *sdev;
2622
2623 shost_for_each_device(sdev, ioc->shost) {
2624 sas_device_priv_data = sdev->hostdata;
2625 if (!sas_device_priv_data)
2626 continue;
2627 if (sas_device_priv_data->sas_target->sas_address
2628 != sas_address)
2629 continue;
2630 if (sas_device_priv_data->block) {
2631 sas_device_priv_data->block = 0;
2632 scsi_internal_device_unblock(sdev, SDEV_RUNNING);
2633 }
2634 }
2635}
2636
2637/**
2638 * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
2639 * @ioc: per adapter object
2640 * @handle: device handle
2641 *
2642 * During device pull we need to appropiately set the sdev state.
2643 */
2644static void
2645_scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc)
2646{
2647 struct MPT3SAS_DEVICE *sas_device_priv_data;
2648 struct scsi_device *sdev;
2649
2650 shost_for_each_device(sdev, ioc->shost) {
2651 sas_device_priv_data = sdev->hostdata;
2652 if (!sas_device_priv_data)
2653 continue;
2654 if (sas_device_priv_data->block)
2655 continue;
2656 sas_device_priv_data->block = 1;
2657 scsi_internal_device_block(sdev);
2658 sdev_printk(KERN_INFO, sdev, "device_blocked, handle(0x%04x)\n",
2659 sas_device_priv_data->sas_target->handle);
2660 }
2661}
2662
2663/**
2664 * _scsih_block_io_device - set the device state to SDEV_BLOCK
2665 * @ioc: per adapter object
2666 * @handle: device handle
2667 *
2668 * During device pull we need to appropiately set the sdev state.
2669 */
2670static void
2671_scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2672{
2673 struct MPT3SAS_DEVICE *sas_device_priv_data;
2674 struct scsi_device *sdev;
2675
2676 shost_for_each_device(sdev, ioc->shost) {
2677 sas_device_priv_data = sdev->hostdata;
2678 if (!sas_device_priv_data)
2679 continue;
2680 if (sas_device_priv_data->sas_target->handle != handle)
2681 continue;
2682 if (sas_device_priv_data->block)
2683 continue;
2684 sas_device_priv_data->block = 1;
2685 scsi_internal_device_block(sdev);
2686 sdev_printk(KERN_INFO, sdev,
2687 "device_blocked, handle(0x%04x)\n", handle);
2688 }
2689}
2690
2691/**
2692 * _scsih_block_io_to_children_attached_to_ex
2693 * @ioc: per adapter object
2694 * @sas_expander: the sas_device object
2695 *
2696 * This routine set sdev state to SDEV_BLOCK for all devices
2697 * attached to this expander. This function called when expander is
2698 * pulled.
2699 */
2700static void
2701_scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
2702 struct _sas_node *sas_expander)
2703{
2704 struct _sas_port *mpt3sas_port;
2705 struct _sas_device *sas_device;
2706 struct _sas_node *expander_sibling;
2707 unsigned long flags;
2708
2709 if (!sas_expander)
2710 return;
2711
2712 list_for_each_entry(mpt3sas_port,
2713 &sas_expander->sas_port_list, port_list) {
2714 if (mpt3sas_port->remote_identify.device_type ==
2715 SAS_END_DEVICE) {
2716 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2717 sas_device =
2718 mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
2719 mpt3sas_port->remote_identify.sas_address);
2720 if (sas_device)
2721 set_bit(sas_device->handle,
2722 ioc->blocking_handles);
2723 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2724 }
2725 }
2726
2727 list_for_each_entry(mpt3sas_port,
2728 &sas_expander->sas_port_list, port_list) {
2729
2730 if (mpt3sas_port->remote_identify.device_type ==
2731 SAS_EDGE_EXPANDER_DEVICE ||
2732 mpt3sas_port->remote_identify.device_type ==
2733 SAS_FANOUT_EXPANDER_DEVICE) {
2734 expander_sibling =
2735 mpt3sas_scsih_expander_find_by_sas_address(
2736 ioc, mpt3sas_port->remote_identify.sas_address);
2737 _scsih_block_io_to_children_attached_to_ex(ioc,
2738 expander_sibling);
2739 }
2740 }
2741}
2742
2743/**
2744 * _scsih_block_io_to_children_attached_directly
2745 * @ioc: per adapter object
2746 * @event_data: topology change event data
2747 *
2748 * This routine set sdev state to SDEV_BLOCK for all devices
2749 * direct attached during device pull.
2750 */
2751static void
2752_scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc,
2753 Mpi2EventDataSasTopologyChangeList_t *event_data)
2754{
2755 int i;
2756 u16 handle;
2757 u16 reason_code;
2758 u8 phy_number;
2759
2760 for (i = 0; i < event_data->NumEntries; i++) {
2761 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
2762 if (!handle)
2763 continue;
2764 phy_number = event_data->StartPhyNum + i;
2765 reason_code = event_data->PHY[i].PhyStatus &
2766 MPI2_EVENT_SAS_TOPO_RC_MASK;
2767 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
2768 _scsih_block_io_device(ioc, handle);
2769 }
2770}
2771
2772/**
2773 * _scsih_tm_tr_send - send task management request
2774 * @ioc: per adapter object
2775 * @handle: device handle
2776 * Context: interrupt time.
2777 *
2778 * This code is to initiate the device removal handshake protocol
2779 * with controller firmware. This function will issue target reset
2780 * using high priority request queue. It will send a sas iounit
2781 * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
2782 *
2783 * This is designed to send muliple task management request at the same
2784 * time to the fifo. If the fifo is full, we will append the request,
2785 * and process it in a future completion.
2786 */
2787static void
2788_scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2789{
2790 Mpi2SCSITaskManagementRequest_t *mpi_request;
2791 u16 smid;
2792 struct _sas_device *sas_device;
2793 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
2794 u64 sas_address = 0;
2795 unsigned long flags;
2796 struct _tr_list *delayed_tr;
2797 u32 ioc_state;
2798
2799 if (ioc->remove_host) {
2800 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2801 "%s: host has been removed: handle(0x%04x)\n",
2802 __func__, ioc->name, handle));
2803 return;
2804 } else if (ioc->pci_error_recovery) {
2805 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2806 "%s: host in pci error recovery: handle(0x%04x)\n",
2807 __func__, ioc->name,
2808 handle));
2809 return;
2810 }
2811 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
2812 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
2813 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2814 "%s: host is not operational: handle(0x%04x)\n",
2815 __func__, ioc->name,
2816 handle));
2817 return;
2818 }
2819
2820 /* if PD, then return */
2821 if (test_bit(handle, ioc->pd_handles))
2822 return;
2823
2824 spin_lock_irqsave(&ioc->sas_device_lock, flags);
2825 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
2826 if (sas_device && sas_device->starget &&
2827 sas_device->starget->hostdata) {
2828 sas_target_priv_data = sas_device->starget->hostdata;
2829 sas_target_priv_data->deleted = 1;
2830 sas_address = sas_device->sas_address;
2831 }
2832 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2833
2834 if (sas_target_priv_data) {
2835 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2836 "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n",
2837 ioc->name, handle,
2838 (unsigned long long)sas_address));
2839 _scsih_ublock_io_device(ioc, sas_address);
2840 sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
2841 }
2842
2843 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
2844 if (!smid) {
2845 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
2846 if (!delayed_tr)
2847 return;
2848 INIT_LIST_HEAD(&delayed_tr->list);
2849 delayed_tr->handle = handle;
2850 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
2851 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2852 "DELAYED:tr:handle(0x%04x), (open)\n",
2853 ioc->name, handle));
2854 return;
2855 }
2856
2857 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2858 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
2859 ioc->name, handle, smid,
2860 ioc->tm_tr_cb_idx));
2861 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2862 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
2863 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
2864 mpi_request->DevHandle = cpu_to_le16(handle);
2865 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
2866 mpt3sas_base_put_smid_hi_priority(ioc, smid);
2867 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
2868}
2869
2870/**
2871 * _scsih_tm_tr_complete -
2872 * @ioc: per adapter object
2873 * @smid: system request message index
2874 * @msix_index: MSIX table index supplied by the OS
2875 * @reply: reply message frame(lower 32bit addr)
2876 * Context: interrupt time.
2877 *
2878 * This is the target reset completion routine.
2879 * This code is part of the code to initiate the device removal
2880 * handshake protocol with controller firmware.
2881 * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
2882 *
2883 * Return 1 meaning mf should be freed from _base_interrupt
2884 * 0 means the mf is freed from this function.
2885 */
2886static u8
2887_scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
2888 u32 reply)
2889{
2890 u16 handle;
2891 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
2892 Mpi2SCSITaskManagementReply_t *mpi_reply =
2893 mpt3sas_base_get_reply_virt_addr(ioc, reply);
2894 Mpi2SasIoUnitControlRequest_t *mpi_request;
2895 u16 smid_sas_ctrl;
2896 u32 ioc_state;
2897
2898 if (ioc->remove_host) {
2899 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2900 "%s: host has been removed\n", __func__, ioc->name));
2901 return 1;
2902 } else if (ioc->pci_error_recovery) {
2903 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2904 "%s: host in pci error recovery\n", __func__,
2905 ioc->name));
2906 return 1;
2907 }
2908 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
2909 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
2910 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2911 "%s: host is not operational\n", __func__, ioc->name));
2912 return 1;
2913 }
2914 if (unlikely(!mpi_reply)) {
2915 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
2916 ioc->name, __FILE__, __LINE__, __func__);
2917 return 1;
2918 }
2919 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
2920 handle = le16_to_cpu(mpi_request_tm->DevHandle);
2921 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
2922 dewtprintk(ioc, pr_err(MPT3SAS_FMT
2923 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
2924 ioc->name, handle,
2925 le16_to_cpu(mpi_reply->DevHandle), smid));
2926 return 0;
2927 }
2928
2929 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
2930 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2931 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
2932 "loginfo(0x%08x), completed(%d)\n", ioc->name,
2933 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
2934 le32_to_cpu(mpi_reply->IOCLogInfo),
2935 le32_to_cpu(mpi_reply->TerminationCount)));
2936
2937 smid_sas_ctrl = mpt3sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
2938 if (!smid_sas_ctrl) {
2939 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2940 ioc->name, __func__);
2941 return 1;
2942 }
2943
2944 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2945 "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
2946 ioc->name, handle, smid_sas_ctrl,
2947 ioc->tm_sas_control_cb_idx));
2948 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid_sas_ctrl);
2949 memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
2950 mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
2951 mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
2952 mpi_request->DevHandle = mpi_request_tm->DevHandle;
2953 mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl);
2954
2955 return _scsih_check_for_pending_tm(ioc, smid);
2956}
2957
2958
2959/**
2960 * _scsih_sas_control_complete - completion routine
2961 * @ioc: per adapter object
2962 * @smid: system request message index
2963 * @msix_index: MSIX table index supplied by the OS
2964 * @reply: reply message frame(lower 32bit addr)
2965 * Context: interrupt time.
2966 *
2967 * This is the sas iounit control completion routine.
2968 * This code is part of the code to initiate the device removal
2969 * handshake protocol with controller firmware.
2970 *
2971 * Return 1 meaning mf should be freed from _base_interrupt
2972 * 0 means the mf is freed from this function.
2973 */
2974static u8
2975_scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
2976 u8 msix_index, u32 reply)
2977{
2978 Mpi2SasIoUnitControlReply_t *mpi_reply =
2979 mpt3sas_base_get_reply_virt_addr(ioc, reply);
2980
2981 if (likely(mpi_reply)) {
2982 dewtprintk(ioc, pr_info(MPT3SAS_FMT
2983 "sc_complete:handle(0x%04x), (open) "
2984 "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
2985 ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
2986 le16_to_cpu(mpi_reply->IOCStatus),
2987 le32_to_cpu(mpi_reply->IOCLogInfo)));
2988 } else {
2989 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
2990 ioc->name, __FILE__, __LINE__, __func__);
2991 }
2992 return 1;
2993}
2994
2995/**
2996 * _scsih_tm_tr_volume_send - send target reset request for volumes
2997 * @ioc: per adapter object
2998 * @handle: device handle
2999 * Context: interrupt time.
3000 *
3001 * This is designed to send muliple task management request at the same
3002 * time to the fifo. If the fifo is full, we will append the request,
3003 * and process it in a future completion.
3004 */
3005static void
3006_scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3007{
3008 Mpi2SCSITaskManagementRequest_t *mpi_request;
3009 u16 smid;
3010 struct _tr_list *delayed_tr;
3011
3012 if (ioc->shost_recovery || ioc->remove_host ||
3013 ioc->pci_error_recovery) {
3014 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3015 "%s: host reset in progress!\n",
3016 __func__, ioc->name));
3017 return;
3018 }
3019
3020 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
3021 if (!smid) {
3022 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3023 if (!delayed_tr)
3024 return;
3025 INIT_LIST_HEAD(&delayed_tr->list);
3026 delayed_tr->handle = handle;
3027 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
3028 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3029 "DELAYED:tr:handle(0x%04x), (open)\n",
3030 ioc->name, handle));
3031 return;
3032 }
3033
3034 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3035 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3036 ioc->name, handle, smid,
3037 ioc->tm_tr_volume_cb_idx));
3038 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3039 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3040 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3041 mpi_request->DevHandle = cpu_to_le16(handle);
3042 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3043 mpt3sas_base_put_smid_hi_priority(ioc, smid);
3044}
3045
3046/**
3047 * _scsih_tm_volume_tr_complete - target reset completion
3048 * @ioc: per adapter object
3049 * @smid: system request message index
3050 * @msix_index: MSIX table index supplied by the OS
3051 * @reply: reply message frame(lower 32bit addr)
3052 * Context: interrupt time.
3053 *
3054 * Return 1 meaning mf should be freed from _base_interrupt
3055 * 0 means the mf is freed from this function.
3056 */
3057static u8
3058_scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3059 u8 msix_index, u32 reply)
3060{
3061 u16 handle;
3062 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3063 Mpi2SCSITaskManagementReply_t *mpi_reply =
3064 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3065
3066 if (ioc->shost_recovery || ioc->remove_host ||
3067 ioc->pci_error_recovery) {
3068 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3069 "%s: host reset in progress!\n",
3070 __func__, ioc->name));
3071 return 1;
3072 }
3073 if (unlikely(!mpi_reply)) {
3074 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3075 ioc->name, __FILE__, __LINE__, __func__);
3076 return 1;
3077 }
3078
3079 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
3080 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3081 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3082 dewtprintk(ioc, pr_err(MPT3SAS_FMT
3083 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
3084 ioc->name, handle,
3085 le16_to_cpu(mpi_reply->DevHandle), smid));
3086 return 0;
3087 }
3088
3089 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3090 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3091 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3092 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3093 le32_to_cpu(mpi_reply->IOCLogInfo),
3094 le32_to_cpu(mpi_reply->TerminationCount)));
3095
3096 return _scsih_check_for_pending_tm(ioc, smid);
3097}
3098
3099
3100/**
3101 * _scsih_check_for_pending_tm - check for pending task management
3102 * @ioc: per adapter object
3103 * @smid: system request message index
3104 *
3105 * This will check delayed target reset list, and feed the
3106 * next reqeust.
3107 *
3108 * Return 1 meaning mf should be freed from _base_interrupt
3109 * 0 means the mf is freed from this function.
3110 */
3111static u8
3112_scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid)
3113{
3114 struct _tr_list *delayed_tr;
3115
3116 if (!list_empty(&ioc->delayed_tr_volume_list)) {
3117 delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
3118 struct _tr_list, list);
3119 mpt3sas_base_free_smid(ioc, smid);
3120 _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
3121 list_del(&delayed_tr->list);
3122 kfree(delayed_tr);
3123 return 0;
3124 }
3125
3126 if (!list_empty(&ioc->delayed_tr_list)) {
3127 delayed_tr = list_entry(ioc->delayed_tr_list.next,
3128 struct _tr_list, list);
3129 mpt3sas_base_free_smid(ioc, smid);
3130 _scsih_tm_tr_send(ioc, delayed_tr->handle);
3131 list_del(&delayed_tr->list);
3132 kfree(delayed_tr);
3133 return 0;
3134 }
3135
3136 return 1;
3137}
3138
3139/**
3140 * _scsih_check_topo_delete_events - sanity check on topo events
3141 * @ioc: per adapter object
3142 * @event_data: the event data payload
3143 *
3144 * This routine added to better handle cable breaker.
3145 *
3146 * This handles the case where driver receives multiple expander
3147 * add and delete events in a single shot. When there is a delete event
3148 * the routine will void any pending add events waiting in the event queue.
3149 *
3150 * Return nothing.
3151 */
3152static void
3153_scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc,
3154 Mpi2EventDataSasTopologyChangeList_t *event_data)
3155{
3156 struct fw_event_work *fw_event;
3157 Mpi2EventDataSasTopologyChangeList_t *local_event_data;
3158 u16 expander_handle;
3159 struct _sas_node *sas_expander;
3160 unsigned long flags;
3161 int i, reason_code;
3162 u16 handle;
3163
3164 for (i = 0 ; i < event_data->NumEntries; i++) {
3165 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3166 if (!handle)
3167 continue;
3168 reason_code = event_data->PHY[i].PhyStatus &
3169 MPI2_EVENT_SAS_TOPO_RC_MASK;
3170 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
3171 _scsih_tm_tr_send(ioc, handle);
3172 }
3173
3174 expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
3175 if (expander_handle < ioc->sas_hba.num_phys) {
3176 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3177 return;
3178 }
3179 if (event_data->ExpStatus ==
3180 MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
3181 /* put expander attached devices into blocking state */
3182 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3183 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
3184 expander_handle);
3185 _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
3186 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3187 do {
3188 handle = find_first_bit(ioc->blocking_handles,
3189 ioc->facts.MaxDevHandle);
3190 if (handle < ioc->facts.MaxDevHandle)
3191 _scsih_block_io_device(ioc, handle);
3192 } while (test_and_clear_bit(handle, ioc->blocking_handles));
3193 } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
3194 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3195
3196 if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
3197 return;
3198
3199 /* mark ignore flag for pending events */
3200 spin_lock_irqsave(&ioc->fw_event_lock, flags);
3201 list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
3202 if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
3203 fw_event->ignore)
3204 continue;
3205 local_event_data = fw_event->event_data;
3206 if (local_event_data->ExpStatus ==
3207 MPI2_EVENT_SAS_TOPO_ES_ADDED ||
3208 local_event_data->ExpStatus ==
3209 MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
3210 if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
3211 expander_handle) {
3212 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3213 "setting ignoring flag\n", ioc->name));
3214 fw_event->ignore = 1;
3215 }
3216 }
3217 }
3218 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
3219}
3220
3221/**
3222 * _scsih_set_volume_delete_flag - setting volume delete flag
3223 * @ioc: per adapter object
3224 * @handle: device handle
3225 *
3226 * This returns nothing.
3227 */
3228static void
3229_scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3230{
3231 struct _raid_device *raid_device;
3232 struct MPT3SAS_TARGET *sas_target_priv_data;
3233 unsigned long flags;
3234
3235 spin_lock_irqsave(&ioc->raid_device_lock, flags);
3236 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
3237 if (raid_device && raid_device->starget &&
3238 raid_device->starget->hostdata) {
3239 sas_target_priv_data =
3240 raid_device->starget->hostdata;
3241 sas_target_priv_data->deleted = 1;
3242 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3243 "setting delete flag: handle(0x%04x), "
3244 "wwid(0x%016llx)\n", ioc->name, handle,
3245 (unsigned long long) raid_device->wwid));
3246 }
3247 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
3248}
3249
3250/**
3251 * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
3252 * @handle: input handle
3253 * @a: handle for volume a
3254 * @b: handle for volume b
3255 *
3256 * IR firmware only supports two raid volumes. The purpose of this
3257 * routine is to set the volume handle in either a or b. When the given
3258 * input handle is non-zero, or when a and b have not been set before.
3259 */
3260static void
3261_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
3262{
3263 if (!handle || handle == *a || handle == *b)
3264 return;
3265 if (!*a)
3266 *a = handle;
3267 else if (!*b)
3268 *b = handle;
3269}
3270
3271/**
3272 * _scsih_check_ir_config_unhide_events - check for UNHIDE events
3273 * @ioc: per adapter object
3274 * @event_data: the event data payload
3275 * Context: interrupt time.
3276 *
3277 * This routine will send target reset to volume, followed by target
3278 * resets to the PDs. This is called when a PD has been removed, or
3279 * volume has been deleted or removed. When the target reset is sent
3280 * to volume, the PD target resets need to be queued to start upon
3281 * completion of the volume target reset.
3282 *
3283 * Return nothing.
3284 */
3285static void
3286_scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc,
3287 Mpi2EventDataIrConfigChangeList_t *event_data)
3288{
3289 Mpi2EventIrConfigElement_t *element;
3290 int i;
3291 u16 handle, volume_handle, a, b;
3292 struct _tr_list *delayed_tr;
3293
3294 a = 0;
3295 b = 0;
3296
3297 /* Volume Resets for Deleted or Removed */
3298 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3299 for (i = 0; i < event_data->NumElements; i++, element++) {
3300 if (le32_to_cpu(event_data->Flags) &
3301 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3302 continue;
3303 if (element->ReasonCode ==
3304 MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
3305 element->ReasonCode ==
3306 MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
3307 volume_handle = le16_to_cpu(element->VolDevHandle);
3308 _scsih_set_volume_delete_flag(ioc, volume_handle);
3309 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3310 }
3311 }
3312
3313 /* Volume Resets for UNHIDE events */
3314 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3315 for (i = 0; i < event_data->NumElements; i++, element++) {
3316 if (le32_to_cpu(event_data->Flags) &
3317 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3318 continue;
3319 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
3320 volume_handle = le16_to_cpu(element->VolDevHandle);
3321 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3322 }
3323 }
3324
3325 if (a)
3326 _scsih_tm_tr_volume_send(ioc, a);
3327 if (b)
3328 _scsih_tm_tr_volume_send(ioc, b);
3329
3330 /* PD target resets */
3331 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3332 for (i = 0; i < event_data->NumElements; i++, element++) {
3333 if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
3334 continue;
3335 handle = le16_to_cpu(element->PhysDiskDevHandle);
3336 volume_handle = le16_to_cpu(element->VolDevHandle);
3337 clear_bit(handle, ioc->pd_handles);
3338 if (!volume_handle)
3339 _scsih_tm_tr_send(ioc, handle);
3340 else if (volume_handle == a || volume_handle == b) {
3341 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3342 BUG_ON(!delayed_tr);
3343 INIT_LIST_HEAD(&delayed_tr->list);
3344 delayed_tr->handle = handle;
3345 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3346 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3347 "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
3348 handle));
3349 } else
3350 _scsih_tm_tr_send(ioc, handle);
3351 }
3352}
3353
3354
3355/**
3356 * _scsih_check_volume_delete_events - set delete flag for volumes
3357 * @ioc: per adapter object
3358 * @event_data: the event data payload
3359 * Context: interrupt time.
3360 *
3361 * This will handle the case when the cable connected to entire volume is
3362 * pulled. We will take care of setting the deleted flag so normal IO will
3363 * not be sent.
3364 *
3365 * Return nothing.
3366 */
3367static void
3368_scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc,
3369 Mpi2EventDataIrVolume_t *event_data)
3370{
3371 u32 state;
3372
3373 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
3374 return;
3375 state = le32_to_cpu(event_data->NewValue);
3376 if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
3377 MPI2_RAID_VOL_STATE_FAILED)
3378 _scsih_set_volume_delete_flag(ioc,
3379 le16_to_cpu(event_data->VolDevHandle));
3380}
3381
3382/**
3383 * _scsih_flush_running_cmds - completing outstanding commands.
3384 * @ioc: per adapter object
3385 *
3386 * The flushing out of all pending scmd commands following host reset,
3387 * where all IO is dropped to the floor.
3388 *
3389 * Return nothing.
3390 */
3391static void
3392_scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
3393{
3394 struct scsi_cmnd *scmd;
3395 u16 smid;
3396 u16 count = 0;
3397
3398 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
3399 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
3400 if (!scmd)
3401 continue;
3402 count++;
3403 mpt3sas_base_free_smid(ioc, smid);
3404 scsi_dma_unmap(scmd);
3405 if (ioc->pci_error_recovery)
3406 scmd->result = DID_NO_CONNECT << 16;
3407 else
3408 scmd->result = DID_RESET << 16;
3409 scmd->scsi_done(scmd);
3410 }
3411 dtmprintk(ioc, pr_info(MPT3SAS_FMT "completing %d cmds\n",
3412 ioc->name, count));
3413}
3414
3415/**
3416 * _scsih_setup_eedp - setup MPI request for EEDP transfer
3417 * @ioc: per adapter object
3418 * @scmd: pointer to scsi command object
3419 * @mpi_request: pointer to the SCSI_IO reqest message frame
3420 *
3421 * Supporting protection 1 and 3.
3422 *
3423 * Returns nothing
3424 */
3425static void
3426_scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3427 Mpi2SCSIIORequest_t *mpi_request)
3428{
3429 u16 eedp_flags;
3430 unsigned char prot_op = scsi_get_prot_op(scmd);
3431 unsigned char prot_type = scsi_get_prot_type(scmd);
3432 Mpi25SCSIIORequest_t *mpi_request_3v =
3433 (Mpi25SCSIIORequest_t *)mpi_request;
3434
3435 if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
3436 return;
3437
3438 if (prot_op == SCSI_PROT_READ_STRIP)
3439 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
3440 else if (prot_op == SCSI_PROT_WRITE_INSERT)
3441 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
3442 else
3443 return;
3444
3445 switch (prot_type) {
3446 case SCSI_PROT_DIF_TYPE1:
3447 case SCSI_PROT_DIF_TYPE2:
3448
3449 /*
3450 * enable ref/guard checking
3451 * auto increment ref tag
3452 */
3453 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
3454 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
3455 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3456 mpi_request->CDB.EEDP32.PrimaryReferenceTag =
3457 cpu_to_be32(scsi_get_lba(scmd));
3458 break;
3459
3460 case SCSI_PROT_DIF_TYPE3:
3461
3462 /*
3463 * enable guard checking
3464 */
3465 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3466
3467 break;
3468 }
3469
3470 mpi_request_3v->EEDPBlockSize =
3471 cpu_to_le16(scmd->device->sector_size);
3472 mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
3473}
3474
3475/**
3476 * _scsih_eedp_error_handling - return sense code for EEDP errors
3477 * @scmd: pointer to scsi command object
3478 * @ioc_status: ioc status
3479 *
3480 * Returns nothing
3481 */
3482static void
3483_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
3484{
3485 u8 ascq;
3486
3487 switch (ioc_status) {
3488 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
3489 ascq = 0x01;
3490 break;
3491 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
3492 ascq = 0x02;
3493 break;
3494 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
3495 ascq = 0x03;
3496 break;
3497 default:
3498 ascq = 0x00;
3499 break;
3500 }
3501 scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10,
3502 ascq);
3503 scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
3504 SAM_STAT_CHECK_CONDITION;
3505}
3506
3507
3508/**
3509 * _scsih_qcmd_lck - main scsi request entry point
3510 * @scmd: pointer to scsi command object
3511 * @done: function pointer to be invoked on completion
3512 *
3513 * The callback index is set inside `ioc->scsi_io_cb_idx`.
3514 *
3515 * Returns 0 on success. If there's a failure, return either:
3516 * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
3517 * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
3518 */
3519static int
3520_scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
3521{
3522 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
3523 struct MPT3SAS_DEVICE *sas_device_priv_data;
3524 struct MPT3SAS_TARGET *sas_target_priv_data;
3525 Mpi2SCSIIORequest_t *mpi_request;
3526 u32 mpi_control;
3527 u16 smid;
3528 u16 handle;
3529
3530#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
3531 if (ioc->logging_level & MPT_DEBUG_SCSI)
3532 scsi_print_command(scmd);
3533#endif
3534
3535 scmd->scsi_done = done;
3536 sas_device_priv_data = scmd->device->hostdata;
3537 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
3538 scmd->result = DID_NO_CONNECT << 16;
3539 scmd->scsi_done(scmd);
3540 return 0;
3541 }
3542
3543 if (ioc->pci_error_recovery || ioc->remove_host) {
3544 scmd->result = DID_NO_CONNECT << 16;
3545 scmd->scsi_done(scmd);
3546 return 0;
3547 }
3548
3549 sas_target_priv_data = sas_device_priv_data->sas_target;
3550
3551 /* invalid device handle */
3552 handle = sas_target_priv_data->handle;
3553 if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) {
3554 scmd->result = DID_NO_CONNECT << 16;
3555 scmd->scsi_done(scmd);
3556 return 0;
3557 }
3558
3559
3560 /* host recovery or link resets sent via IOCTLs */
3561 if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
3562 return SCSI_MLQUEUE_HOST_BUSY;
3563
3564 /* device has been deleted */
3565 else if (sas_target_priv_data->deleted) {
3566 scmd->result = DID_NO_CONNECT << 16;
3567 scmd->scsi_done(scmd);
3568 return 0;
3569 /* device busy with task managment */
3570 } else if (sas_target_priv_data->tm_busy ||
3571 sas_device_priv_data->block)
3572 return SCSI_MLQUEUE_DEVICE_BUSY;
3573
3574 if (scmd->sc_data_direction == DMA_FROM_DEVICE)
3575 mpi_control = MPI2_SCSIIO_CONTROL_READ;
3576 else if (scmd->sc_data_direction == DMA_TO_DEVICE)
3577 mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
3578 else
3579 mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
3580
3581 /* set tags */
3582 if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) {
3583 if (scmd->device->tagged_supported) {
3584 if (scmd->device->ordered_tags)
3585 mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
3586 else
3587 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
3588 } else
3589 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
3590 } else
3591 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
3592
3593 if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
3594 scmd->cmd_len != 32)
3595 mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
3596
3597 smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
3598 if (!smid) {
3599 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3600 ioc->name, __func__);
3601 goto out;
3602 }
3603 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3604 memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
3605 _scsih_setup_eedp(ioc, scmd, mpi_request);
3606
3607 if (scmd->cmd_len == 32)
3608 mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
3609 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
3610 if (sas_device_priv_data->sas_target->flags &
3611 MPT_TARGET_FLAGS_RAID_COMPONENT)
3612 mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3613 else
3614 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
3615 mpi_request->DevHandle = cpu_to_le16(handle);
3616 mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
3617 mpi_request->Control = cpu_to_le32(mpi_control);
3618 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
3619 mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
3620 mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
3621 mpi_request->SenseBufferLowAddress =
3622 mpt3sas_base_get_sense_buffer_dma(ioc, smid);
3623 mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
3624 int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
3625 mpi_request->LUN);
3626 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
3627
3628 if (mpi_request->DataLength) {
3629 if (ioc->build_sg_scmd(ioc, scmd, smid)) {
3630 mpt3sas_base_free_smid(ioc, smid);
3631 goto out;
3632 }
3633 } else
3634 ioc->build_zero_len_sge(ioc, &mpi_request->SGL);
3635
3636 if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
3637 if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
3638 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
3639 MPI25_SCSIIO_IOFLAGS_FAST_PATH);
3640 mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
3641 } else
3642 mpt3sas_base_put_smid_scsi_io(ioc, smid, handle);
3643 } else
3644 mpt3sas_base_put_smid_default(ioc, smid);
3645 return 0;
3646
3647 out:
3648 return SCSI_MLQUEUE_HOST_BUSY;
3649}
3650static DEF_SCSI_QCMD(_scsih_qcmd)
3651
3652
3653/**
3654 * _scsih_normalize_sense - normalize descriptor and fixed format sense data
3655 * @sense_buffer: sense data returned by target
3656 * @data: normalized skey/asc/ascq
3657 *
3658 * Return nothing.
3659 */
3660static void
3661_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
3662{
3663 if ((sense_buffer[0] & 0x7F) >= 0x72) {
3664 /* descriptor format */
3665 data->skey = sense_buffer[1] & 0x0F;
3666 data->asc = sense_buffer[2];
3667 data->ascq = sense_buffer[3];
3668 } else {
3669 /* fixed format */
3670 data->skey = sense_buffer[2] & 0x0F;
3671 data->asc = sense_buffer[12];
3672 data->ascq = sense_buffer[13];
3673 }
3674}
3675
3676#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
3677/**
3678 * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
3679 * @ioc: per adapter object
3680 * @scmd: pointer to scsi command object
3681 * @mpi_reply: reply mf payload returned from firmware
3682 *
3683 * scsi_status - SCSI Status code returned from target device
3684 * scsi_state - state info associated with SCSI_IO determined by ioc
3685 * ioc_status - ioc supplied status info
3686 *
3687 * Return nothing.
3688 */
3689static void
3690_scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3691 Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
3692{
3693 u32 response_info;
3694 u8 *response_bytes;
3695 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
3696 MPI2_IOCSTATUS_MASK;
3697 u8 scsi_state = mpi_reply->SCSIState;
3698 u8 scsi_status = mpi_reply->SCSIStatus;
3699 char *desc_ioc_state = NULL;
3700 char *desc_scsi_status = NULL;
3701 char *desc_scsi_state = ioc->tmp_string;
3702 u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
3703 struct _sas_device *sas_device = NULL;
3704 unsigned long flags;
3705 struct scsi_target *starget = scmd->device->sdev_target;
3706 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
3707 char *device_str = NULL;
3708
3709 if (!priv_target)
3710 return;
3711 device_str = "volume";
3712
3713 if (log_info == 0x31170000)
3714 return;
3715
3716 switch (ioc_status) {
3717 case MPI2_IOCSTATUS_SUCCESS:
3718 desc_ioc_state = "success";
3719 break;
3720 case MPI2_IOCSTATUS_INVALID_FUNCTION:
3721 desc_ioc_state = "invalid function";
3722 break;
3723 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
3724 desc_ioc_state = "scsi recovered error";
3725 break;
3726 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
3727 desc_ioc_state = "scsi invalid dev handle";
3728 break;
3729 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
3730 desc_ioc_state = "scsi device not there";
3731 break;
3732 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
3733 desc_ioc_state = "scsi data overrun";
3734 break;
3735 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
3736 desc_ioc_state = "scsi data underrun";
3737 break;
3738 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
3739 desc_ioc_state = "scsi io data error";
3740 break;
3741 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
3742 desc_ioc_state = "scsi protocol error";
3743 break;
3744 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
3745 desc_ioc_state = "scsi task terminated";
3746 break;
3747 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
3748 desc_ioc_state = "scsi residual mismatch";
3749 break;
3750 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
3751 desc_ioc_state = "scsi task mgmt failed";
3752 break;
3753 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
3754 desc_ioc_state = "scsi ioc terminated";
3755 break;
3756 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
3757 desc_ioc_state = "scsi ext terminated";
3758 break;
3759 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
3760 desc_ioc_state = "eedp guard error";
3761 break;
3762 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
3763 desc_ioc_state = "eedp ref tag error";
3764 break;
3765 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
3766 desc_ioc_state = "eedp app tag error";
3767 break;
3768 default:
3769 desc_ioc_state = "unknown";
3770 break;
3771 }
3772
3773 switch (scsi_status) {
3774 case MPI2_SCSI_STATUS_GOOD:
3775 desc_scsi_status = "good";
3776 break;
3777 case MPI2_SCSI_STATUS_CHECK_CONDITION:
3778 desc_scsi_status = "check condition";
3779 break;
3780 case MPI2_SCSI_STATUS_CONDITION_MET:
3781 desc_scsi_status = "condition met";
3782 break;
3783 case MPI2_SCSI_STATUS_BUSY:
3784 desc_scsi_status = "busy";
3785 break;
3786 case MPI2_SCSI_STATUS_INTERMEDIATE:
3787 desc_scsi_status = "intermediate";
3788 break;
3789 case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
3790 desc_scsi_status = "intermediate condmet";
3791 break;
3792 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
3793 desc_scsi_status = "reservation conflict";
3794 break;
3795 case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
3796 desc_scsi_status = "command terminated";
3797 break;
3798 case MPI2_SCSI_STATUS_TASK_SET_FULL:
3799 desc_scsi_status = "task set full";
3800 break;
3801 case MPI2_SCSI_STATUS_ACA_ACTIVE:
3802 desc_scsi_status = "aca active";
3803 break;
3804 case MPI2_SCSI_STATUS_TASK_ABORTED:
3805 desc_scsi_status = "task aborted";
3806 break;
3807 default:
3808 desc_scsi_status = "unknown";
3809 break;
3810 }
3811
3812 desc_scsi_state[0] = '\0';
3813 if (!scsi_state)
3814 desc_scsi_state = " ";
3815 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
3816 strcat(desc_scsi_state, "response info ");
3817 if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
3818 strcat(desc_scsi_state, "state terminated ");
3819 if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
3820 strcat(desc_scsi_state, "no status ");
3821 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
3822 strcat(desc_scsi_state, "autosense failed ");
3823 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
3824 strcat(desc_scsi_state, "autosense valid ");
3825
3826 scsi_print_command(scmd);
3827
3828 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
3829 pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
3830 device_str, (unsigned long long)priv_target->sas_address);
3831 } else {
3832 spin_lock_irqsave(&ioc->sas_device_lock, flags);
3833 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
3834 priv_target->sas_address);
3835 if (sas_device) {
3836 pr_warn(MPT3SAS_FMT
3837 "\tsas_address(0x%016llx), phy(%d)\n",
3838 ioc->name, (unsigned long long)
3839 sas_device->sas_address, sas_device->phy);
3840 pr_warn(MPT3SAS_FMT
3841 "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
3842 ioc->name, (unsigned long long)
3843 sas_device->enclosure_logical_id, sas_device->slot);
3844 }
3845 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3846 }
3847
3848 pr_warn(MPT3SAS_FMT
3849 "\thandle(0x%04x), ioc_status(%s)(0x%04x), smid(%d)\n",
3850 ioc->name, le16_to_cpu(mpi_reply->DevHandle),
3851 desc_ioc_state, ioc_status, smid);
3852 pr_warn(MPT3SAS_FMT
3853 "\trequest_len(%d), underflow(%d), resid(%d)\n",
3854 ioc->name, scsi_bufflen(scmd), scmd->underflow,
3855 scsi_get_resid(scmd));
3856 pr_warn(MPT3SAS_FMT
3857 "\ttag(%d), transfer_count(%d), sc->result(0x%08x)\n",
3858 ioc->name, le16_to_cpu(mpi_reply->TaskTag),
3859 le32_to_cpu(mpi_reply->TransferCount), scmd->result);
3860 pr_warn(MPT3SAS_FMT
3861 "\tscsi_status(%s)(0x%02x), scsi_state(%s)(0x%02x)\n",
3862 ioc->name, desc_scsi_status,
3863 scsi_status, desc_scsi_state, scsi_state);
3864
3865 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
3866 struct sense_info data;
3867 _scsih_normalize_sense(scmd->sense_buffer, &data);
3868 pr_warn(MPT3SAS_FMT
3869 "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
3870 ioc->name, data.skey,
3871 data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
3872 }
3873
3874 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
3875 response_info = le32_to_cpu(mpi_reply->ResponseInfo);
3876 response_bytes = (u8 *)&response_info;
3877 _scsih_response_code(ioc, response_bytes[0]);
3878 }
3879}
3880#endif
3881
3882/**
3883 * _scsih_turn_on_fault_led - illuminate Fault LED
3884 * @ioc: per adapter object
3885 * @handle: device handle
3886 * Context: process
3887 *
3888 * Return nothing.
3889 */
3890static void
3891_scsih_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3892{
3893 Mpi2SepReply_t mpi_reply;
3894 Mpi2SepRequest_t mpi_request;
3895
3896 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
3897 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
3898 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
3899 mpi_request.SlotStatus =
3900 cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
3901 mpi_request.DevHandle = cpu_to_le16(handle);
3902 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
3903 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
3904 &mpi_request)) != 0) {
3905 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
3906 __FILE__, __LINE__, __func__);
3907 return;
3908 }
3909
3910 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
3911 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3912 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
3913 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
3914 le32_to_cpu(mpi_reply.IOCLogInfo)));
3915 return;
3916 }
3917}
3918
3919/**
3920 * _scsih_send_event_to_turn_on_fault_led - fire delayed event
3921 * @ioc: per adapter object
3922 * @handle: device handle
3923 * Context: interrupt.
3924 *
3925 * Return nothing.
3926 */
3927static void
3928_scsih_send_event_to_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3929{
3930 struct fw_event_work *fw_event;
3931
3932 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
3933 if (!fw_event)
3934 return;
3935 fw_event->event = MPT3SAS_TURN_ON_FAULT_LED;
3936 fw_event->device_handle = handle;
3937 fw_event->ioc = ioc;
3938 _scsih_fw_event_add(ioc, fw_event);
3939}
3940
3941/**
3942 * _scsih_smart_predicted_fault - process smart errors
3943 * @ioc: per adapter object
3944 * @handle: device handle
3945 * Context: interrupt.
3946 *
3947 * Return nothing.
3948 */
3949static void
3950_scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3951{
3952 struct scsi_target *starget;
3953 struct MPT3SAS_TARGET *sas_target_priv_data;
3954 Mpi2EventNotificationReply_t *event_reply;
3955 Mpi2EventDataSasDeviceStatusChange_t *event_data;
3956 struct _sas_device *sas_device;
3957 ssize_t sz;
3958 unsigned long flags;
3959
3960 /* only handle non-raid devices */
3961 spin_lock_irqsave(&ioc->sas_device_lock, flags);
3962 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
3963 if (!sas_device) {
3964 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3965 return;
3966 }
3967 starget = sas_device->starget;
3968 sas_target_priv_data = starget->hostdata;
3969
3970 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
3971 ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) {
3972 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3973 return;
3974 }
3975 starget_printk(KERN_WARNING, starget, "predicted fault\n");
3976 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3977
3978 if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
3979 _scsih_send_event_to_turn_on_fault_led(ioc, handle);
3980
3981 /* insert into event log */
3982 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
3983 sizeof(Mpi2EventDataSasDeviceStatusChange_t);
3984 event_reply = kzalloc(sz, GFP_KERNEL);
3985 if (!event_reply) {
3986 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
3987 ioc->name, __FILE__, __LINE__, __func__);
3988 return;
3989 }
3990
3991 event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
3992 event_reply->Event =
3993 cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
3994 event_reply->MsgLength = sz/4;
3995 event_reply->EventDataLength =
3996 cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
3997 event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
3998 event_reply->EventData;
3999 event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
4000 event_data->ASC = 0x5D;
4001 event_data->DevHandle = cpu_to_le16(handle);
4002 event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
4003 mpt3sas_ctl_add_to_event_log(ioc, event_reply);
4004 kfree(event_reply);
4005}
4006
4007/**
4008 * _scsih_io_done - scsi request callback
4009 * @ioc: per adapter object
4010 * @smid: system request message index
4011 * @msix_index: MSIX table index supplied by the OS
4012 * @reply: reply message frame(lower 32bit addr)
4013 *
4014 * Callback handler when using _scsih_qcmd.
4015 *
4016 * Return 1 meaning mf should be freed from _base_interrupt
4017 * 0 means the mf is freed from this function.
4018 */
4019static u8
4020_scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4021{
4022 Mpi2SCSIIORequest_t *mpi_request;
4023 Mpi2SCSIIOReply_t *mpi_reply;
4024 struct scsi_cmnd *scmd;
4025 u16 ioc_status;
4026 u32 xfer_cnt;
4027 u8 scsi_state;
4028 u8 scsi_status;
4029 u32 log_info;
4030 struct MPT3SAS_DEVICE *sas_device_priv_data;
4031 u32 response_code = 0;
4032
4033 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
4034 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
4035 if (scmd == NULL)
4036 return 1;
4037
4038 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4039
4040 if (mpi_reply == NULL) {
4041 scmd->result = DID_OK << 16;
4042 goto out;
4043 }
4044
4045 sas_device_priv_data = scmd->device->hostdata;
4046 if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
4047 sas_device_priv_data->sas_target->deleted) {
4048 scmd->result = DID_NO_CONNECT << 16;
4049 goto out;
4050 }
4051 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
4052
4053 /* turning off TLR */
4054 scsi_state = mpi_reply->SCSIState;
4055 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4056 response_code =
4057 le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
4058 if (!sas_device_priv_data->tlr_snoop_check) {
4059 sas_device_priv_data->tlr_snoop_check++;
4060 if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
4061 response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME)
4062 sas_device_priv_data->flags &=
4063 ~MPT_DEVICE_TLR_ON;
4064 }
4065
4066 xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
4067 scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
4068 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
4069 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4070 else
4071 log_info = 0;
4072 ioc_status &= MPI2_IOCSTATUS_MASK;
4073 scsi_status = mpi_reply->SCSIStatus;
4074
4075 if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
4076 (scsi_status == MPI2_SCSI_STATUS_BUSY ||
4077 scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
4078 scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
4079 ioc_status = MPI2_IOCSTATUS_SUCCESS;
4080 }
4081
4082 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4083 struct sense_info data;
4084 const void *sense_data = mpt3sas_base_get_sense_buffer(ioc,
4085 smid);
4086 u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
4087 le32_to_cpu(mpi_reply->SenseCount));
4088 memcpy(scmd->sense_buffer, sense_data, sz);
4089 _scsih_normalize_sense(scmd->sense_buffer, &data);
4090 /* failure prediction threshold exceeded */
4091 if (data.asc == 0x5D)
4092 _scsih_smart_predicted_fault(ioc,
4093 le16_to_cpu(mpi_reply->DevHandle));
4094 mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
4095 }
4096
4097 switch (ioc_status) {
4098 case MPI2_IOCSTATUS_BUSY:
4099 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
4100 scmd->result = SAM_STAT_BUSY;
4101 break;
4102
4103 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4104 scmd->result = DID_NO_CONNECT << 16;
4105 break;
4106
4107 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4108 if (sas_device_priv_data->block) {
4109 scmd->result = DID_TRANSPORT_DISRUPTED << 16;
4110 goto out;
4111 }
4112 if (log_info == 0x31110630) {
4113 if (scmd->retries > 2) {
4114 scmd->result = DID_NO_CONNECT << 16;
4115 scsi_device_set_state(scmd->device,
4116 SDEV_OFFLINE);
4117 } else {
4118 scmd->result = DID_SOFT_ERROR << 16;
4119 scmd->device->expecting_cc_ua = 1;
4120 }
4121 break;
4122 }
4123 scmd->result = DID_SOFT_ERROR << 16;
4124 break;
4125 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4126 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4127 scmd->result = DID_RESET << 16;
4128 break;
4129
4130 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4131 if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
4132 scmd->result = DID_SOFT_ERROR << 16;
4133 else
4134 scmd->result = (DID_OK << 16) | scsi_status;
4135 break;
4136
4137 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4138 scmd->result = (DID_OK << 16) | scsi_status;
4139
4140 if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
4141 break;
4142
4143 if (xfer_cnt < scmd->underflow) {
4144 if (scsi_status == SAM_STAT_BUSY)
4145 scmd->result = SAM_STAT_BUSY;
4146 else
4147 scmd->result = DID_SOFT_ERROR << 16;
4148 } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4149 MPI2_SCSI_STATE_NO_SCSI_STATUS))
4150 scmd->result = DID_SOFT_ERROR << 16;
4151 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4152 scmd->result = DID_RESET << 16;
4153 else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
4154 mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
4155 mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
4156 scmd->result = (DRIVER_SENSE << 24) |
4157 SAM_STAT_CHECK_CONDITION;
4158 scmd->sense_buffer[0] = 0x70;
4159 scmd->sense_buffer[2] = ILLEGAL_REQUEST;
4160 scmd->sense_buffer[12] = 0x20;
4161 scmd->sense_buffer[13] = 0;
4162 }
4163 break;
4164
4165 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4166 scsi_set_resid(scmd, 0);
4167 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4168 case MPI2_IOCSTATUS_SUCCESS:
4169 scmd->result = (DID_OK << 16) | scsi_status;
4170 if (response_code ==
4171 MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
4172 (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4173 MPI2_SCSI_STATE_NO_SCSI_STATUS)))
4174 scmd->result = DID_SOFT_ERROR << 16;
4175 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4176 scmd->result = DID_RESET << 16;
4177 break;
4178
4179 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4180 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4181 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4182 _scsih_eedp_error_handling(scmd, ioc_status);
4183 break;
4184
4185 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4186 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4187 case MPI2_IOCSTATUS_INVALID_SGL:
4188 case MPI2_IOCSTATUS_INTERNAL_ERROR:
4189 case MPI2_IOCSTATUS_INVALID_FIELD:
4190 case MPI2_IOCSTATUS_INVALID_STATE:
4191 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4192 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4193 default:
4194 scmd->result = DID_SOFT_ERROR << 16;
4195 break;
4196
4197 }
4198
4199#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
4200 if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
4201 _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
4202#endif
4203
4204 out:
4205
4206 scsi_dma_unmap(scmd);
4207
4208 scmd->scsi_done(scmd);
4209 return 1;
4210}
4211
4212/**
4213 * _scsih_sas_host_refresh - refreshing sas host object contents
4214 * @ioc: per adapter object
4215 * Context: user
4216 *
4217 * During port enable, fw will send topology events for every device. Its
4218 * possible that the handles may change from the previous setting, so this
4219 * code keeping handles updating if changed.
4220 *
4221 * Return nothing.
4222 */
4223static void
4224_scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
4225{
4226 u16 sz;
4227 u16 ioc_status;
4228 int i;
4229 Mpi2ConfigReply_t mpi_reply;
4230 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4231 u16 attached_handle;
4232 u8 link_rate;
4233
4234 dtmprintk(ioc, pr_info(MPT3SAS_FMT
4235 "updating handles for sas_host(0x%016llx)\n",
4236 ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
4237
4238 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
4239 * sizeof(Mpi2SasIOUnit0PhyData_t));
4240 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4241 if (!sas_iounit_pg0) {
4242 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4243 ioc->name, __FILE__, __LINE__, __func__);
4244 return;
4245 }
4246
4247 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4248 sas_iounit_pg0, sz)) != 0)
4249 goto out;
4250 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
4251 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
4252 goto out;
4253 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4254 link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
4255 if (i == 0)
4256 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4257 PhyData[0].ControllerDevHandle);
4258 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4259 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
4260 AttachedDevHandle);
4261 if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4262 link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
4263 mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
4264 attached_handle, i, link_rate);
4265 }
4266 out:
4267 kfree(sas_iounit_pg0);
4268}
4269
4270/**
4271 * _scsih_sas_host_add - create sas host object
4272 * @ioc: per adapter object
4273 *
4274 * Creating host side data object, stored in ioc->sas_hba
4275 *
4276 * Return nothing.
4277 */
4278static void
4279_scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
4280{
4281 int i;
4282 Mpi2ConfigReply_t mpi_reply;
4283 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4284 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
4285 Mpi2SasPhyPage0_t phy_pg0;
4286 Mpi2SasDevicePage0_t sas_device_pg0;
4287 Mpi2SasEnclosurePage0_t enclosure_pg0;
4288 u16 ioc_status;
4289 u16 sz;
4290 u8 device_missing_delay;
4291
4292 mpt3sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
4293 if (!ioc->sas_hba.num_phys) {
4294 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4295 ioc->name, __FILE__, __LINE__, __func__);
4296 return;
4297 }
4298
4299 /* sas_iounit page 0 */
4300 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
4301 sizeof(Mpi2SasIOUnit0PhyData_t));
4302 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4303 if (!sas_iounit_pg0) {
4304 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4305 ioc->name, __FILE__, __LINE__, __func__);
4306 return;
4307 }
4308 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4309 sas_iounit_pg0, sz))) {
4310 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4311 ioc->name, __FILE__, __LINE__, __func__);
4312 goto out;
4313 }
4314 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4315 MPI2_IOCSTATUS_MASK;
4316 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4317 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4318 ioc->name, __FILE__, __LINE__, __func__);
4319 goto out;
4320 }
4321
4322 /* sas_iounit page 1 */
4323 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
4324 sizeof(Mpi2SasIOUnit1PhyData_t));
4325 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
4326 if (!sas_iounit_pg1) {
4327 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4328 ioc->name, __FILE__, __LINE__, __func__);
4329 goto out;
4330 }
4331 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
4332 sas_iounit_pg1, sz))) {
4333 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4334 ioc->name, __FILE__, __LINE__, __func__);
4335 goto out;
4336 }
4337 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4338 MPI2_IOCSTATUS_MASK;
4339 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4340 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4341 ioc->name, __FILE__, __LINE__, __func__);
4342 goto out;
4343 }
4344
4345 ioc->io_missing_delay =
4346 sas_iounit_pg1->IODeviceMissingDelay;
4347 device_missing_delay =
4348 sas_iounit_pg1->ReportDeviceMissingDelay;
4349 if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
4350 ioc->device_missing_delay = (device_missing_delay &
4351 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
4352 else
4353 ioc->device_missing_delay = device_missing_delay &
4354 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
4355
4356 ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
4357 ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
4358 sizeof(struct _sas_phy), GFP_KERNEL);
4359 if (!ioc->sas_hba.phy) {
4360 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4361 ioc->name, __FILE__, __LINE__, __func__);
4362 goto out;
4363 }
4364 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4365 if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
4366 i))) {
4367 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4368 ioc->name, __FILE__, __LINE__, __func__);
4369 goto out;
4370 }
4371 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4372 MPI2_IOCSTATUS_MASK;
4373 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4374 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4375 ioc->name, __FILE__, __LINE__, __func__);
4376 goto out;
4377 }
4378
4379 if (i == 0)
4380 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4381 PhyData[0].ControllerDevHandle);
4382 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4383 ioc->sas_hba.phy[i].phy_id = i;
4384 mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
4385 phy_pg0, ioc->sas_hba.parent_dev);
4386 }
4387 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
4388 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
4389 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4390 ioc->name, __FILE__, __LINE__, __func__);
4391 goto out;
4392 }
4393 ioc->sas_hba.enclosure_handle =
4394 le16_to_cpu(sas_device_pg0.EnclosureHandle);
4395 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
4396 pr_info(MPT3SAS_FMT
4397 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
4398 ioc->name, ioc->sas_hba.handle,
4399 (unsigned long long) ioc->sas_hba.sas_address,
4400 ioc->sas_hba.num_phys) ;
4401
4402 if (ioc->sas_hba.enclosure_handle) {
4403 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4404 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4405 ioc->sas_hba.enclosure_handle)))
4406 ioc->sas_hba.enclosure_logical_id =
4407 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4408 }
4409
4410 out:
4411 kfree(sas_iounit_pg1);
4412 kfree(sas_iounit_pg0);
4413}
4414
4415/**
4416 * _scsih_expander_add - creating expander object
4417 * @ioc: per adapter object
4418 * @handle: expander handle
4419 *
4420 * Creating expander object, stored in ioc->sas_expander_list.
4421 *
4422 * Return 0 for success, else error.
4423 */
4424static int
4425_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
4426{
4427 struct _sas_node *sas_expander;
4428 Mpi2ConfigReply_t mpi_reply;
4429 Mpi2ExpanderPage0_t expander_pg0;
4430 Mpi2ExpanderPage1_t expander_pg1;
4431 Mpi2SasEnclosurePage0_t enclosure_pg0;
4432 u32 ioc_status;
4433 u16 parent_handle;
4434 u64 sas_address, sas_address_parent = 0;
4435 int i;
4436 unsigned long flags;
4437 struct _sas_port *mpt3sas_port = NULL;
4438
4439 int rc = 0;
4440
4441 if (!handle)
4442 return -1;
4443
4444 if (ioc->shost_recovery || ioc->pci_error_recovery)
4445 return -1;
4446
4447 if ((mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
4448 MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
4449 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4450 ioc->name, __FILE__, __LINE__, __func__);
4451 return -1;
4452 }
4453
4454 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4455 MPI2_IOCSTATUS_MASK;
4456 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4457 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4458 ioc->name, __FILE__, __LINE__, __func__);
4459 return -1;
4460 }
4461
4462 /* handle out of order topology events */
4463 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
4464 if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
4465 != 0) {
4466 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4467 ioc->name, __FILE__, __LINE__, __func__);
4468 return -1;
4469 }
4470 if (sas_address_parent != ioc->sas_hba.sas_address) {
4471 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4472 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
4473 sas_address_parent);
4474 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4475 if (!sas_expander) {
4476 rc = _scsih_expander_add(ioc, parent_handle);
4477 if (rc != 0)
4478 return rc;
4479 }
4480 }
4481
4482 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4483 sas_address = le64_to_cpu(expander_pg0.SASAddress);
4484 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
4485 sas_address);
4486 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4487
4488 if (sas_expander)
4489 return 0;
4490
4491 sas_expander = kzalloc(sizeof(struct _sas_node),
4492 GFP_KERNEL);
4493 if (!sas_expander) {
4494 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4495 ioc->name, __FILE__, __LINE__, __func__);
4496 return -1;
4497 }
4498
4499 sas_expander->handle = handle;
4500 sas_expander->num_phys = expander_pg0.NumPhys;
4501 sas_expander->sas_address_parent = sas_address_parent;
4502 sas_expander->sas_address = sas_address;
4503
4504 pr_info(MPT3SAS_FMT "expander_add: handle(0x%04x)," \
4505 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
4506 handle, parent_handle, (unsigned long long)
4507 sas_expander->sas_address, sas_expander->num_phys);
4508
4509 if (!sas_expander->num_phys)
4510 goto out_fail;
4511 sas_expander->phy = kcalloc(sas_expander->num_phys,
4512 sizeof(struct _sas_phy), GFP_KERNEL);
4513 if (!sas_expander->phy) {
4514 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4515 ioc->name, __FILE__, __LINE__, __func__);
4516 rc = -1;
4517 goto out_fail;
4518 }
4519
4520 INIT_LIST_HEAD(&sas_expander->sas_port_list);
4521 mpt3sas_port = mpt3sas_transport_port_add(ioc, handle,
4522 sas_address_parent);
4523 if (!mpt3sas_port) {
4524 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4525 ioc->name, __FILE__, __LINE__, __func__);
4526 rc = -1;
4527 goto out_fail;
4528 }
4529 sas_expander->parent_dev = &mpt3sas_port->rphy->dev;
4530
4531 for (i = 0 ; i < sas_expander->num_phys ; i++) {
4532 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
4533 &expander_pg1, i, handle))) {
4534 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4535 ioc->name, __FILE__, __LINE__, __func__);
4536 rc = -1;
4537 goto out_fail;
4538 }
4539 sas_expander->phy[i].handle = handle;
4540 sas_expander->phy[i].phy_id = i;
4541
4542 if ((mpt3sas_transport_add_expander_phy(ioc,
4543 &sas_expander->phy[i], expander_pg1,
4544 sas_expander->parent_dev))) {
4545 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4546 ioc->name, __FILE__, __LINE__, __func__);
4547 rc = -1;
4548 goto out_fail;
4549 }
4550 }
4551
4552 if (sas_expander->enclosure_handle) {
4553 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4554 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4555 sas_expander->enclosure_handle)))
4556 sas_expander->enclosure_logical_id =
4557 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4558 }
4559
4560 _scsih_expander_node_add(ioc, sas_expander);
4561 return 0;
4562
4563 out_fail:
4564
4565 if (mpt3sas_port)
4566 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
4567 sas_address_parent);
4568 kfree(sas_expander);
4569 return rc;
4570}
4571
4572/**
4573 * mpt3sas_expander_remove - removing expander object
4574 * @ioc: per adapter object
4575 * @sas_address: expander sas_address
4576 *
4577 * Return nothing.
4578 */
4579void
4580mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
4581{
4582 struct _sas_node *sas_expander;
4583 unsigned long flags;
4584
4585 if (ioc->shost_recovery)
4586 return;
4587
4588 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4589 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
4590 sas_address);
4591 if (sas_expander)
4592 list_del(&sas_expander->list);
4593 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4594 if (sas_expander)
4595 _scsih_expander_node_remove(ioc, sas_expander);
4596}
4597
4598/**
4599 * _scsih_done - internal SCSI_IO callback handler.
4600 * @ioc: per adapter object
4601 * @smid: system request message index
4602 * @msix_index: MSIX table index supplied by the OS
4603 * @reply: reply message frame(lower 32bit addr)
4604 *
4605 * Callback handler when sending internal generated SCSI_IO.
4606 * The callback index passed is `ioc->scsih_cb_idx`
4607 *
4608 * Return 1 meaning mf should be freed from _base_interrupt
4609 * 0 means the mf is freed from this function.
4610 */
4611static u8
4612_scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4613{
4614 MPI2DefaultReply_t *mpi_reply;
4615
4616 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
4617 if (ioc->scsih_cmds.status == MPT3_CMD_NOT_USED)
4618 return 1;
4619 if (ioc->scsih_cmds.smid != smid)
4620 return 1;
4621 ioc->scsih_cmds.status |= MPT3_CMD_COMPLETE;
4622 if (mpi_reply) {
4623 memcpy(ioc->scsih_cmds.reply, mpi_reply,
4624 mpi_reply->MsgLength*4);
4625 ioc->scsih_cmds.status |= MPT3_CMD_REPLY_VALID;
4626 }
4627 ioc->scsih_cmds.status &= ~MPT3_CMD_PENDING;
4628 complete(&ioc->scsih_cmds.done);
4629 return 1;
4630}
4631
4632
4633
4634
4635#define MPT3_MAX_LUNS (255)
4636
4637
4638/**
4639 * _scsih_check_access_status - check access flags
4640 * @ioc: per adapter object
4641 * @sas_address: sas address
4642 * @handle: sas device handle
4643 * @access_flags: errors returned during discovery of the device
4644 *
4645 * Return 0 for success, else failure
4646 */
4647static u8
4648_scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
4649 u16 handle, u8 access_status)
4650{
4651 u8 rc = 1;
4652 char *desc = NULL;
4653
4654 switch (access_status) {
4655 case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
4656 case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
4657 rc = 0;
4658 break;
4659 case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
4660 desc = "sata capability failed";
4661 break;
4662 case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
4663 desc = "sata affiliation conflict";
4664 break;
4665 case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
4666 desc = "route not addressable";
4667 break;
4668 case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
4669 desc = "smp error not addressable";
4670 break;
4671 case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
4672 desc = "device blocked";
4673 break;
4674 case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
4675 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
4676 case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
4677 case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
4678 case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
4679 case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
4680 case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
4681 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
4682 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
4683 case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
4684 case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
4685 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
4686 desc = "sata initialization failed";
4687 break;
4688 default:
4689 desc = "unknown";
4690 break;
4691 }
4692
4693 if (!rc)
4694 return 0;
4695
4696 pr_err(MPT3SAS_FMT
4697 "discovery errors(%s): sas_address(0x%016llx), handle(0x%04x)\n",
4698 ioc->name, desc, (unsigned long long)sas_address, handle);
4699 return rc;
4700}
4701
4702/**
4703 * _scsih_check_device - checking device responsiveness
4704 * @ioc: per adapter object
4705 * @parent_sas_address: sas address of parent expander or sas host
4706 * @handle: attached device handle
4707 * @phy_numberv: phy number
4708 * @link_rate: new link rate
4709 *
4710 * Returns nothing.
4711 */
4712static void
4713_scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
4714 u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate)
4715{
4716 Mpi2ConfigReply_t mpi_reply;
4717 Mpi2SasDevicePage0_t sas_device_pg0;
4718 struct _sas_device *sas_device;
4719 u32 ioc_status;
4720 unsigned long flags;
4721 u64 sas_address;
4722 struct scsi_target *starget;
4723 struct MPT3SAS_TARGET *sas_target_priv_data;
4724 u32 device_info;
4725
4726
4727 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
4728 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
4729 return;
4730
4731 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
4732 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
4733 return;
4734
4735 /* wide port handling ~ we need only handle device once for the phy that
4736 * is matched in sas device page zero
4737 */
4738 if (phy_number != sas_device_pg0.PhyNum)
4739 return;
4740
4741 /* check if this is end device */
4742 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
4743 if (!(_scsih_is_end_device(device_info)))
4744 return;
4745
4746 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4747 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
4748 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
4749 sas_address);
4750
4751 if (!sas_device) {
4752 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4753 return;
4754 }
4755
4756 if (unlikely(sas_device->handle != handle)) {
4757 starget = sas_device->starget;
4758 sas_target_priv_data = starget->hostdata;
4759 starget_printk(KERN_INFO, starget,
4760 "handle changed from(0x%04x) to (0x%04x)!!!\n",
4761 sas_device->handle, handle);
4762 sas_target_priv_data->handle = handle;
4763 sas_device->handle = handle;
4764 }
4765
4766 /* check if device is present */
4767 if (!(le16_to_cpu(sas_device_pg0.Flags) &
4768 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
4769 pr_err(MPT3SAS_FMT
4770 "device is not present handle(0x%04x), flags!!!\n",
4771 ioc->name, handle);
4772 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4773 return;
4774 }
4775
4776 /* check if there were any issues with discovery */
4777 if (_scsih_check_access_status(ioc, sas_address, handle,
4778 sas_device_pg0.AccessStatus)) {
4779 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4780 return;
4781 }
4782
4783 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4784 _scsih_ublock_io_device(ioc, sas_address);
4785
4786}
4787
4788/**
4789 * _scsih_add_device - creating sas device object
4790 * @ioc: per adapter object
4791 * @handle: sas device handle
4792 * @phy_num: phy number end device attached to
4793 * @is_pd: is this hidden raid component
4794 *
4795 * Creating end device object, stored in ioc->sas_device_list.
4796 *
4797 * Returns 0 for success, non-zero for failure.
4798 */
4799static int
4800_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
4801 u8 is_pd)
4802{
4803 Mpi2ConfigReply_t mpi_reply;
4804 Mpi2SasDevicePage0_t sas_device_pg0;
4805 Mpi2SasEnclosurePage0_t enclosure_pg0;
4806 struct _sas_device *sas_device;
4807 u32 ioc_status;
4808 u64 sas_address;
4809 u32 device_info;
4810 unsigned long flags;
4811
4812 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
4813 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
4814 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4815 ioc->name, __FILE__, __LINE__, __func__);
4816 return -1;
4817 }
4818
4819 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4820 MPI2_IOCSTATUS_MASK;
4821 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4822 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4823 ioc->name, __FILE__, __LINE__, __func__);
4824 return -1;
4825 }
4826
4827 /* check if this is end device */
4828 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
4829 if (!(_scsih_is_end_device(device_info)))
4830 return -1;
4831 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
4832
4833 /* check if device is present */
4834 if (!(le16_to_cpu(sas_device_pg0.Flags) &
4835 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
4836 pr_err(MPT3SAS_FMT "device is not present handle(0x04%x)!!!\n",
4837 ioc->name, handle);
4838 return -1;
4839 }
4840
4841 /* check if there were any issues with discovery */
4842 if (_scsih_check_access_status(ioc, sas_address, handle,
4843 sas_device_pg0.AccessStatus))
4844 return -1;
4845
4846 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4847 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
4848 sas_address);
4849 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4850
4851 if (sas_device)
4852 return -1;
4853
4854 sas_device = kzalloc(sizeof(struct _sas_device),
4855 GFP_KERNEL);
4856 if (!sas_device) {
4857 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4858 ioc->name, __FILE__, __LINE__, __func__);
4859 return 0;
4860 }
4861
4862 sas_device->handle = handle;
4863 if (_scsih_get_sas_address(ioc,
4864 le16_to_cpu(sas_device_pg0.ParentDevHandle),
4865 &sas_device->sas_address_parent) != 0)
4866 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4867 ioc->name, __FILE__, __LINE__, __func__);
4868 sas_device->enclosure_handle =
4869 le16_to_cpu(sas_device_pg0.EnclosureHandle);
4870 sas_device->slot =
4871 le16_to_cpu(sas_device_pg0.Slot);
4872 sas_device->device_info = device_info;
4873 sas_device->sas_address = sas_address;
4874 sas_device->phy = sas_device_pg0.PhyNum;
4875 sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
4876 MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
4877
4878 /* get enclosure_logical_id */
4879 if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0(
4880 ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4881 sas_device->enclosure_handle)))
4882 sas_device->enclosure_logical_id =
4883 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4884
4885 /* get device name */
4886 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
4887
4888 if (ioc->wait_for_discovery_to_complete)
4889 _scsih_sas_device_init_add(ioc, sas_device);
4890 else
4891 _scsih_sas_device_add(ioc, sas_device);
4892
4893 return 0;
4894}
4895
4896/**
4897 * _scsih_remove_device - removing sas device object
4898 * @ioc: per adapter object
4899 * @sas_device_delete: the sas_device object
4900 *
4901 * Return nothing.
4902 */
4903static void
4904_scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
4905 struct _sas_device *sas_device)
4906{
4907 struct MPT3SAS_TARGET *sas_target_priv_data;
4908
4909
4910 dewtprintk(ioc, pr_info(MPT3SAS_FMT
4911 "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n",
4912 ioc->name, __func__,
4913 sas_device->handle, (unsigned long long)
4914 sas_device->sas_address));
4915
4916 if (sas_device->starget && sas_device->starget->hostdata) {
4917 sas_target_priv_data = sas_device->starget->hostdata;
4918 sas_target_priv_data->deleted = 1;
4919 _scsih_ublock_io_device(ioc, sas_device->sas_address);
4920 sas_target_priv_data->handle =
4921 MPT3SAS_INVALID_DEVICE_HANDLE;
4922 }
4923 mpt3sas_transport_port_remove(ioc,
4924 sas_device->sas_address,
4925 sas_device->sas_address_parent);
4926
4927 pr_info(MPT3SAS_FMT
4928 "removing handle(0x%04x), sas_addr(0x%016llx)\n",
4929 ioc->name, sas_device->handle,
4930 (unsigned long long) sas_device->sas_address);
4931
4932 dewtprintk(ioc, pr_info(MPT3SAS_FMT
4933 "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n",
4934 ioc->name, __func__,
4935 sas_device->handle, (unsigned long long)
4936 sas_device->sas_address));
4937
4938 kfree(sas_device);
4939}
4940
4941#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
4942/**
4943 * _scsih_sas_topology_change_event_debug - debug for topology event
4944 * @ioc: per adapter object
4945 * @event_data: event data payload
4946 * Context: user.
4947 */
4948static void
4949_scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
4950 Mpi2EventDataSasTopologyChangeList_t *event_data)
4951{
4952 int i;
4953 u16 handle;
4954 u16 reason_code;
4955 u8 phy_number;
4956 char *status_str = NULL;
4957 u8 link_rate, prev_link_rate;
4958
4959 switch (event_data->ExpStatus) {
4960 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
4961 status_str = "add";
4962 break;
4963 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
4964 status_str = "remove";
4965 break;
4966 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
4967 case 0:
4968 status_str = "responding";
4969 break;
4970 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
4971 status_str = "remove delay";
4972 break;
4973 default:
4974 status_str = "unknown status";
4975 break;
4976 }
4977 pr_info(MPT3SAS_FMT "sas topology change: (%s)\n",
4978 ioc->name, status_str);
4979 pr_info("\thandle(0x%04x), enclosure_handle(0x%04x) " \
4980 "start_phy(%02d), count(%d)\n",
4981 le16_to_cpu(event_data->ExpanderDevHandle),
4982 le16_to_cpu(event_data->EnclosureHandle),
4983 event_data->StartPhyNum, event_data->NumEntries);
4984 for (i = 0; i < event_data->NumEntries; i++) {
4985 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
4986 if (!handle)
4987 continue;
4988 phy_number = event_data->StartPhyNum + i;
4989 reason_code = event_data->PHY[i].PhyStatus &
4990 MPI2_EVENT_SAS_TOPO_RC_MASK;
4991 switch (reason_code) {
4992 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
4993 status_str = "target add";
4994 break;
4995 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
4996 status_str = "target remove";
4997 break;
4998 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
4999 status_str = "delay target remove";
5000 break;
5001 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5002 status_str = "link rate change";
5003 break;
5004 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
5005 status_str = "target responding";
5006 break;
5007 default:
5008 status_str = "unknown";
5009 break;
5010 }
5011 link_rate = event_data->PHY[i].LinkRate >> 4;
5012 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5013 pr_info("\tphy(%02d), attached_handle(0x%04x): %s:" \
5014 " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
5015 handle, status_str, link_rate, prev_link_rate);
5016
5017 }
5018}
5019#endif
5020
5021/**
5022 * _scsih_sas_topology_change_event - handle topology changes
5023 * @ioc: per adapter object
5024 * @fw_event: The fw_event_work object
5025 * Context: user.
5026 *
5027 */
5028static int
5029_scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
5030 struct fw_event_work *fw_event)
5031{
5032 int i;
5033 u16 parent_handle, handle;
5034 u16 reason_code;
5035 u8 phy_number, max_phys;
5036 struct _sas_node *sas_expander;
5037 u64 sas_address;
5038 unsigned long flags;
5039 u8 link_rate, prev_link_rate;
5040 Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
5041
5042#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
5043 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5044 _scsih_sas_topology_change_event_debug(ioc, event_data);
5045#endif
5046
5047 if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
5048 return 0;
5049
5050 if (!ioc->sas_hba.num_phys)
5051 _scsih_sas_host_add(ioc);
5052 else
5053 _scsih_sas_host_refresh(ioc);
5054
5055 if (fw_event->ignore) {
5056 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5057 "ignoring expander event\n", ioc->name));
5058 return 0;
5059 }
5060
5061 parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
5062
5063 /* handle expander add */
5064 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
5065 if (_scsih_expander_add(ioc, parent_handle) != 0)
5066 return 0;
5067
5068 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5069 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
5070 parent_handle);
5071 if (sas_expander) {
5072 sas_address = sas_expander->sas_address;
5073 max_phys = sas_expander->num_phys;
5074 } else if (parent_handle < ioc->sas_hba.num_phys) {
5075 sas_address = ioc->sas_hba.sas_address;
5076 max_phys = ioc->sas_hba.num_phys;
5077 } else {
5078 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5079 return 0;
5080 }
5081 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5082
5083 /* handle siblings events */
5084 for (i = 0; i < event_data->NumEntries; i++) {
5085 if (fw_event->ignore) {
5086 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5087 "ignoring expander event\n", ioc->name));
5088 return 0;
5089 }
5090 if (ioc->remove_host || ioc->pci_error_recovery)
5091 return 0;
5092 phy_number = event_data->StartPhyNum + i;
5093 if (phy_number >= max_phys)
5094 continue;
5095 reason_code = event_data->PHY[i].PhyStatus &
5096 MPI2_EVENT_SAS_TOPO_RC_MASK;
5097 if ((event_data->PHY[i].PhyStatus &
5098 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
5099 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
5100 continue;
5101 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5102 if (!handle)
5103 continue;
5104 link_rate = event_data->PHY[i].LinkRate >> 4;
5105 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5106 switch (reason_code) {
5107 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5108
5109 if (ioc->shost_recovery)
5110 break;
5111
5112 if (link_rate == prev_link_rate)
5113 break;
5114
5115 mpt3sas_transport_update_links(ioc, sas_address,
5116 handle, phy_number, link_rate);
5117
5118 if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
5119 break;
5120
5121 _scsih_check_device(ioc, sas_address, handle,
5122 phy_number, link_rate);
5123
5124
5125 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5126
5127 if (ioc->shost_recovery)
5128 break;
5129
5130 mpt3sas_transport_update_links(ioc, sas_address,
5131 handle, phy_number, link_rate);
5132
5133 _scsih_add_device(ioc, handle, phy_number, 0);
5134
5135 break;
5136 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5137
5138 _scsih_device_remove_by_handle(ioc, handle);
5139 break;
5140 }
5141 }
5142
5143 /* handle expander removal */
5144 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
5145 sas_expander)
5146 mpt3sas_expander_remove(ioc, sas_address);
5147
5148 return 0;
5149}
5150
5151#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
5152/**
5153 * _scsih_sas_device_status_change_event_debug - debug for device event
5154 * @event_data: event data payload
5155 * Context: user.
5156 *
5157 * Return nothing.
5158 */
5159static void
5160_scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5161 Mpi2EventDataSasDeviceStatusChange_t *event_data)
5162{
5163 char *reason_str = NULL;
5164
5165 switch (event_data->ReasonCode) {
5166 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5167 reason_str = "smart data";
5168 break;
5169 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
5170 reason_str = "unsupported device discovered";
5171 break;
5172 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5173 reason_str = "internal device reset";
5174 break;
5175 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5176 reason_str = "internal task abort";
5177 break;
5178 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5179 reason_str = "internal task abort set";
5180 break;
5181 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5182 reason_str = "internal clear task set";
5183 break;
5184 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5185 reason_str = "internal query task";
5186 break;
5187 case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
5188 reason_str = "sata init failure";
5189 break;
5190 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
5191 reason_str = "internal device reset complete";
5192 break;
5193 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
5194 reason_str = "internal task abort complete";
5195 break;
5196 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
5197 reason_str = "internal async notification";
5198 break;
5199 case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
5200 reason_str = "expander reduced functionality";
5201 break;
5202 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
5203 reason_str = "expander reduced functionality complete";
5204 break;
5205 default:
5206 reason_str = "unknown reason";
5207 break;
5208 }
5209 pr_info(MPT3SAS_FMT "device status change: (%s)\n"
5210 "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
5211 ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
5212 (unsigned long long)le64_to_cpu(event_data->SASAddress),
5213 le16_to_cpu(event_data->TaskTag));
5214 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
5215 pr_info(MPT3SAS_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
5216 event_data->ASC, event_data->ASCQ);
5217 pr_info("\n");
5218}
5219#endif
5220
5221/**
5222 * _scsih_sas_device_status_change_event - handle device status change
5223 * @ioc: per adapter object
5224 * @fw_event: The fw_event_work object
5225 * Context: user.
5226 *
5227 * Return nothing.
5228 */
5229static void
5230_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
5231 struct fw_event_work *fw_event)
5232{
5233 struct MPT3SAS_TARGET *target_priv_data;
5234 struct _sas_device *sas_device;
5235 u64 sas_address;
5236 unsigned long flags;
5237 Mpi2EventDataSasDeviceStatusChange_t *event_data =
5238 fw_event->event_data;
5239
5240#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
5241 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5242 _scsih_sas_device_status_change_event_debug(ioc,
5243 event_data);
5244#endif
5245
5246 /* In MPI Revision K (0xC), the internal device reset complete was
5247 * implemented, so avoid setting tm_busy flag for older firmware.
5248 */
5249 if ((ioc->facts.HeaderVersion >> 8) < 0xC)
5250 return;
5251
5252 if (event_data->ReasonCode !=
5253 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
5254 event_data->ReasonCode !=
5255 MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
5256 return;
5257
5258 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5259 sas_address = le64_to_cpu(event_data->SASAddress);
5260 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
5261 sas_address);
5262
5263 if (!sas_device || !sas_device->starget) {
5264 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5265 return;
5266 }
5267
5268 target_priv_data = sas_device->starget->hostdata;
5269 if (!target_priv_data) {
5270 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5271 return;
5272 }
5273
5274 if (event_data->ReasonCode ==
5275 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
5276 target_priv_data->tm_busy = 1;
5277 else
5278 target_priv_data->tm_busy = 0;
5279 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5280}
5281
5282#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
5283/**
5284 * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
5285 * event
5286 * @ioc: per adapter object
5287 * @event_data: event data payload
5288 * Context: user.
5289 *
5290 * Return nothing.
5291 */
5292static void
5293_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5294 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
5295{
5296 char *reason_str = NULL;
5297
5298 switch (event_data->ReasonCode) {
5299 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
5300 reason_str = "enclosure add";
5301 break;
5302 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
5303 reason_str = "enclosure remove";
5304 break;
5305 default:
5306 reason_str = "unknown reason";
5307 break;
5308 }
5309
5310 pr_info(MPT3SAS_FMT "enclosure status change: (%s)\n"
5311 "\thandle(0x%04x), enclosure logical id(0x%016llx)"
5312 " number slots(%d)\n", ioc->name, reason_str,
5313 le16_to_cpu(event_data->EnclosureHandle),
5314 (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
5315 le16_to_cpu(event_data->StartSlot));
5316}
5317#endif
5318
5319/**
5320 * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
5321 * @ioc: per adapter object
5322 * @fw_event: The fw_event_work object
5323 * Context: user.
5324 *
5325 * Return nothing.
5326 */
5327static void
5328_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
5329 struct fw_event_work *fw_event)
5330{
5331#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
5332 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5333 _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
5334 fw_event->event_data);
5335#endif
5336}
5337
5338/**
5339 * _scsih_sas_broadcast_primitive_event - handle broadcast events
5340 * @ioc: per adapter object
5341 * @fw_event: The fw_event_work object
5342 * Context: user.
5343 *
5344 * Return nothing.
5345 */
5346static void
5347_scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
5348 struct fw_event_work *fw_event)
5349{
5350 struct scsi_cmnd *scmd;
5351 struct scsi_device *sdev;
5352 u16 smid, handle;
5353 u32 lun;
5354 struct MPT3SAS_DEVICE *sas_device_priv_data;
5355 u32 termination_count;
5356 u32 query_count;
5357 Mpi2SCSITaskManagementReply_t *mpi_reply;
5358 Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data;
5359 u16 ioc_status;
5360 unsigned long flags;
5361 int r;
5362 u8 max_retries = 0;
5363 u8 task_abort_retries;
5364
5365 mutex_lock(&ioc->tm_cmds.mutex);
5366 pr_info(MPT3SAS_FMT
5367 "%s: enter: phy number(%d), width(%d)\n",
5368 ioc->name, __func__, event_data->PhyNum,
5369 event_data->PortWidth);
5370
5371 _scsih_block_io_all_device(ioc);
5372
5373 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5374 mpi_reply = ioc->tm_cmds.reply;
5375 broadcast_aen_retry:
5376
5377 /* sanity checks for retrying this loop */
5378 if (max_retries++ == 5) {
5379 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: giving up\n",
5380 ioc->name, __func__));
5381 goto out;
5382 } else if (max_retries > 1)
5383 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: %d retry\n",
5384 ioc->name, __func__, max_retries - 1));
5385
5386 termination_count = 0;
5387 query_count = 0;
5388 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
5389 if (ioc->shost_recovery)
5390 goto out;
5391 scmd = _scsih_scsi_lookup_get(ioc, smid);
5392 if (!scmd)
5393 continue;
5394 sdev = scmd->device;
5395 sas_device_priv_data = sdev->hostdata;
5396 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
5397 continue;
5398 /* skip hidden raid components */
5399 if (sas_device_priv_data->sas_target->flags &
5400 MPT_TARGET_FLAGS_RAID_COMPONENT)
5401 continue;
5402 /* skip volumes */
5403 if (sas_device_priv_data->sas_target->flags &
5404 MPT_TARGET_FLAGS_VOLUME)
5405 continue;
5406
5407 handle = sas_device_priv_data->sas_target->handle;
5408 lun = sas_device_priv_data->lun;
5409 query_count++;
5410
5411 if (ioc->shost_recovery)
5412 goto out;
5413
5414 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5415 r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
5416 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0,
5417 TM_MUTEX_OFF);
5418 if (r == FAILED) {
5419 sdev_printk(KERN_WARNING, sdev,
5420 "mpt3sas_scsih_issue_tm: FAILED when sending "
5421 "QUERY_TASK: scmd(%p)\n", scmd);
5422 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5423 goto broadcast_aen_retry;
5424 }
5425 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
5426 & MPI2_IOCSTATUS_MASK;
5427 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5428 sdev_printk(KERN_WARNING, sdev,
5429 "query task: FAILED with IOCSTATUS(0x%04x), scmd(%p)\n",
5430 ioc_status, scmd);
5431 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5432 goto broadcast_aen_retry;
5433 }
5434
5435 /* see if IO is still owned by IOC and target */
5436 if (mpi_reply->ResponseCode ==
5437 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
5438 mpi_reply->ResponseCode ==
5439 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
5440 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5441 continue;
5442 }
5443 task_abort_retries = 0;
5444 tm_retry:
5445 if (task_abort_retries++ == 60) {
5446 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5447 "%s: ABORT_TASK: giving up\n", ioc->name,
5448 __func__));
5449 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5450 goto broadcast_aen_retry;
5451 }
5452
5453 if (ioc->shost_recovery)
5454 goto out_no_lock;
5455
5456 r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
5457 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
5458 scmd->serial_number, TM_MUTEX_OFF);
5459 if (r == FAILED) {
5460 sdev_printk(KERN_WARNING, sdev,
5461 "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
5462 "scmd(%p)\n", scmd);
5463 goto tm_retry;
5464 }
5465
5466 if (task_abort_retries > 1)
5467 sdev_printk(KERN_WARNING, sdev,
5468 "mpt3sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
5469 " scmd(%p)\n",
5470 task_abort_retries - 1, scmd);
5471
5472 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
5473 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5474 }
5475
5476 if (ioc->broadcast_aen_pending) {
5477 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5478 "%s: loop back due to pending AEN\n",
5479 ioc->name, __func__));
5480 ioc->broadcast_aen_pending = 0;
5481 goto broadcast_aen_retry;
5482 }
5483
5484 out:
5485 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5486 out_no_lock:
5487
5488 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5489 "%s - exit, query_count = %d termination_count = %d\n",
5490 ioc->name, __func__, query_count, termination_count));
5491
5492 ioc->broadcast_aen_busy = 0;
5493 if (!ioc->shost_recovery)
5494 _scsih_ublock_io_all_device(ioc);
5495 mutex_unlock(&ioc->tm_cmds.mutex);
5496}
5497
5498/**
5499 * _scsih_sas_discovery_event - handle discovery events
5500 * @ioc: per adapter object
5501 * @fw_event: The fw_event_work object
5502 * Context: user.
5503 *
5504 * Return nothing.
5505 */
5506static void
5507_scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
5508 struct fw_event_work *fw_event)
5509{
5510 Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data;
5511
5512#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
5513 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
5514 pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
5515 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
5516 "start" : "stop");
5517 if (event_data->DiscoveryStatus)
5518 pr_info("discovery_status(0x%08x)",
5519 le32_to_cpu(event_data->DiscoveryStatus));
5520 pr_info("\n");
5521 }
5522#endif
5523
5524 if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
5525 !ioc->sas_hba.num_phys) {
5526 if (disable_discovery > 0 && ioc->shost_recovery) {
5527 /* Wait for the reset to complete */
5528 while (ioc->shost_recovery)
5529 ssleep(1);
5530 }
5531 _scsih_sas_host_add(ioc);
5532 }
5533}
5534
5535/**
5536 * _scsih_ir_fastpath - turn on fastpath for IR physdisk
5537 * @ioc: per adapter object
5538 * @handle: device handle for physical disk
5539 * @phys_disk_num: physical disk number
5540 *
5541 * Return 0 for success, else failure.
5542 */
5543static int
5544_scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
5545{
5546 Mpi2RaidActionRequest_t *mpi_request;
5547 Mpi2RaidActionReply_t *mpi_reply;
5548 u16 smid;
5549 u8 issue_reset = 0;
5550 int rc = 0;
5551 u16 ioc_status;
5552 u32 log_info;
5553
5554
5555 mutex_lock(&ioc->scsih_cmds.mutex);
5556
5557 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
5558 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
5559 ioc->name, __func__);
5560 rc = -EAGAIN;
5561 goto out;
5562 }
5563 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
5564
5565 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
5566 if (!smid) {
5567 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
5568 ioc->name, __func__);
5569 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
5570 rc = -EAGAIN;
5571 goto out;
5572 }
5573
5574 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
5575 ioc->scsih_cmds.smid = smid;
5576 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
5577
5578 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
5579 mpi_request->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN;
5580 mpi_request->PhysDiskNum = phys_disk_num;
5581
5582 dewtprintk(ioc, pr_info(MPT3SAS_FMT "IR RAID_ACTION: turning fast "\
5583 "path on for handle(0x%04x), phys_disk_num (0x%02x)\n", ioc->name,
5584 handle, phys_disk_num));
5585
5586 init_completion(&ioc->scsih_cmds.done);
5587 mpt3sas_base_put_smid_default(ioc, smid);
5588 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
5589
5590 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
5591 pr_err(MPT3SAS_FMT "%s: timeout\n",
5592 ioc->name, __func__);
5593 if (!(ioc->scsih_cmds.status & MPT3_CMD_RESET))
5594 issue_reset = 1;
5595 rc = -EFAULT;
5596 goto out;
5597 }
5598
5599 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
5600
5601 mpi_reply = ioc->scsih_cmds.reply;
5602 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
5603 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
5604 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
5605 else
5606 log_info = 0;
5607 ioc_status &= MPI2_IOCSTATUS_MASK;
5608 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5609 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5610 "IR RAID_ACTION: failed: ioc_status(0x%04x), "
5611 "loginfo(0x%08x)!!!\n", ioc->name, ioc_status,
5612 log_info));
5613 rc = -EFAULT;
5614 } else
5615 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5616 "IR RAID_ACTION: completed successfully\n",
5617 ioc->name));
5618 }
5619
5620 out:
5621 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
5622 mutex_unlock(&ioc->scsih_cmds.mutex);
5623
5624 if (issue_reset)
5625 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
5626 FORCE_BIG_HAMMER);
5627 return rc;
5628}
5629
5630/**
5631 * _scsih_reprobe_lun - reprobing lun
5632 * @sdev: scsi device struct
5633 * @no_uld_attach: sdev->no_uld_attach flag setting
5634 *
5635 **/
5636static void
5637_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
5638{
5639 int rc;
5640 sdev->no_uld_attach = no_uld_attach ? 1 : 0;
5641 sdev_printk(KERN_INFO, sdev, "%s raid component\n",
5642 sdev->no_uld_attach ? "hidding" : "exposing");
5643 rc = scsi_device_reprobe(sdev);
5644}
5645
5646/**
5647 * _scsih_sas_volume_add - add new volume
5648 * @ioc: per adapter object
5649 * @element: IR config element data
5650 * Context: user.
5651 *
5652 * Return nothing.
5653 */
5654static void
5655_scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc,
5656 Mpi2EventIrConfigElement_t *element)
5657{
5658 struct _raid_device *raid_device;
5659 unsigned long flags;
5660 u64 wwid;
5661 u16 handle = le16_to_cpu(element->VolDevHandle);
5662 int rc;
5663
5664 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
5665 if (!wwid) {
5666 pr_err(MPT3SAS_FMT
5667 "failure at %s:%d/%s()!\n", ioc->name,
5668 __FILE__, __LINE__, __func__);
5669 return;
5670 }
5671
5672 spin_lock_irqsave(&ioc->raid_device_lock, flags);
5673 raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
5674 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
5675
5676 if (raid_device)
5677 return;
5678
5679 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
5680 if (!raid_device) {
5681 pr_err(MPT3SAS_FMT
5682 "failure at %s:%d/%s()!\n", ioc->name,
5683 __FILE__, __LINE__, __func__);
5684 return;
5685 }
5686
5687 raid_device->id = ioc->sas_id++;
5688 raid_device->channel = RAID_CHANNEL;
5689 raid_device->handle = handle;
5690 raid_device->wwid = wwid;
5691 _scsih_raid_device_add(ioc, raid_device);
5692 if (!ioc->wait_for_discovery_to_complete) {
5693 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
5694 raid_device->id, 0);
5695 if (rc)
5696 _scsih_raid_device_remove(ioc, raid_device);
5697 } else {
5698 spin_lock_irqsave(&ioc->raid_device_lock, flags);
5699 _scsih_determine_boot_device(ioc, raid_device, 1);
5700 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
5701 }
5702}
5703
5704/**
5705 * _scsih_sas_volume_delete - delete volume
5706 * @ioc: per adapter object
5707 * @handle: volume device handle
5708 * Context: user.
5709 *
5710 * Return nothing.
5711 */
5712static void
5713_scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle)
5714{
5715 struct _raid_device *raid_device;
5716 unsigned long flags;
5717 struct MPT3SAS_TARGET *sas_target_priv_data;
5718 struct scsi_target *starget = NULL;
5719
5720 spin_lock_irqsave(&ioc->raid_device_lock, flags);
5721 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
5722 if (raid_device) {
5723 if (raid_device->starget) {
5724 starget = raid_device->starget;
5725 sas_target_priv_data = starget->hostdata;
5726 sas_target_priv_data->deleted = 1;
5727 }
5728 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
5729 ioc->name, raid_device->handle,
5730 (unsigned long long) raid_device->wwid);
5731 list_del(&raid_device->list);
5732 kfree(raid_device);
5733 }
5734 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
5735 if (starget)
5736 scsi_remove_target(&starget->dev);
5737}
5738
5739/**
5740 * _scsih_sas_pd_expose - expose pd component to /dev/sdX
5741 * @ioc: per adapter object
5742 * @element: IR config element data
5743 * Context: user.
5744 *
5745 * Return nothing.
5746 */
5747static void
5748_scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
5749 Mpi2EventIrConfigElement_t *element)
5750{
5751 struct _sas_device *sas_device;
5752 struct scsi_target *starget = NULL;
5753 struct MPT3SAS_TARGET *sas_target_priv_data;
5754 unsigned long flags;
5755 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
5756
5757 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5758 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
5759 if (sas_device) {
5760 sas_device->volume_handle = 0;
5761 sas_device->volume_wwid = 0;
5762 clear_bit(handle, ioc->pd_handles);
5763 if (sas_device->starget && sas_device->starget->hostdata) {
5764 starget = sas_device->starget;
5765 sas_target_priv_data = starget->hostdata;
5766 sas_target_priv_data->flags &=
5767 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
5768 }
5769 }
5770 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5771 if (!sas_device)
5772 return;
5773
5774 /* exposing raid component */
5775 if (starget)
5776 starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
5777}
5778
5779/**
5780 * _scsih_sas_pd_hide - hide pd component from /dev/sdX
5781 * @ioc: per adapter object
5782 * @element: IR config element data
5783 * Context: user.
5784 *
5785 * Return nothing.
5786 */
5787static void
5788_scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
5789 Mpi2EventIrConfigElement_t *element)
5790{
5791 struct _sas_device *sas_device;
5792 struct scsi_target *starget = NULL;
5793 struct MPT3SAS_TARGET *sas_target_priv_data;
5794 unsigned long flags;
5795 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
5796 u16 volume_handle = 0;
5797 u64 volume_wwid = 0;
5798
5799 mpt3sas_config_get_volume_handle(ioc, handle, &volume_handle);
5800 if (volume_handle)
5801 mpt3sas_config_get_volume_wwid(ioc, volume_handle,
5802 &volume_wwid);
5803
5804 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5805 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
5806 if (sas_device) {
5807 set_bit(handle, ioc->pd_handles);
5808 if (sas_device->starget && sas_device->starget->hostdata) {
5809 starget = sas_device->starget;
5810 sas_target_priv_data = starget->hostdata;
5811 sas_target_priv_data->flags |=
5812 MPT_TARGET_FLAGS_RAID_COMPONENT;
5813 sas_device->volume_handle = volume_handle;
5814 sas_device->volume_wwid = volume_wwid;
5815 }
5816 }
5817 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5818 if (!sas_device)
5819 return;
5820
5821 /* hiding raid component */
5822 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
5823 if (starget)
5824 starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
5825}
5826
5827/**
5828 * _scsih_sas_pd_delete - delete pd component
5829 * @ioc: per adapter object
5830 * @element: IR config element data
5831 * Context: user.
5832 *
5833 * Return nothing.
5834 */
5835static void
5836_scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc,
5837 Mpi2EventIrConfigElement_t *element)
5838{
5839 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
5840
5841 _scsih_device_remove_by_handle(ioc, handle);
5842}
5843
5844/**
5845 * _scsih_sas_pd_add - remove pd component
5846 * @ioc: per adapter object
5847 * @element: IR config element data
5848 * Context: user.
5849 *
5850 * Return nothing.
5851 */
5852static void
5853_scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
5854 Mpi2EventIrConfigElement_t *element)
5855{
5856 struct _sas_device *sas_device;
5857 unsigned long flags;
5858 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
5859 Mpi2ConfigReply_t mpi_reply;
5860 Mpi2SasDevicePage0_t sas_device_pg0;
5861 u32 ioc_status;
5862 u64 sas_address;
5863 u16 parent_handle;
5864
5865 set_bit(handle, ioc->pd_handles);
5866
5867 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5868 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
5869 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5870 if (sas_device) {
5871 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
5872 return;
5873 }
5874
5875 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5876 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
5877 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5878 ioc->name, __FILE__, __LINE__, __func__);
5879 return;
5880 }
5881
5882 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5883 MPI2_IOCSTATUS_MASK;
5884 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5885 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5886 ioc->name, __FILE__, __LINE__, __func__);
5887 return;
5888 }
5889
5890 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
5891 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
5892 mpt3sas_transport_update_links(ioc, sas_address, handle,
5893 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
5894
5895 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
5896 _scsih_add_device(ioc, handle, 0, 1);
5897}
5898
5899#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
5900/**
5901 * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
5902 * @ioc: per adapter object
5903 * @event_data: event data payload
5904 * Context: user.
5905 *
5906 * Return nothing.
5907 */
5908static void
5909_scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5910 Mpi2EventDataIrConfigChangeList_t *event_data)
5911{
5912 Mpi2EventIrConfigElement_t *element;
5913 u8 element_type;
5914 int i;
5915 char *reason_str = NULL, *element_str = NULL;
5916
5917 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
5918
5919 pr_info(MPT3SAS_FMT "raid config change: (%s), elements(%d)\n",
5920 ioc->name, (le32_to_cpu(event_data->Flags) &
5921 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
5922 "foreign" : "native", event_data->NumElements);
5923 for (i = 0; i < event_data->NumElements; i++, element++) {
5924 switch (element->ReasonCode) {
5925 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
5926 reason_str = "add";
5927 break;
5928 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
5929 reason_str = "remove";
5930 break;
5931 case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
5932 reason_str = "no change";
5933 break;
5934 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
5935 reason_str = "hide";
5936 break;
5937 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
5938 reason_str = "unhide";
5939 break;
5940 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
5941 reason_str = "volume_created";
5942 break;
5943 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
5944 reason_str = "volume_deleted";
5945 break;
5946 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
5947 reason_str = "pd_created";
5948 break;
5949 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
5950 reason_str = "pd_deleted";
5951 break;
5952 default:
5953 reason_str = "unknown reason";
5954 break;
5955 }
5956 element_type = le16_to_cpu(element->ElementFlags) &
5957 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
5958 switch (element_type) {
5959 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
5960 element_str = "volume";
5961 break;
5962 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
5963 element_str = "phys disk";
5964 break;
5965 case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
5966 element_str = "hot spare";
5967 break;
5968 default:
5969 element_str = "unknown element";
5970 break;
5971 }
5972 pr_info("\t(%s:%s), vol handle(0x%04x), " \
5973 "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
5974 reason_str, le16_to_cpu(element->VolDevHandle),
5975 le16_to_cpu(element->PhysDiskDevHandle),
5976 element->PhysDiskNum);
5977 }
5978}
5979#endif
5980
5981/**
5982 * _scsih_sas_ir_config_change_event - handle ir configuration change events
5983 * @ioc: per adapter object
5984 * @fw_event: The fw_event_work object
5985 * Context: user.
5986 *
5987 * Return nothing.
5988 */
5989static void
5990_scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
5991 struct fw_event_work *fw_event)
5992{
5993 Mpi2EventIrConfigElement_t *element;
5994 int i;
5995 u8 foreign_config;
5996 Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
5997
5998#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
5999 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
6000 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
6001
6002#endif
6003
6004 foreign_config = (le32_to_cpu(event_data->Flags) &
6005 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
6006
6007 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6008 if (ioc->shost_recovery) {
6009
6010 for (i = 0; i < event_data->NumElements; i++, element++) {
6011 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE)
6012 _scsih_ir_fastpath(ioc,
6013 le16_to_cpu(element->PhysDiskDevHandle),
6014 element->PhysDiskNum);
6015 }
6016 return;
6017 }
6018 for (i = 0; i < event_data->NumElements; i++, element++) {
6019
6020 switch (element->ReasonCode) {
6021 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6022 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6023 if (!foreign_config)
6024 _scsih_sas_volume_add(ioc, element);
6025 break;
6026 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6027 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6028 if (!foreign_config)
6029 _scsih_sas_volume_delete(ioc,
6030 le16_to_cpu(element->VolDevHandle));
6031 break;
6032 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6033 _scsih_sas_pd_hide(ioc, element);
6034 break;
6035 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6036 _scsih_sas_pd_expose(ioc, element);
6037 break;
6038 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6039 _scsih_sas_pd_add(ioc, element);
6040 break;
6041 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6042 _scsih_sas_pd_delete(ioc, element);
6043 break;
6044 }
6045 }
6046}
6047
6048/**
6049 * _scsih_sas_ir_volume_event - IR volume event
6050 * @ioc: per adapter object
6051 * @fw_event: The fw_event_work object
6052 * Context: user.
6053 *
6054 * Return nothing.
6055 */
6056static void
6057_scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
6058 struct fw_event_work *fw_event)
6059{
6060 u64 wwid;
6061 unsigned long flags;
6062 struct _raid_device *raid_device;
6063 u16 handle;
6064 u32 state;
6065 int rc;
6066 Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
6067
6068 if (ioc->shost_recovery)
6069 return;
6070
6071 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
6072 return;
6073
6074 handle = le16_to_cpu(event_data->VolDevHandle);
6075 state = le32_to_cpu(event_data->NewValue);
6076 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6077 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6078 ioc->name, __func__, handle,
6079 le32_to_cpu(event_data->PreviousValue), state));
6080 switch (state) {
6081 case MPI2_RAID_VOL_STATE_MISSING:
6082 case MPI2_RAID_VOL_STATE_FAILED:
6083 _scsih_sas_volume_delete(ioc, handle);
6084 break;
6085
6086 case MPI2_RAID_VOL_STATE_ONLINE:
6087 case MPI2_RAID_VOL_STATE_DEGRADED:
6088 case MPI2_RAID_VOL_STATE_OPTIMAL:
6089
6090 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6091 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6092 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6093
6094 if (raid_device)
6095 break;
6096
6097 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6098 if (!wwid) {
6099 pr_err(MPT3SAS_FMT
6100 "failure at %s:%d/%s()!\n", ioc->name,
6101 __FILE__, __LINE__, __func__);
6102 break;
6103 }
6104
6105 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6106 if (!raid_device) {
6107 pr_err(MPT3SAS_FMT
6108 "failure at %s:%d/%s()!\n", ioc->name,
6109 __FILE__, __LINE__, __func__);
6110 break;
6111 }
6112
6113 raid_device->id = ioc->sas_id++;
6114 raid_device->channel = RAID_CHANNEL;
6115 raid_device->handle = handle;
6116 raid_device->wwid = wwid;
6117 _scsih_raid_device_add(ioc, raid_device);
6118 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6119 raid_device->id, 0);
6120 if (rc)
6121 _scsih_raid_device_remove(ioc, raid_device);
6122 break;
6123
6124 case MPI2_RAID_VOL_STATE_INITIALIZING:
6125 default:
6126 break;
6127 }
6128}
6129
6130/**
6131 * _scsih_sas_ir_physical_disk_event - PD event
6132 * @ioc: per adapter object
6133 * @fw_event: The fw_event_work object
6134 * Context: user.
6135 *
6136 * Return nothing.
6137 */
6138static void
6139_scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
6140 struct fw_event_work *fw_event)
6141{
6142 u16 handle, parent_handle;
6143 u32 state;
6144 struct _sas_device *sas_device;
6145 unsigned long flags;
6146 Mpi2ConfigReply_t mpi_reply;
6147 Mpi2SasDevicePage0_t sas_device_pg0;
6148 u32 ioc_status;
6149 Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
6150 u64 sas_address;
6151
6152 if (ioc->shost_recovery)
6153 return;
6154
6155 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
6156 return;
6157
6158 handle = le16_to_cpu(event_data->PhysDiskDevHandle);
6159 state = le32_to_cpu(event_data->NewValue);
6160
6161 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6162 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6163 ioc->name, __func__, handle,
6164 le32_to_cpu(event_data->PreviousValue), state));
6165 switch (state) {
6166 case MPI2_RAID_PD_STATE_ONLINE:
6167 case MPI2_RAID_PD_STATE_DEGRADED:
6168 case MPI2_RAID_PD_STATE_REBUILDING:
6169 case MPI2_RAID_PD_STATE_OPTIMAL:
6170 case MPI2_RAID_PD_STATE_HOT_SPARE:
6171
6172 set_bit(handle, ioc->pd_handles);
6173 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6174 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6175 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6176
6177 if (sas_device)
6178 return;
6179
6180 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6181 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6182 handle))) {
6183 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6184 ioc->name, __FILE__, __LINE__, __func__);
6185 return;
6186 }
6187
6188 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6189 MPI2_IOCSTATUS_MASK;
6190 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6191 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6192 ioc->name, __FILE__, __LINE__, __func__);
6193 return;
6194 }
6195
6196 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6197 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6198 mpt3sas_transport_update_links(ioc, sas_address, handle,
6199 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6200
6201 _scsih_add_device(ioc, handle, 0, 1);
6202
6203 break;
6204
6205 case MPI2_RAID_PD_STATE_OFFLINE:
6206 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
6207 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
6208 default:
6209 break;
6210 }
6211}
6212
6213#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
6214/**
6215 * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
6216 * @ioc: per adapter object
6217 * @event_data: event data payload
6218 * Context: user.
6219 *
6220 * Return nothing.
6221 */
6222static void
6223_scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
6224 Mpi2EventDataIrOperationStatus_t *event_data)
6225{
6226 char *reason_str = NULL;
6227
6228 switch (event_data->RAIDOperation) {
6229 case MPI2_EVENT_IR_RAIDOP_RESYNC:
6230 reason_str = "resync";
6231 break;
6232 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
6233 reason_str = "online capacity expansion";
6234 break;
6235 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
6236 reason_str = "consistency check";
6237 break;
6238 case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
6239 reason_str = "background init";
6240 break;
6241 case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
6242 reason_str = "make data consistent";
6243 break;
6244 }
6245
6246 if (!reason_str)
6247 return;
6248
6249 pr_info(MPT3SAS_FMT "raid operational status: (%s)" \
6250 "\thandle(0x%04x), percent complete(%d)\n",
6251 ioc->name, reason_str,
6252 le16_to_cpu(event_data->VolDevHandle),
6253 event_data->PercentComplete);
6254}
6255#endif
6256
6257/**
6258 * _scsih_sas_ir_operation_status_event - handle RAID operation events
6259 * @ioc: per adapter object
6260 * @fw_event: The fw_event_work object
6261 * Context: user.
6262 *
6263 * Return nothing.
6264 */
6265static void
6266_scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
6267 struct fw_event_work *fw_event)
6268{
6269 Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data;
6270 static struct _raid_device *raid_device;
6271 unsigned long flags;
6272 u16 handle;
6273
6274#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
6275 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
6276 _scsih_sas_ir_operation_status_event_debug(ioc,
6277 event_data);
6278#endif
6279
6280 /* code added for raid transport support */
6281 if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
6282
6283 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6284 handle = le16_to_cpu(event_data->VolDevHandle);
6285 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6286 if (raid_device)
6287 raid_device->percent_complete =
6288 event_data->PercentComplete;
6289 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6290 }
6291}
6292
6293/**
6294 * _scsih_prep_device_scan - initialize parameters prior to device scan
6295 * @ioc: per adapter object
6296 *
6297 * Set the deleted flag prior to device scan. If the device is found during
6298 * the scan, then we clear the deleted flag.
6299 */
6300static void
6301_scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
6302{
6303 struct MPT3SAS_DEVICE *sas_device_priv_data;
6304 struct scsi_device *sdev;
6305
6306 shost_for_each_device(sdev, ioc->shost) {
6307 sas_device_priv_data = sdev->hostdata;
6308 if (sas_device_priv_data && sas_device_priv_data->sas_target)
6309 sas_device_priv_data->sas_target->deleted = 1;
6310 }
6311}
6312
6313/**
6314 * _scsih_mark_responding_sas_device - mark a sas_devices as responding
6315 * @ioc: per adapter object
6316 * @sas_address: sas address
6317 * @slot: enclosure slot id
6318 * @handle: device handle
6319 *
6320 * After host reset, find out whether devices are still responding.
6321 * Used in _scsih_remove_unresponsive_sas_devices.
6322 *
6323 * Return nothing.
6324 */
6325static void
6326_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
6327 u16 slot, u16 handle)
6328{
6329 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
6330 struct scsi_target *starget;
6331 struct _sas_device *sas_device;
6332 unsigned long flags;
6333
6334 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6335 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
6336 if (sas_device->sas_address == sas_address &&
6337 sas_device->slot == slot) {
6338 sas_device->responding = 1;
6339 starget = sas_device->starget;
6340 if (starget && starget->hostdata) {
6341 sas_target_priv_data = starget->hostdata;
6342 sas_target_priv_data->tm_busy = 0;
6343 sas_target_priv_data->deleted = 0;
6344 } else
6345 sas_target_priv_data = NULL;
6346 if (starget)
6347 starget_printk(KERN_INFO, starget,
6348 "handle(0x%04x), sas_addr(0x%016llx), "
6349 "enclosure logical id(0x%016llx), "
6350 "slot(%d)\n", handle,
6351 (unsigned long long)sas_device->sas_address,
6352 (unsigned long long)
6353 sas_device->enclosure_logical_id,
6354 sas_device->slot);
6355 if (sas_device->handle == handle)
6356 goto out;
6357 pr_info("\thandle changed from(0x%04x)!!!\n",
6358 sas_device->handle);
6359 sas_device->handle = handle;
6360 if (sas_target_priv_data)
6361 sas_target_priv_data->handle = handle;
6362 goto out;
6363 }
6364 }
6365 out:
6366 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6367}
6368
6369/**
6370 * _scsih_search_responding_sas_devices -
6371 * @ioc: per adapter object
6372 *
6373 * After host reset, find out whether devices are still responding.
6374 * If not remove.
6375 *
6376 * Return nothing.
6377 */
6378static void
6379_scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
6380{
6381 Mpi2SasDevicePage0_t sas_device_pg0;
6382 Mpi2ConfigReply_t mpi_reply;
6383 u16 ioc_status;
6384 u16 handle;
6385 u32 device_info;
6386
6387 pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name);
6388
6389 if (list_empty(&ioc->sas_device_list))
6390 goto out;
6391
6392 handle = 0xFFFF;
6393 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6394 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
6395 handle))) {
6396 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6397 MPI2_IOCSTATUS_MASK;
6398 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6399 break;
6400 handle = le16_to_cpu(sas_device_pg0.DevHandle);
6401 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
6402 if (!(_scsih_is_end_device(device_info)))
6403 continue;
6404 _scsih_mark_responding_sas_device(ioc,
6405 le64_to_cpu(sas_device_pg0.SASAddress),
6406 le16_to_cpu(sas_device_pg0.Slot), handle);
6407 }
6408
6409 out:
6410 pr_info(MPT3SAS_FMT "search for end-devices: complete\n",
6411 ioc->name);
6412}
6413
6414/**
6415 * _scsih_mark_responding_raid_device - mark a raid_device as responding
6416 * @ioc: per adapter object
6417 * @wwid: world wide identifier for raid volume
6418 * @handle: device handle
6419 *
6420 * After host reset, find out whether devices are still responding.
6421 * Used in _scsih_remove_unresponsive_raid_devices.
6422 *
6423 * Return nothing.
6424 */
6425static void
6426_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
6427 u16 handle)
6428{
6429 struct MPT3SAS_TARGET *sas_target_priv_data;
6430 struct scsi_target *starget;
6431 struct _raid_device *raid_device;
6432 unsigned long flags;
6433
6434 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6435 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
6436 if (raid_device->wwid == wwid && raid_device->starget) {
6437 starget = raid_device->starget;
6438 if (starget && starget->hostdata) {
6439 sas_target_priv_data = starget->hostdata;
6440 sas_target_priv_data->deleted = 0;
6441 } else
6442 sas_target_priv_data = NULL;
6443 raid_device->responding = 1;
6444 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6445 starget_printk(KERN_INFO, raid_device->starget,
6446 "handle(0x%04x), wwid(0x%016llx)\n", handle,
6447 (unsigned long long)raid_device->wwid);
6448 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6449 if (raid_device->handle == handle) {
6450 spin_unlock_irqrestore(&ioc->raid_device_lock,
6451 flags);
6452 return;
6453 }
6454 pr_info("\thandle changed from(0x%04x)!!!\n",
6455 raid_device->handle);
6456 raid_device->handle = handle;
6457 if (sas_target_priv_data)
6458 sas_target_priv_data->handle = handle;
6459 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6460 return;
6461 }
6462 }
6463 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6464}
6465
6466/**
6467 * _scsih_search_responding_raid_devices -
6468 * @ioc: per adapter object
6469 *
6470 * After host reset, find out whether devices are still responding.
6471 * If not remove.
6472 *
6473 * Return nothing.
6474 */
6475static void
6476_scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
6477{
6478 Mpi2RaidVolPage1_t volume_pg1;
6479 Mpi2RaidVolPage0_t volume_pg0;
6480 Mpi2RaidPhysDiskPage0_t pd_pg0;
6481 Mpi2ConfigReply_t mpi_reply;
6482 u16 ioc_status;
6483 u16 handle;
6484 u8 phys_disk_num;
6485
6486 if (!ioc->ir_firmware)
6487 return;
6488
6489 pr_info(MPT3SAS_FMT "search for raid volumes: start\n",
6490 ioc->name);
6491
6492 if (list_empty(&ioc->raid_device_list))
6493 goto out;
6494
6495 handle = 0xFFFF;
6496 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
6497 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
6498 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6499 MPI2_IOCSTATUS_MASK;
6500 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6501 break;
6502 handle = le16_to_cpu(volume_pg1.DevHandle);
6503
6504 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
6505 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
6506 sizeof(Mpi2RaidVolPage0_t)))
6507 continue;
6508
6509 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
6510 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
6511 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
6512 _scsih_mark_responding_raid_device(ioc,
6513 le64_to_cpu(volume_pg1.WWID), handle);
6514 }
6515
6516 /* refresh the pd_handles */
6517 phys_disk_num = 0xFF;
6518 memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
6519 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
6520 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
6521 phys_disk_num))) {
6522 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6523 MPI2_IOCSTATUS_MASK;
6524 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6525 break;
6526 phys_disk_num = pd_pg0.PhysDiskNum;
6527 handle = le16_to_cpu(pd_pg0.DevHandle);
6528 set_bit(handle, ioc->pd_handles);
6529 }
6530 out:
6531 pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n",
6532 ioc->name);
6533}
6534
6535/**
6536 * _scsih_mark_responding_expander - mark a expander as responding
6537 * @ioc: per adapter object
6538 * @sas_address: sas address
6539 * @handle:
6540 *
6541 * After host reset, find out whether devices are still responding.
6542 * Used in _scsih_remove_unresponsive_expanders.
6543 *
6544 * Return nothing.
6545 */
6546static void
6547_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
6548 u16 handle)
6549{
6550 struct _sas_node *sas_expander;
6551 unsigned long flags;
6552 int i;
6553
6554 spin_lock_irqsave(&ioc->sas_node_lock, flags);
6555 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
6556 if (sas_expander->sas_address != sas_address)
6557 continue;
6558 sas_expander->responding = 1;
6559 if (sas_expander->handle == handle)
6560 goto out;
6561 pr_info("\texpander(0x%016llx): handle changed" \
6562 " from(0x%04x) to (0x%04x)!!!\n",
6563 (unsigned long long)sas_expander->sas_address,
6564 sas_expander->handle, handle);
6565 sas_expander->handle = handle;
6566 for (i = 0 ; i < sas_expander->num_phys ; i++)
6567 sas_expander->phy[i].handle = handle;
6568 goto out;
6569 }
6570 out:
6571 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
6572}
6573
6574/**
6575 * _scsih_search_responding_expanders -
6576 * @ioc: per adapter object
6577 *
6578 * After host reset, find out whether devices are still responding.
6579 * If not remove.
6580 *
6581 * Return nothing.
6582 */
6583static void
6584_scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
6585{
6586 Mpi2ExpanderPage0_t expander_pg0;
6587 Mpi2ConfigReply_t mpi_reply;
6588 u16 ioc_status;
6589 u64 sas_address;
6590 u16 handle;
6591
6592 pr_info(MPT3SAS_FMT "search for expanders: start\n", ioc->name);
6593
6594 if (list_empty(&ioc->sas_expander_list))
6595 goto out;
6596
6597 handle = 0xFFFF;
6598 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
6599 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
6600
6601 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6602 MPI2_IOCSTATUS_MASK;
6603 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6604 break;
6605
6606 handle = le16_to_cpu(expander_pg0.DevHandle);
6607 sas_address = le64_to_cpu(expander_pg0.SASAddress);
6608 pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n",
6609 handle,
6610 (unsigned long long)sas_address);
6611 _scsih_mark_responding_expander(ioc, sas_address, handle);
6612 }
6613
6614 out:
6615 pr_info(MPT3SAS_FMT "search for expanders: complete\n", ioc->name);
6616}
6617
6618/**
6619 * _scsih_remove_unresponding_sas_devices - removing unresponding devices
6620 * @ioc: per adapter object
6621 *
6622 * Return nothing.
6623 */
6624static void
6625_scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
6626{
6627 struct _sas_device *sas_device, *sas_device_next;
6628 struct _sas_node *sas_expander, *sas_expander_next;
6629 struct _raid_device *raid_device, *raid_device_next;
6630 struct list_head tmp_list;
6631 unsigned long flags;
6632
6633 pr_info(MPT3SAS_FMT "removing unresponding devices: start\n",
6634 ioc->name);
6635
6636 /* removing unresponding end devices */
6637 pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n",
6638 ioc->name);
6639 list_for_each_entry_safe(sas_device, sas_device_next,
6640 &ioc->sas_device_list, list) {
6641 if (!sas_device->responding)
6642 mpt3sas_device_remove_by_sas_address(ioc,
6643 sas_device->sas_address);
6644 else
6645 sas_device->responding = 0;
6646 }
6647
6648 /* removing unresponding volumes */
6649 if (ioc->ir_firmware) {
6650 pr_info(MPT3SAS_FMT "removing unresponding devices: volumes\n",
6651 ioc->name);
6652 list_for_each_entry_safe(raid_device, raid_device_next,
6653 &ioc->raid_device_list, list) {
6654 if (!raid_device->responding)
6655 _scsih_sas_volume_delete(ioc,
6656 raid_device->handle);
6657 else
6658 raid_device->responding = 0;
6659 }
6660 }
6661
6662 /* removing unresponding expanders */
6663 pr_info(MPT3SAS_FMT "removing unresponding devices: expanders\n",
6664 ioc->name);
6665 spin_lock_irqsave(&ioc->sas_node_lock, flags);
6666 INIT_LIST_HEAD(&tmp_list);
6667 list_for_each_entry_safe(sas_expander, sas_expander_next,
6668 &ioc->sas_expander_list, list) {
6669 if (!sas_expander->responding)
6670 list_move_tail(&sas_expander->list, &tmp_list);
6671 else
6672 sas_expander->responding = 0;
6673 }
6674 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
6675 list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
6676 list) {
6677 list_del(&sas_expander->list);
6678 _scsih_expander_node_remove(ioc, sas_expander);
6679 }
6680
6681 pr_info(MPT3SAS_FMT "removing unresponding devices: complete\n",
6682 ioc->name);
6683
6684 /* unblock devices */
6685 _scsih_ublock_io_all_device(ioc);
6686}
6687
6688static void
6689_scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc,
6690 struct _sas_node *sas_expander, u16 handle)
6691{
6692 Mpi2ExpanderPage1_t expander_pg1;
6693 Mpi2ConfigReply_t mpi_reply;
6694 int i;
6695
6696 for (i = 0 ; i < sas_expander->num_phys ; i++) {
6697 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
6698 &expander_pg1, i, handle))) {
6699 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6700 ioc->name, __FILE__, __LINE__, __func__);
6701 return;
6702 }
6703
6704 mpt3sas_transport_update_links(ioc, sas_expander->sas_address,
6705 le16_to_cpu(expander_pg1.AttachedDevHandle), i,
6706 expander_pg1.NegotiatedLinkRate >> 4);
6707 }
6708}
6709
6710/**
6711 * _scsih_scan_for_devices_after_reset - scan for devices after host reset
6712 * @ioc: per adapter object
6713 *
6714 * Return nothing.
6715 */
6716static void
6717_scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
6718{
6719 Mpi2ExpanderPage0_t expander_pg0;
6720 Mpi2SasDevicePage0_t sas_device_pg0;
6721 Mpi2RaidVolPage1_t volume_pg1;
6722 Mpi2RaidVolPage0_t volume_pg0;
6723 Mpi2RaidPhysDiskPage0_t pd_pg0;
6724 Mpi2EventIrConfigElement_t element;
6725 Mpi2ConfigReply_t mpi_reply;
6726 u8 phys_disk_num;
6727 u16 ioc_status;
6728 u16 handle, parent_handle;
6729 u64 sas_address;
6730 struct _sas_device *sas_device;
6731 struct _sas_node *expander_device;
6732 static struct _raid_device *raid_device;
6733 u8 retry_count;
6734 unsigned long flags;
6735
6736 pr_info(MPT3SAS_FMT "scan devices: start\n", ioc->name);
6737
6738 _scsih_sas_host_refresh(ioc);
6739
6740 pr_info(MPT3SAS_FMT "\tscan devices: expanders start\n", ioc->name);
6741
6742 /* expanders */
6743 handle = 0xFFFF;
6744 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
6745 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
6746 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6747 MPI2_IOCSTATUS_MASK;
6748 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6749 break;
6750 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6751 pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \
6752 "ioc_status(0x%04x), loginfo(0x%08x)\n",
6753 ioc->name, ioc_status,
6754 le32_to_cpu(mpi_reply.IOCLogInfo));
6755 break;
6756 }
6757 handle = le16_to_cpu(expander_pg0.DevHandle);
6758 spin_lock_irqsave(&ioc->sas_node_lock, flags);
6759 expander_device = mpt3sas_scsih_expander_find_by_sas_address(
6760 ioc, le64_to_cpu(expander_pg0.SASAddress));
6761 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
6762 if (expander_device)
6763 _scsih_refresh_expander_links(ioc, expander_device,
6764 handle);
6765 else {
6766 pr_info(MPT3SAS_FMT "\tBEFORE adding expander: " \
6767 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
6768 handle, (unsigned long long)
6769 le64_to_cpu(expander_pg0.SASAddress));
6770 _scsih_expander_add(ioc, handle);
6771 pr_info(MPT3SAS_FMT "\tAFTER adding expander: " \
6772 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
6773 handle, (unsigned long long)
6774 le64_to_cpu(expander_pg0.SASAddress));
6775 }
6776 }
6777
6778 pr_info(MPT3SAS_FMT "\tscan devices: expanders complete\n",
6779 ioc->name);
6780
6781 if (!ioc->ir_firmware)
6782 goto skip_to_sas;
6783
6784 pr_info(MPT3SAS_FMT "\tscan devices: phys disk start\n", ioc->name);
6785
6786 /* phys disk */
6787 phys_disk_num = 0xFF;
6788 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
6789 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
6790 phys_disk_num))) {
6791 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6792 MPI2_IOCSTATUS_MASK;
6793 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6794 break;
6795 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6796 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\
6797 "ioc_status(0x%04x), loginfo(0x%08x)\n",
6798 ioc->name, ioc_status,
6799 le32_to_cpu(mpi_reply.IOCLogInfo));
6800 break;
6801 }
6802 phys_disk_num = pd_pg0.PhysDiskNum;
6803 handle = le16_to_cpu(pd_pg0.DevHandle);
6804 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6805 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
6806 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6807 if (sas_device)
6808 continue;
6809 if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6810 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6811 handle) != 0)
6812 continue;
6813 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6814 MPI2_IOCSTATUS_MASK;
6815 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6816 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan " \
6817 "ioc_status(0x%04x), loginfo(0x%08x)\n",
6818 ioc->name, ioc_status,
6819 le32_to_cpu(mpi_reply.IOCLogInfo));
6820 break;
6821 }
6822 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6823 if (!_scsih_get_sas_address(ioc, parent_handle,
6824 &sas_address)) {
6825 pr_info(MPT3SAS_FMT "\tBEFORE adding phys disk: " \
6826 " handle (0x%04x), sas_addr(0x%016llx)\n",
6827 ioc->name, handle, (unsigned long long)
6828 le64_to_cpu(sas_device_pg0.SASAddress));
6829 mpt3sas_transport_update_links(ioc, sas_address,
6830 handle, sas_device_pg0.PhyNum,
6831 MPI2_SAS_NEG_LINK_RATE_1_5);
6832 set_bit(handle, ioc->pd_handles);
6833 retry_count = 0;
6834 /* This will retry adding the end device.
6835 * _scsih_add_device() will decide on retries and
6836 * return "1" when it should be retried
6837 */
6838 while (_scsih_add_device(ioc, handle, retry_count++,
6839 1)) {
6840 ssleep(1);
6841 }
6842 pr_info(MPT3SAS_FMT "\tAFTER adding phys disk: " \
6843 " handle (0x%04x), sas_addr(0x%016llx)\n",
6844 ioc->name, handle, (unsigned long long)
6845 le64_to_cpu(sas_device_pg0.SASAddress));
6846 }
6847 }
6848
6849 pr_info(MPT3SAS_FMT "\tscan devices: phys disk complete\n",
6850 ioc->name);
6851
6852 pr_info(MPT3SAS_FMT "\tscan devices: volumes start\n", ioc->name);
6853
6854 /* volumes */
6855 handle = 0xFFFF;
6856 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
6857 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
6858 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6859 MPI2_IOCSTATUS_MASK;
6860 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6861 break;
6862 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6863 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
6864 "ioc_status(0x%04x), loginfo(0x%08x)\n",
6865 ioc->name, ioc_status,
6866 le32_to_cpu(mpi_reply.IOCLogInfo));
6867 break;
6868 }
6869 handle = le16_to_cpu(volume_pg1.DevHandle);
6870 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6871 raid_device = _scsih_raid_device_find_by_wwid(ioc,
6872 le64_to_cpu(volume_pg1.WWID));
6873 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6874 if (raid_device)
6875 continue;
6876 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
6877 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
6878 sizeof(Mpi2RaidVolPage0_t)))
6879 continue;
6880 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6881 MPI2_IOCSTATUS_MASK;
6882 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6883 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
6884 "ioc_status(0x%04x), loginfo(0x%08x)\n",
6885 ioc->name, ioc_status,
6886 le32_to_cpu(mpi_reply.IOCLogInfo));
6887 break;
6888 }
6889 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
6890 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
6891 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
6892 memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
6893 element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
6894 element.VolDevHandle = volume_pg1.DevHandle;
6895 pr_info(MPT3SAS_FMT
6896 "\tBEFORE adding volume: handle (0x%04x)\n",
6897 ioc->name, volume_pg1.DevHandle);
6898 _scsih_sas_volume_add(ioc, &element);
6899 pr_info(MPT3SAS_FMT
6900 "\tAFTER adding volume: handle (0x%04x)\n",
6901 ioc->name, volume_pg1.DevHandle);
6902 }
6903 }
6904
6905 pr_info(MPT3SAS_FMT "\tscan devices: volumes complete\n",
6906 ioc->name);
6907
6908 skip_to_sas:
6909
6910 pr_info(MPT3SAS_FMT "\tscan devices: end devices start\n",
6911 ioc->name);
6912
6913 /* sas devices */
6914 handle = 0xFFFF;
6915 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6916 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
6917 handle))) {
6918 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6919 MPI2_IOCSTATUS_MASK;
6920 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
6921 break;
6922 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6923 pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\
6924 " ioc_status(0x%04x), loginfo(0x%08x)\n",
6925 ioc->name, ioc_status,
6926 le32_to_cpu(mpi_reply.IOCLogInfo));
6927 break;
6928 }
6929 handle = le16_to_cpu(sas_device_pg0.DevHandle);
6930 if (!(_scsih_is_end_device(
6931 le32_to_cpu(sas_device_pg0.DeviceInfo))))
6932 continue;
6933 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6934 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
6935 le64_to_cpu(sas_device_pg0.SASAddress));
6936 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6937 if (sas_device)
6938 continue;
6939 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6940 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
6941 pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \
6942 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
6943 handle, (unsigned long long)
6944 le64_to_cpu(sas_device_pg0.SASAddress));
6945 mpt3sas_transport_update_links(ioc, sas_address, handle,
6946 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6947 retry_count = 0;
6948 /* This will retry adding the end device.
6949 * _scsih_add_device() will decide on retries and
6950 * return "1" when it should be retried
6951 */
6952 while (_scsih_add_device(ioc, handle, retry_count++,
6953 0)) {
6954 ssleep(1);
6955 }
6956 pr_info(MPT3SAS_FMT "\tAFTER adding end device: " \
6957 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
6958 handle, (unsigned long long)
6959 le64_to_cpu(sas_device_pg0.SASAddress));
6960 }
6961 }
6962 pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n",
6963 ioc->name);
6964
6965 pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name);
6966}
6967/**
6968 * mpt3sas_scsih_reset_handler - reset callback handler (for scsih)
6969 * @ioc: per adapter object
6970 * @reset_phase: phase
6971 *
6972 * The handler for doing any required cleanup or initialization.
6973 *
6974 * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
6975 * MPT3_IOC_DONE_RESET
6976 *
6977 * Return nothing.
6978 */
6979void
6980mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
6981{
6982 switch (reset_phase) {
6983 case MPT3_IOC_PRE_RESET:
6984 dtmprintk(ioc, pr_info(MPT3SAS_FMT
6985 "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
6986 break;
6987 case MPT3_IOC_AFTER_RESET:
6988 dtmprintk(ioc, pr_info(MPT3SAS_FMT
6989 "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
6990 if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) {
6991 ioc->scsih_cmds.status |= MPT3_CMD_RESET;
6992 mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
6993 complete(&ioc->scsih_cmds.done);
6994 }
6995 if (ioc->tm_cmds.status & MPT3_CMD_PENDING) {
6996 ioc->tm_cmds.status |= MPT3_CMD_RESET;
6997 mpt3sas_base_free_smid(ioc, ioc->tm_cmds.smid);
6998 complete(&ioc->tm_cmds.done);
6999 }
7000
7001 _scsih_fw_event_cleanup_queue(ioc);
7002 _scsih_flush_running_cmds(ioc);
7003 break;
7004 case MPT3_IOC_DONE_RESET:
7005 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7006 "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
7007 if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
7008 !ioc->sas_hba.num_phys)) {
7009 _scsih_prep_device_scan(ioc);
7010 _scsih_search_responding_sas_devices(ioc);
7011 _scsih_search_responding_raid_devices(ioc);
7012 _scsih_search_responding_expanders(ioc);
7013 _scsih_error_recovery_delete_devices(ioc);
7014 }
7015 break;
7016 }
7017}
7018
7019/**
7020 * _mpt3sas_fw_work - delayed task for processing firmware events
7021 * @ioc: per adapter object
7022 * @fw_event: The fw_event_work object
7023 * Context: user.
7024 *
7025 * Return nothing.
7026 */
7027static void
7028_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
7029{
7030 /* the queue is being flushed so ignore this event */
7031 if (ioc->remove_host || fw_event->cancel_pending_work ||
7032 ioc->pci_error_recovery) {
7033 _scsih_fw_event_free(ioc, fw_event);
7034 return;
7035 }
7036
7037 switch (fw_event->event) {
7038 case MPT3SAS_PROCESS_TRIGGER_DIAG:
7039 mpt3sas_process_trigger_data(ioc, fw_event->event_data);
7040 break;
7041 case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
7042 while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
7043 ssleep(1);
7044 _scsih_remove_unresponding_sas_devices(ioc);
7045 _scsih_scan_for_devices_after_reset(ioc);
7046 break;
7047 case MPT3SAS_PORT_ENABLE_COMPLETE:
7048 ioc->start_scan = 0;
7049 if (missing_delay[0] != -1 && missing_delay[1] != -1)
7050 mpt3sas_base_update_missing_delay(ioc, missing_delay[0],
7051 missing_delay[1]);
7052 dewtprintk(ioc, pr_info(MPT3SAS_FMT
7053 "port enable: complete from worker thread\n",
7054 ioc->name));
7055 break;
7056 case MPT3SAS_TURN_ON_FAULT_LED:
7057 _scsih_turn_on_fault_led(ioc, fw_event->device_handle);
7058 break;
7059 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7060 _scsih_sas_topology_change_event(ioc, fw_event);
7061 break;
7062 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7063 _scsih_sas_device_status_change_event(ioc, fw_event);
7064 break;
7065 case MPI2_EVENT_SAS_DISCOVERY:
7066 _scsih_sas_discovery_event(ioc, fw_event);
7067 break;
7068 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7069 _scsih_sas_broadcast_primitive_event(ioc, fw_event);
7070 break;
7071 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7072 _scsih_sas_enclosure_dev_status_change_event(ioc,
7073 fw_event);
7074 break;
7075 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7076 _scsih_sas_ir_config_change_event(ioc, fw_event);
7077 break;
7078 case MPI2_EVENT_IR_VOLUME:
7079 _scsih_sas_ir_volume_event(ioc, fw_event);
7080 break;
7081 case MPI2_EVENT_IR_PHYSICAL_DISK:
7082 _scsih_sas_ir_physical_disk_event(ioc, fw_event);
7083 break;
7084 case MPI2_EVENT_IR_OPERATION_STATUS:
7085 _scsih_sas_ir_operation_status_event(ioc, fw_event);
7086 break;
7087 }
7088 _scsih_fw_event_free(ioc, fw_event);
7089}
7090
7091/**
7092 * _firmware_event_work
7093 * @ioc: per adapter object
7094 * @work: The fw_event_work object
7095 * Context: user.
7096 *
7097 * wrappers for the work thread handling firmware events
7098 *
7099 * Return nothing.
7100 */
7101
7102static void
7103_firmware_event_work(struct work_struct *work)
7104{
7105 struct fw_event_work *fw_event = container_of(work,
7106 struct fw_event_work, work);
7107
7108 _mpt3sas_fw_work(fw_event->ioc, fw_event);
7109}
7110
7111/**
7112 * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time)
7113 * @ioc: per adapter object
7114 * @msix_index: MSIX table index supplied by the OS
7115 * @reply: reply message frame(lower 32bit addr)
7116 * Context: interrupt.
7117 *
7118 * This function merely adds a new work task into ioc->firmware_event_thread.
7119 * The tasks are worked from _firmware_event_work in user context.
7120 *
7121 * Return 1 meaning mf should be freed from _base_interrupt
7122 * 0 means the mf is freed from this function.
7123 */
7124u8
7125mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
7126 u32 reply)
7127{
7128 struct fw_event_work *fw_event;
7129 Mpi2EventNotificationReply_t *mpi_reply;
7130 u16 event;
7131 u16 sz;
7132
7133 /* events turned off due to host reset or driver unloading */
7134 if (ioc->remove_host || ioc->pci_error_recovery)
7135 return 1;
7136
7137 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
7138
7139 if (unlikely(!mpi_reply)) {
7140 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
7141 ioc->name, __FILE__, __LINE__, __func__);
7142 return 1;
7143 }
7144
7145 event = le16_to_cpu(mpi_reply->Event);
7146
7147 if (event != MPI2_EVENT_LOG_ENTRY_ADDED)
7148 mpt3sas_trigger_event(ioc, event, 0);
7149
7150 switch (event) {
7151 /* handle these */
7152 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7153 {
7154 Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
7155 (Mpi2EventDataSasBroadcastPrimitive_t *)
7156 mpi_reply->EventData;
7157
7158 if (baen_data->Primitive !=
7159 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
7160 return 1;
7161
7162 if (ioc->broadcast_aen_busy) {
7163 ioc->broadcast_aen_pending++;
7164 return 1;
7165 } else
7166 ioc->broadcast_aen_busy = 1;
7167 break;
7168 }
7169
7170 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7171 _scsih_check_topo_delete_events(ioc,
7172 (Mpi2EventDataSasTopologyChangeList_t *)
7173 mpi_reply->EventData);
7174 break;
7175 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7176 _scsih_check_ir_config_unhide_events(ioc,
7177 (Mpi2EventDataIrConfigChangeList_t *)
7178 mpi_reply->EventData);
7179 break;
7180 case MPI2_EVENT_IR_VOLUME:
7181 _scsih_check_volume_delete_events(ioc,
7182 (Mpi2EventDataIrVolume_t *)
7183 mpi_reply->EventData);
7184 break;
7185
7186 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7187 case MPI2_EVENT_IR_OPERATION_STATUS:
7188 case MPI2_EVENT_SAS_DISCOVERY:
7189 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7190 case MPI2_EVENT_IR_PHYSICAL_DISK:
7191 break;
7192
7193 default: /* ignore the rest */
7194 return 1;
7195 }
7196
7197 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
7198 if (!fw_event) {
7199 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7200 ioc->name, __FILE__, __LINE__, __func__);
7201 return 1;
7202 }
7203 sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
7204 fw_event->event_data = kzalloc(sz, GFP_ATOMIC);
7205 if (!fw_event->event_data) {
7206 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7207 ioc->name, __FILE__, __LINE__, __func__);
7208 kfree(fw_event);
7209 return 1;
7210 }
7211
7212 memcpy(fw_event->event_data, mpi_reply->EventData, sz);
7213 fw_event->ioc = ioc;
7214 fw_event->VF_ID = mpi_reply->VF_ID;
7215 fw_event->VP_ID = mpi_reply->VP_ID;
7216 fw_event->event = event;
7217 _scsih_fw_event_add(ioc, fw_event);
7218 return 1;
7219}
7220
7221/* shost template */
7222static struct scsi_host_template scsih_driver_template = {
7223 .module = THIS_MODULE,
7224 .name = "Fusion MPT SAS Host",
7225 .proc_name = MPT3SAS_DRIVER_NAME,
7226 .queuecommand = _scsih_qcmd,
7227 .target_alloc = _scsih_target_alloc,
7228 .slave_alloc = _scsih_slave_alloc,
7229 .slave_configure = _scsih_slave_configure,
7230 .target_destroy = _scsih_target_destroy,
7231 .slave_destroy = _scsih_slave_destroy,
7232 .scan_finished = _scsih_scan_finished,
7233 .scan_start = _scsih_scan_start,
7234 .change_queue_depth = _scsih_change_queue_depth,
7235 .change_queue_type = _scsih_change_queue_type,
7236 .eh_abort_handler = _scsih_abort,
7237 .eh_device_reset_handler = _scsih_dev_reset,
7238 .eh_target_reset_handler = _scsih_target_reset,
7239 .eh_host_reset_handler = _scsih_host_reset,
7240 .bios_param = _scsih_bios_param,
7241 .can_queue = 1,
7242 .this_id = -1,
7243 .sg_tablesize = MPT3SAS_SG_DEPTH,
7244 .max_sectors = 32767,
7245 .cmd_per_lun = 7,
7246 .use_clustering = ENABLE_CLUSTERING,
7247 .shost_attrs = mpt3sas_host_attrs,
7248 .sdev_attrs = mpt3sas_dev_attrs,
7249};
7250
7251/**
7252 * _scsih_expander_node_remove - removing expander device from list.
7253 * @ioc: per adapter object
7254 * @sas_expander: the sas_device object
7255 * Context: Calling function should acquire ioc->sas_node_lock.
7256 *
7257 * Removing object and freeing associated memory from the
7258 * ioc->sas_expander_list.
7259 *
7260 * Return nothing.
7261 */
7262static void
7263_scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
7264 struct _sas_node *sas_expander)
7265{
7266 struct _sas_port *mpt3sas_port, *next;
7267
7268 /* remove sibling ports attached to this expander */
7269 list_for_each_entry_safe(mpt3sas_port, next,
7270 &sas_expander->sas_port_list, port_list) {
7271 if (ioc->shost_recovery)
7272 return;
7273 if (mpt3sas_port->remote_identify.device_type ==
7274 SAS_END_DEVICE)
7275 mpt3sas_device_remove_by_sas_address(ioc,
7276 mpt3sas_port->remote_identify.sas_address);
7277 else if (mpt3sas_port->remote_identify.device_type ==
7278 SAS_EDGE_EXPANDER_DEVICE ||
7279 mpt3sas_port->remote_identify.device_type ==
7280 SAS_FANOUT_EXPANDER_DEVICE)
7281 mpt3sas_expander_remove(ioc,
7282 mpt3sas_port->remote_identify.sas_address);
7283 }
7284
7285 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
7286 sas_expander->sas_address_parent);
7287
7288 pr_info(MPT3SAS_FMT
7289 "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n",
7290 ioc->name,
7291 sas_expander->handle, (unsigned long long)
7292 sas_expander->sas_address);
7293
7294 kfree(sas_expander->phy);
7295 kfree(sas_expander);
7296}
7297
7298/**
7299 * _scsih_ir_shutdown - IR shutdown notification
7300 * @ioc: per adapter object
7301 *
7302 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
7303 * the host system is shutting down.
7304 *
7305 * Return nothing.
7306 */
7307static void
7308_scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
7309{
7310 Mpi2RaidActionRequest_t *mpi_request;
7311 Mpi2RaidActionReply_t *mpi_reply;
7312 u16 smid;
7313
7314 /* is IR firmware build loaded ? */
7315 if (!ioc->ir_firmware)
7316 return;
7317
7318 /* are there any volumes ? */
7319 if (list_empty(&ioc->raid_device_list))
7320 return;
7321
7322 mutex_lock(&ioc->scsih_cmds.mutex);
7323
7324 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
7325 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
7326 ioc->name, __func__);
7327 goto out;
7328 }
7329 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
7330
7331 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
7332 if (!smid) {
7333 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
7334 ioc->name, __func__);
7335 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
7336 goto out;
7337 }
7338
7339 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
7340 ioc->scsih_cmds.smid = smid;
7341 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
7342
7343 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
7344 mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
7345
7346 pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
7347 init_completion(&ioc->scsih_cmds.done);
7348 mpt3sas_base_put_smid_default(ioc, smid);
7349 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
7350
7351 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
7352 pr_err(MPT3SAS_FMT "%s: timeout\n",
7353 ioc->name, __func__);
7354 goto out;
7355 }
7356
7357 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
7358 mpi_reply = ioc->scsih_cmds.reply;
7359 pr_info(MPT3SAS_FMT
7360 "IR shutdown (complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
7361 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
7362 le32_to_cpu(mpi_reply->IOCLogInfo));
7363 }
7364
7365 out:
7366 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
7367 mutex_unlock(&ioc->scsih_cmds.mutex);
7368}
7369
7370/**
7371 * _scsih_remove - detach and remove add host
7372 * @pdev: PCI device struct
7373 *
7374 * Routine called when unloading the driver.
7375 * Return nothing.
7376 */
7377static void __devexit
7378_scsih_remove(struct pci_dev *pdev)
7379{
7380 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7381 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7382 struct _sas_port *mpt3sas_port, *next_port;
7383 struct _raid_device *raid_device, *next;
7384 struct MPT3SAS_TARGET *sas_target_priv_data;
7385 struct workqueue_struct *wq;
7386 unsigned long flags;
7387
7388 ioc->remove_host = 1;
7389 _scsih_fw_event_cleanup_queue(ioc);
7390
7391 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7392 wq = ioc->firmware_event_thread;
7393 ioc->firmware_event_thread = NULL;
7394 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7395 if (wq)
7396 destroy_workqueue(wq);
7397
7398 /* release all the volumes */
7399 _scsih_ir_shutdown(ioc);
7400 list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
7401 list) {
7402 if (raid_device->starget) {
7403 sas_target_priv_data =
7404 raid_device->starget->hostdata;
7405 sas_target_priv_data->deleted = 1;
7406 scsi_remove_target(&raid_device->starget->dev);
7407 }
7408 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
7409 ioc->name, raid_device->handle,
7410 (unsigned long long) raid_device->wwid);
7411 _scsih_raid_device_remove(ioc, raid_device);
7412 }
7413
7414 /* free ports attached to the sas_host */
7415 list_for_each_entry_safe(mpt3sas_port, next_port,
7416 &ioc->sas_hba.sas_port_list, port_list) {
7417 if (mpt3sas_port->remote_identify.device_type ==
7418 SAS_END_DEVICE)
7419 mpt3sas_device_remove_by_sas_address(ioc,
7420 mpt3sas_port->remote_identify.sas_address);
7421 else if (mpt3sas_port->remote_identify.device_type ==
7422 SAS_EDGE_EXPANDER_DEVICE ||
7423 mpt3sas_port->remote_identify.device_type ==
7424 SAS_FANOUT_EXPANDER_DEVICE)
7425 mpt3sas_expander_remove(ioc,
7426 mpt3sas_port->remote_identify.sas_address);
7427 }
7428
7429 /* free phys attached to the sas_host */
7430 if (ioc->sas_hba.num_phys) {
7431 kfree(ioc->sas_hba.phy);
7432 ioc->sas_hba.phy = NULL;
7433 ioc->sas_hba.num_phys = 0;
7434 }
7435
7436 sas_remove_host(shost);
7437 mpt3sas_base_detach(ioc);
7438 list_del(&ioc->list);
7439 scsi_remove_host(shost);
7440 scsi_host_put(shost);
7441}
7442
7443/**
7444 * _scsih_shutdown - routine call during system shutdown
7445 * @pdev: PCI device struct
7446 *
7447 * Return nothing.
7448 */
7449static void
7450_scsih_shutdown(struct pci_dev *pdev)
7451{
7452 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7453 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7454 struct workqueue_struct *wq;
7455 unsigned long flags;
7456
7457 ioc->remove_host = 1;
7458 _scsih_fw_event_cleanup_queue(ioc);
7459
7460 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7461 wq = ioc->firmware_event_thread;
7462 ioc->firmware_event_thread = NULL;
7463 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7464 if (wq)
7465 destroy_workqueue(wq);
7466
7467 _scsih_ir_shutdown(ioc);
7468 mpt3sas_base_detach(ioc);
7469}
7470
7471
7472/**
7473 * _scsih_probe_boot_devices - reports 1st device
7474 * @ioc: per adapter object
7475 *
7476 * If specified in bios page 2, this routine reports the 1st
7477 * device scsi-ml or sas transport for persistent boot device
7478 * purposes. Please refer to function _scsih_determine_boot_device()
7479 */
7480static void
7481_scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
7482{
7483 u8 is_raid;
7484 void *device;
7485 struct _sas_device *sas_device;
7486 struct _raid_device *raid_device;
7487 u16 handle;
7488 u64 sas_address_parent;
7489 u64 sas_address;
7490 unsigned long flags;
7491 int rc;
7492
7493 /* no Bios, return immediately */
7494 if (!ioc->bios_pg3.BiosVersion)
7495 return;
7496
7497 device = NULL;
7498 is_raid = 0;
7499 if (ioc->req_boot_device.device) {
7500 device = ioc->req_boot_device.device;
7501 is_raid = ioc->req_boot_device.is_raid;
7502 } else if (ioc->req_alt_boot_device.device) {
7503 device = ioc->req_alt_boot_device.device;
7504 is_raid = ioc->req_alt_boot_device.is_raid;
7505 } else if (ioc->current_boot_device.device) {
7506 device = ioc->current_boot_device.device;
7507 is_raid = ioc->current_boot_device.is_raid;
7508 }
7509
7510 if (!device)
7511 return;
7512
7513 if (is_raid) {
7514 raid_device = device;
7515 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
7516 raid_device->id, 0);
7517 if (rc)
7518 _scsih_raid_device_remove(ioc, raid_device);
7519 } else {
7520 spin_lock_irqsave(&ioc->sas_device_lock, flags);
7521 sas_device = device;
7522 handle = sas_device->handle;
7523 sas_address_parent = sas_device->sas_address_parent;
7524 sas_address = sas_device->sas_address;
7525 list_move_tail(&sas_device->list, &ioc->sas_device_list);
7526 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
7527
7528 if (!mpt3sas_transport_port_add(ioc, handle,
7529 sas_address_parent)) {
7530 _scsih_sas_device_remove(ioc, sas_device);
7531 } else if (!sas_device->starget) {
7532 if (!ioc->is_driver_loading)
7533 mpt3sas_transport_port_remove(ioc, sas_address,
7534 sas_address_parent);
7535 _scsih_sas_device_remove(ioc, sas_device);
7536 }
7537 }
7538}
7539
7540/**
7541 * _scsih_probe_raid - reporting raid volumes to scsi-ml
7542 * @ioc: per adapter object
7543 *
7544 * Called during initial loading of the driver.
7545 */
7546static void
7547_scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
7548{
7549 struct _raid_device *raid_device, *raid_next;
7550 int rc;
7551
7552 list_for_each_entry_safe(raid_device, raid_next,
7553 &ioc->raid_device_list, list) {
7554 if (raid_device->starget)
7555 continue;
7556 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
7557 raid_device->id, 0);
7558 if (rc)
7559 _scsih_raid_device_remove(ioc, raid_device);
7560 }
7561}
7562
7563/**
7564 * _scsih_probe_sas - reporting sas devices to sas transport
7565 * @ioc: per adapter object
7566 *
7567 * Called during initial loading of the driver.
7568 */
7569static void
7570_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
7571{
7572 struct _sas_device *sas_device, *next;
7573 unsigned long flags;
7574
7575 /* SAS Device List */
7576 list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
7577 list) {
7578
7579 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
7580 sas_device->sas_address_parent)) {
7581 list_del(&sas_device->list);
7582 kfree(sas_device);
7583 continue;
7584 } else if (!sas_device->starget) {
7585 /*
7586 * When asyn scanning is enabled, its not possible to
7587 * remove devices while scanning is turned on due to an
7588 * oops in scsi_sysfs_add_sdev()->add_device()->
7589 * sysfs_addrm_start()
7590 */
7591 if (!ioc->is_driver_loading)
7592 mpt3sas_transport_port_remove(ioc,
7593 sas_device->sas_address,
7594 sas_device->sas_address_parent);
7595 list_del(&sas_device->list);
7596 kfree(sas_device);
7597 continue;
7598 }
7599
7600 spin_lock_irqsave(&ioc->sas_device_lock, flags);
7601 list_move_tail(&sas_device->list, &ioc->sas_device_list);
7602 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
7603 }
7604}
7605
7606/**
7607 * _scsih_probe_devices - probing for devices
7608 * @ioc: per adapter object
7609 *
7610 * Called during initial loading of the driver.
7611 */
7612static void
7613_scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
7614{
7615 u16 volume_mapping_flags;
7616
7617 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
7618 return; /* return when IOC doesn't support initiator mode */
7619
7620 _scsih_probe_boot_devices(ioc);
7621
7622 if (ioc->ir_firmware) {
7623 volume_mapping_flags =
7624 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
7625 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
7626 if (volume_mapping_flags ==
7627 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
7628 _scsih_probe_raid(ioc);
7629 _scsih_probe_sas(ioc);
7630 } else {
7631 _scsih_probe_sas(ioc);
7632 _scsih_probe_raid(ioc);
7633 }
7634 } else
7635 _scsih_probe_sas(ioc);
7636}
7637
7638/**
7639 * _scsih_scan_start - scsi lld callback for .scan_start
7640 * @shost: SCSI host pointer
7641 *
7642 * The shost has the ability to discover targets on its own instead
7643 * of scanning the entire bus. In our implemention, we will kick off
7644 * firmware discovery.
7645 */
7646static void
7647_scsih_scan_start(struct Scsi_Host *shost)
7648{
7649 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7650 int rc;
7651 if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
7652 mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
7653
7654 if (disable_discovery > 0)
7655 return;
7656
7657 ioc->start_scan = 1;
7658 rc = mpt3sas_port_enable(ioc);
7659
7660 if (rc != 0)
7661 pr_info(MPT3SAS_FMT "port enable: FAILED\n", ioc->name);
7662}
7663
7664/**
7665 * _scsih_scan_finished - scsi lld callback for .scan_finished
7666 * @shost: SCSI host pointer
7667 * @time: elapsed time of the scan in jiffies
7668 *
7669 * This function will be called periodicallyn until it returns 1 with the
7670 * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
7671 * we wait for firmware discovery to complete, then return 1.
7672 */
7673static int
7674_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
7675{
7676 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7677
7678 if (disable_discovery > 0) {
7679 ioc->is_driver_loading = 0;
7680 ioc->wait_for_discovery_to_complete = 0;
7681 return 1;
7682 }
7683
7684 if (time >= (300 * HZ)) {
7685 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
7686 pr_info(MPT3SAS_FMT
7687 "port enable: FAILED with timeout (timeout=300s)\n",
7688 ioc->name);
7689 ioc->is_driver_loading = 0;
7690 return 1;
7691 }
7692
7693 if (ioc->start_scan)
7694 return 0;
7695
7696 if (ioc->start_scan_failed) {
7697 pr_info(MPT3SAS_FMT
7698 "port enable: FAILED with (ioc_status=0x%08x)\n",
7699 ioc->name, ioc->start_scan_failed);
7700 ioc->is_driver_loading = 0;
7701 ioc->wait_for_discovery_to_complete = 0;
7702 ioc->remove_host = 1;
7703 return 1;
7704 }
7705
7706 pr_info(MPT3SAS_FMT "port enable: SUCCESS\n", ioc->name);
7707 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
7708
7709 if (ioc->wait_for_discovery_to_complete) {
7710 ioc->wait_for_discovery_to_complete = 0;
7711 _scsih_probe_devices(ioc);
7712 }
7713 mpt3sas_base_start_watchdog(ioc);
7714 ioc->is_driver_loading = 0;
7715 return 1;
7716}
7717
7718/**
7719 * _scsih_probe - attach and add scsi host
7720 * @pdev: PCI device struct
7721 * @id: pci device id
7722 *
7723 * Returns 0 success, anything else error.
7724 */
7725static int
7726_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
7727{
7728 struct MPT3SAS_ADAPTER *ioc;
7729 struct Scsi_Host *shost;
7730
7731 shost = scsi_host_alloc(&scsih_driver_template,
7732 sizeof(struct MPT3SAS_ADAPTER));
7733 if (!shost)
7734 return -ENODEV;
7735
7736 /* init local params */
7737 ioc = shost_priv(shost);
7738 memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
7739 INIT_LIST_HEAD(&ioc->list);
7740 list_add_tail(&ioc->list, &mpt3sas_ioc_list);
7741 ioc->shost = shost;
7742 ioc->id = mpt_ids++;
7743 sprintf(ioc->name, "%s%d", MPT3SAS_DRIVER_NAME, ioc->id);
7744 ioc->pdev = pdev;
7745 ioc->scsi_io_cb_idx = scsi_io_cb_idx;
7746 ioc->tm_cb_idx = tm_cb_idx;
7747 ioc->ctl_cb_idx = ctl_cb_idx;
7748 ioc->base_cb_idx = base_cb_idx;
7749 ioc->port_enable_cb_idx = port_enable_cb_idx;
7750 ioc->transport_cb_idx = transport_cb_idx;
7751 ioc->scsih_cb_idx = scsih_cb_idx;
7752 ioc->config_cb_idx = config_cb_idx;
7753 ioc->tm_tr_cb_idx = tm_tr_cb_idx;
7754 ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
7755 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
7756 ioc->logging_level = logging_level;
7757 ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
7758 /* misc semaphores and spin locks */
7759 mutex_init(&ioc->reset_in_progress_mutex);
7760 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
7761 spin_lock_init(&ioc->scsi_lookup_lock);
7762 spin_lock_init(&ioc->sas_device_lock);
7763 spin_lock_init(&ioc->sas_node_lock);
7764 spin_lock_init(&ioc->fw_event_lock);
7765 spin_lock_init(&ioc->raid_device_lock);
7766 spin_lock_init(&ioc->diag_trigger_lock);
7767
7768 INIT_LIST_HEAD(&ioc->sas_device_list);
7769 INIT_LIST_HEAD(&ioc->sas_device_init_list);
7770 INIT_LIST_HEAD(&ioc->sas_expander_list);
7771 INIT_LIST_HEAD(&ioc->fw_event_list);
7772 INIT_LIST_HEAD(&ioc->raid_device_list);
7773 INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
7774 INIT_LIST_HEAD(&ioc->delayed_tr_list);
7775 INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
7776
7777 /* init shost parameters */
7778 shost->max_cmd_len = 32;
7779 shost->max_lun = max_lun;
7780 shost->transportt = mpt3sas_transport_template;
7781 shost->unique_id = ioc->id;
7782
7783 if (max_sectors != 0xFFFF) {
7784 if (max_sectors < 64) {
7785 shost->max_sectors = 64;
7786 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
7787 "for max_sectors, range is 64 to 32767. Assigning "
7788 "value of 64.\n", ioc->name, max_sectors);
7789 } else if (max_sectors > 32767) {
7790 shost->max_sectors = 32767;
7791 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
7792 "for max_sectors, range is 64 to 32767. Assigning "
7793 "default value of 32767.\n", ioc->name,
7794 max_sectors);
7795 } else {
7796 shost->max_sectors = max_sectors & 0xFFFE;
7797 pr_info(MPT3SAS_FMT
7798 "The max_sectors value is set to %d\n",
7799 ioc->name, shost->max_sectors);
7800 }
7801 }
7802
7803 if ((scsi_add_host(shost, &pdev->dev))) {
7804 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7805 ioc->name, __FILE__, __LINE__, __func__);
7806 list_del(&ioc->list);
7807 goto out_add_shost_fail;
7808 }
7809
7810 /* register EEDP capabilities with SCSI layer */
7811 if (prot_mask > 0)
7812 scsi_host_set_prot(shost, prot_mask);
7813 else
7814 scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
7815 | SHOST_DIF_TYPE2_PROTECTION
7816 | SHOST_DIF_TYPE3_PROTECTION);
7817
7818 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
7819
7820 /* event thread */
7821 snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
7822 "fw_event%d", ioc->id);
7823 ioc->firmware_event_thread = create_singlethread_workqueue(
7824 ioc->firmware_event_name);
7825 if (!ioc->firmware_event_thread) {
7826 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7827 ioc->name, __FILE__, __LINE__, __func__);
7828 goto out_thread_fail;
7829 }
7830
7831 ioc->is_driver_loading = 1;
7832 if ((mpt3sas_base_attach(ioc))) {
7833 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7834 ioc->name, __FILE__, __LINE__, __func__);
7835 goto out_attach_fail;
7836 }
7837 scsi_scan_host(shost);
7838 return 0;
7839
7840 out_attach_fail:
7841 destroy_workqueue(ioc->firmware_event_thread);
7842 out_thread_fail:
7843 list_del(&ioc->list);
7844 scsi_remove_host(shost);
7845 out_add_shost_fail:
7846 scsi_host_put(shost);
7847 return -ENODEV;
7848}
7849
7850#ifdef CONFIG_PM
7851/**
7852 * _scsih_suspend - power management suspend main entry point
7853 * @pdev: PCI device struct
7854 * @state: PM state change to (usually PCI_D3)
7855 *
7856 * Returns 0 success, anything else error.
7857 */
7858static int
7859_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
7860{
7861 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7862 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7863 pci_power_t device_state;
7864
7865 mpt3sas_base_stop_watchdog(ioc);
7866 flush_scheduled_work();
7867 scsi_block_requests(shost);
7868 device_state = pci_choose_state(pdev, state);
7869 pr_info(MPT3SAS_FMT
7870 "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
7871 ioc->name, pdev, pci_name(pdev), device_state);
7872
7873 pci_save_state(pdev);
7874 mpt3sas_base_free_resources(ioc);
7875 pci_set_power_state(pdev, device_state);
7876 return 0;
7877}
7878
7879/**
7880 * _scsih_resume - power management resume main entry point
7881 * @pdev: PCI device struct
7882 *
7883 * Returns 0 success, anything else error.
7884 */
7885static int
7886_scsih_resume(struct pci_dev *pdev)
7887{
7888 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7889 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7890 pci_power_t device_state = pdev->current_state;
7891 int r;
7892
7893 pr_info(MPT3SAS_FMT
7894 "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
7895 ioc->name, pdev, pci_name(pdev), device_state);
7896
7897 pci_set_power_state(pdev, PCI_D0);
7898 pci_enable_wake(pdev, PCI_D0, 0);
7899 pci_restore_state(pdev);
7900 ioc->pdev = pdev;
7901 r = mpt3sas_base_map_resources(ioc);
7902 if (r)
7903 return r;
7904
7905 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
7906 scsi_unblock_requests(shost);
7907 mpt3sas_base_start_watchdog(ioc);
7908 return 0;
7909}
7910#endif /* CONFIG_PM */
7911
7912/**
7913 * _scsih_pci_error_detected - Called when a PCI error is detected.
7914 * @pdev: PCI device struct
7915 * @state: PCI channel state
7916 *
7917 * Description: Called when a PCI error is detected.
7918 *
7919 * Return value:
7920 * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
7921 */
7922static pci_ers_result_t
7923_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
7924{
7925 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7926 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7927
7928 pr_info(MPT3SAS_FMT "PCI error: detected callback, state(%d)!!\n",
7929 ioc->name, state);
7930
7931 switch (state) {
7932 case pci_channel_io_normal:
7933 return PCI_ERS_RESULT_CAN_RECOVER;
7934 case pci_channel_io_frozen:
7935 /* Fatal error, prepare for slot reset */
7936 ioc->pci_error_recovery = 1;
7937 scsi_block_requests(ioc->shost);
7938 mpt3sas_base_stop_watchdog(ioc);
7939 mpt3sas_base_free_resources(ioc);
7940 return PCI_ERS_RESULT_NEED_RESET;
7941 case pci_channel_io_perm_failure:
7942 /* Permanent error, prepare for device removal */
7943 ioc->pci_error_recovery = 1;
7944 mpt3sas_base_stop_watchdog(ioc);
7945 _scsih_flush_running_cmds(ioc);
7946 return PCI_ERS_RESULT_DISCONNECT;
7947 }
7948 return PCI_ERS_RESULT_NEED_RESET;
7949}
7950
7951/**
7952 * _scsih_pci_slot_reset - Called when PCI slot has been reset.
7953 * @pdev: PCI device struct
7954 *
7955 * Description: This routine is called by the pci error recovery
7956 * code after the PCI slot has been reset, just before we
7957 * should resume normal operations.
7958 */
7959static pci_ers_result_t
7960_scsih_pci_slot_reset(struct pci_dev *pdev)
7961{
7962 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7963 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7964 int rc;
7965
7966 pr_info(MPT3SAS_FMT "PCI error: slot reset callback!!\n",
7967 ioc->name);
7968
7969 ioc->pci_error_recovery = 0;
7970 ioc->pdev = pdev;
7971 pci_restore_state(pdev);
7972 rc = mpt3sas_base_map_resources(ioc);
7973 if (rc)
7974 return PCI_ERS_RESULT_DISCONNECT;
7975
7976 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
7977 FORCE_BIG_HAMMER);
7978
7979 pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name,
7980 (rc == 0) ? "success" : "failed");
7981
7982 if (!rc)
7983 return PCI_ERS_RESULT_RECOVERED;
7984 else
7985 return PCI_ERS_RESULT_DISCONNECT;
7986}
7987
7988/**
7989 * _scsih_pci_resume() - resume normal ops after PCI reset
7990 * @pdev: pointer to PCI device
7991 *
7992 * Called when the error recovery driver tells us that its
7993 * OK to resume normal operation. Use completion to allow
7994 * halted scsi ops to resume.
7995 */
7996static void
7997_scsih_pci_resume(struct pci_dev *pdev)
7998{
7999 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8000 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8001
8002 pr_info(MPT3SAS_FMT "PCI error: resume callback!!\n", ioc->name);
8003
8004 pci_cleanup_aer_uncorrect_error_status(pdev);
8005 mpt3sas_base_start_watchdog(ioc);
8006 scsi_unblock_requests(ioc->shost);
8007}
8008
8009/**
8010 * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
8011 * @pdev: pointer to PCI device
8012 */
8013static pci_ers_result_t
8014_scsih_pci_mmio_enabled(struct pci_dev *pdev)
8015{
8016 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8017 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8018
8019 pr_info(MPT3SAS_FMT "PCI error: mmio enabled callback!!\n",
8020 ioc->name);
8021
8022 /* TODO - dump whatever for debugging purposes */
8023
8024 /* Request a slot reset. */
8025 return PCI_ERS_RESULT_NEED_RESET;
8026}
8027
8028/* raid transport support */
8029static struct raid_function_template mpt3sas_raid_functions = {
8030 .cookie = &scsih_driver_template,
8031 .is_raid = _scsih_is_raid,
8032 .get_resync = _scsih_get_resync,
8033 .get_state = _scsih_get_state,
8034};
8035
8036static struct pci_error_handlers _scsih_err_handler = {
8037 .error_detected = _scsih_pci_error_detected,
8038 .mmio_enabled = _scsih_pci_mmio_enabled,
8039 .slot_reset = _scsih_pci_slot_reset,
8040 .resume = _scsih_pci_resume,
8041};
8042
8043static struct pci_driver scsih_driver = {
8044 .name = MPT3SAS_DRIVER_NAME,
8045 .id_table = scsih_pci_table,
8046 .probe = _scsih_probe,
8047 .remove = __devexit_p(_scsih_remove),
8048 .shutdown = _scsih_shutdown,
8049 .err_handler = &_scsih_err_handler,
8050#ifdef CONFIG_PM
8051 .suspend = _scsih_suspend,
8052 .resume = _scsih_resume,
8053#endif
8054};
8055
8056
8057/**
8058 * _scsih_init - main entry point for this driver.
8059 *
8060 * Returns 0 success, anything else error.
8061 */
8062static int __init
8063_scsih_init(void)
8064{
8065 int error;
8066
8067 mpt_ids = 0;
8068
8069 pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
8070 MPT3SAS_DRIVER_VERSION);
8071
8072 mpt3sas_transport_template =
8073 sas_attach_transport(&mpt3sas_transport_functions);
8074 if (!mpt3sas_transport_template)
8075 return -ENODEV;
8076
8077/* raid transport support */
8078 mpt3sas_raid_template = raid_class_attach(&mpt3sas_raid_functions);
8079 if (!mpt3sas_raid_template) {
8080 sas_release_transport(mpt3sas_transport_template);
8081 return -ENODEV;
8082 }
8083
8084 mpt3sas_base_initialize_callback_handler();
8085
8086 /* queuecommand callback hander */
8087 scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done);
8088
8089 /* task managment callback handler */
8090 tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done);
8091
8092 /* base internal commands callback handler */
8093 base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done);
8094 port_enable_cb_idx = mpt3sas_base_register_callback_handler(
8095 mpt3sas_port_enable_done);
8096
8097 /* transport internal commands callback handler */
8098 transport_cb_idx = mpt3sas_base_register_callback_handler(
8099 mpt3sas_transport_done);
8100
8101 /* scsih internal commands callback handler */
8102 scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done);
8103
8104 /* configuration page API internal commands callback handler */
8105 config_cb_idx = mpt3sas_base_register_callback_handler(
8106 mpt3sas_config_done);
8107
8108 /* ctl module callback handler */
8109 ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done);
8110
8111 tm_tr_cb_idx = mpt3sas_base_register_callback_handler(
8112 _scsih_tm_tr_complete);
8113
8114 tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler(
8115 _scsih_tm_volume_tr_complete);
8116
8117 tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
8118 _scsih_sas_control_complete);
8119
8120 mpt3sas_ctl_init();
8121
8122 error = pci_register_driver(&scsih_driver);
8123 if (error) {
8124 /* raid transport support */
8125 raid_class_release(mpt3sas_raid_template);
8126 sas_release_transport(mpt3sas_transport_template);
8127 }
8128
8129 return error;
8130}
8131
8132/**
8133 * _scsih_exit - exit point for this driver (when it is a module).
8134 *
8135 * Returns 0 success, anything else error.
8136 */
8137static void __exit
8138_scsih_exit(void)
8139{
8140 pr_info("mpt3sas version %s unloading\n",
8141 MPT3SAS_DRIVER_VERSION);
8142
8143 mpt3sas_ctl_exit();
8144
8145 pci_unregister_driver(&scsih_driver);
8146
8147
8148 mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
8149 mpt3sas_base_release_callback_handler(tm_cb_idx);
8150 mpt3sas_base_release_callback_handler(base_cb_idx);
8151 mpt3sas_base_release_callback_handler(port_enable_cb_idx);
8152 mpt3sas_base_release_callback_handler(transport_cb_idx);
8153 mpt3sas_base_release_callback_handler(scsih_cb_idx);
8154 mpt3sas_base_release_callback_handler(config_cb_idx);
8155 mpt3sas_base_release_callback_handler(ctl_cb_idx);
8156
8157 mpt3sas_base_release_callback_handler(tm_tr_cb_idx);
8158 mpt3sas_base_release_callback_handler(tm_tr_volume_cb_idx);
8159 mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx);
8160
8161/* raid transport support */
8162 raid_class_release(mpt3sas_raid_template);
8163 sas_release_transport(mpt3sas_transport_template);
8164}
8165
8166module_init(_scsih_init);
8167module_exit(_scsih_exit);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
new file mode 100644
index 000000000000..87ca2b7287c3
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -0,0 +1,2128 @@
1/*
2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt3sas/mpt3sas_transport.c
5 * Copyright (C) 2012 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 "mpt3sas_base.h"
61
62/**
63 * _transport_sas_node_find_by_sas_address - sas node search
64 * @ioc: per adapter object
65 * @sas_address: sas address of expander or sas host
66 * Context: Calling function should acquire ioc->sas_node_lock.
67 *
68 * Search for either hba phys or expander device based on handle, then returns
69 * the sas_node object.
70 */
71static struct _sas_node *
72_transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
73 u64 sas_address)
74{
75 if (ioc->sas_hba.sas_address == sas_address)
76 return &ioc->sas_hba;
77 else
78 return mpt3sas_scsih_expander_find_by_sas_address(ioc,
79 sas_address);
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 MPI25_SAS_NEG_LINK_RATE_12_0:
104 rc = SAS_LINK_RATE_12_0_GBPS;
105 break;
106 case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
107 rc = SAS_PHY_DISABLED;
108 break;
109 case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
110 rc = SAS_LINK_RATE_FAILED;
111 break;
112 case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
113 rc = SAS_SATA_PORT_SELECTOR;
114 break;
115 case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
116 rc = SAS_PHY_RESET_IN_PROGRESS;
117 break;
118
119 default:
120 case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
121 case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
122 rc = SAS_LINK_RATE_UNKNOWN;
123 break;
124 }
125 return rc;
126}
127
128/**
129 * _transport_set_identify - set identify for phys and end devices
130 * @ioc: per adapter object
131 * @handle: device handle
132 * @identify: sas identify info
133 *
134 * Populates sas identify info.
135 *
136 * Returns 0 for success, non-zero for failure.
137 */
138static int
139_transport_set_identify(struct MPT3SAS_ADAPTER *ioc, u16 handle,
140 struct sas_identify *identify)
141{
142 Mpi2SasDevicePage0_t sas_device_pg0;
143 Mpi2ConfigReply_t mpi_reply;
144 u32 device_info;
145 u32 ioc_status;
146
147 if (ioc->shost_recovery || ioc->pci_error_recovery) {
148 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
149 __func__, ioc->name);
150 return -EFAULT;
151 }
152
153 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
154 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
155 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
156 ioc->name, __FILE__, __LINE__, __func__);
157 return -ENXIO;
158 }
159
160 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
161 MPI2_IOCSTATUS_MASK;
162 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
163 pr_err(MPT3SAS_FMT
164 "handle(0x%04x), ioc_status(0x%04x)\nfailure at %s:%d/%s()!\n",
165 ioc->name, handle, ioc_status,
166 __FILE__, __LINE__, __func__);
167 return -EIO;
168 }
169
170 memset(identify, 0, sizeof(struct sas_identify));
171 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
172
173 /* sas_address */
174 identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
175
176 /* phy number of the parent device this device is linked to */
177 identify->phy_identifier = sas_device_pg0.PhyNum;
178
179 /* device_type */
180 switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
181 case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
182 identify->device_type = SAS_PHY_UNUSED;
183 break;
184 case MPI2_SAS_DEVICE_INFO_END_DEVICE:
185 identify->device_type = SAS_END_DEVICE;
186 break;
187 case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
188 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
189 break;
190 case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
191 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
192 break;
193 }
194
195 /* initiator_port_protocols */
196 if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
197 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
198 if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
199 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
200 if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
201 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
202 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
203 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
204
205 /* target_port_protocols */
206 if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
207 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
208 if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
209 identify->target_port_protocols |= SAS_PROTOCOL_STP;
210 if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
211 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
212 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
213 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
214
215 return 0;
216}
217
218/**
219 * mpt3sas_transport_done - internal transport layer callback handler.
220 * @ioc: per adapter object
221 * @smid: system request message index
222 * @msix_index: MSIX table index supplied by the OS
223 * @reply: reply message frame(lower 32bit addr)
224 *
225 * Callback handler when sending internal generated transport cmds.
226 * The callback index passed is `ioc->transport_cb_idx`
227 *
228 * Return 1 meaning mf should be freed from _base_interrupt
229 * 0 means the mf is freed from this function.
230 */
231u8
232mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
233 u32 reply)
234{
235 MPI2DefaultReply_t *mpi_reply;
236
237 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
238 if (ioc->transport_cmds.status == MPT3_CMD_NOT_USED)
239 return 1;
240 if (ioc->transport_cmds.smid != smid)
241 return 1;
242 ioc->transport_cmds.status |= MPT3_CMD_COMPLETE;
243 if (mpi_reply) {
244 memcpy(ioc->transport_cmds.reply, mpi_reply,
245 mpi_reply->MsgLength*4);
246 ioc->transport_cmds.status |= MPT3_CMD_REPLY_VALID;
247 }
248 ioc->transport_cmds.status &= ~MPT3_CMD_PENDING;
249 complete(&ioc->transport_cmds.done);
250 return 1;
251}
252
253/* report manufacture request structure */
254struct rep_manu_request {
255 u8 smp_frame_type;
256 u8 function;
257 u8 reserved;
258 u8 request_length;
259};
260
261/* report manufacture reply structure */
262struct rep_manu_reply {
263 u8 smp_frame_type; /* 0x41 */
264 u8 function; /* 0x01 */
265 u8 function_result;
266 u8 response_length;
267 u16 expander_change_count;
268 u8 reserved0[2];
269 u8 sas_format;
270 u8 reserved2[3];
271 u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
272 u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
273 u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
274 u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
275 u16 component_id;
276 u8 component_revision_id;
277 u8 reserved3;
278 u8 vendor_specific[8];
279};
280
281/**
282 * transport_expander_report_manufacture - obtain SMP report_manufacture
283 * @ioc: per adapter object
284 * @sas_address: expander sas address
285 * @edev: the sas_expander_device object
286 *
287 * Fills in the sas_expander_device object when SMP port is created.
288 *
289 * Returns 0 for success, non-zero for failure.
290 */
291static int
292_transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
293 u64 sas_address, struct sas_expander_device *edev)
294{
295 Mpi2SmpPassthroughRequest_t *mpi_request;
296 Mpi2SmpPassthroughReply_t *mpi_reply;
297 struct rep_manu_reply *manufacture_reply;
298 struct rep_manu_request *manufacture_request;
299 int rc;
300 u16 smid;
301 u32 ioc_state;
302 unsigned long timeleft;
303 void *psge;
304 u8 issue_reset = 0;
305 void *data_out = NULL;
306 dma_addr_t data_out_dma;
307 dma_addr_t data_in_dma;
308 size_t data_in_sz;
309 size_t data_out_sz;
310 u16 wait_state_count;
311
312 if (ioc->shost_recovery || ioc->pci_error_recovery) {
313 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
314 __func__, ioc->name);
315 return -EFAULT;
316 }
317
318 mutex_lock(&ioc->transport_cmds.mutex);
319
320 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
321 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
322 ioc->name, __func__);
323 rc = -EAGAIN;
324 goto out;
325 }
326 ioc->transport_cmds.status = MPT3_CMD_PENDING;
327
328 wait_state_count = 0;
329 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
330 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
331 if (wait_state_count++ == 10) {
332 pr_err(MPT3SAS_FMT
333 "%s: failed due to ioc not operational\n",
334 ioc->name, __func__);
335 rc = -EFAULT;
336 goto out;
337 }
338 ssleep(1);
339 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
340 pr_info(MPT3SAS_FMT
341 "%s: waiting for operational state(count=%d)\n",
342 ioc->name, __func__, wait_state_count);
343 }
344 if (wait_state_count)
345 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
346 ioc->name, __func__);
347
348 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
349 if (!smid) {
350 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
351 ioc->name, __func__);
352 rc = -EAGAIN;
353 goto out;
354 }
355
356 rc = 0;
357 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
358 ioc->transport_cmds.smid = smid;
359
360 data_out_sz = sizeof(struct rep_manu_request);
361 data_in_sz = sizeof(struct rep_manu_reply);
362 data_out = pci_alloc_consistent(ioc->pdev, data_out_sz + data_in_sz,
363 &data_out_dma);
364
365 if (!data_out) {
366 pr_err("failure at %s:%d/%s()!\n", __FILE__,
367 __LINE__, __func__);
368 rc = -ENOMEM;
369 mpt3sas_base_free_smid(ioc, smid);
370 goto out;
371 }
372
373 data_in_dma = data_out_dma + sizeof(struct rep_manu_request);
374
375 manufacture_request = data_out;
376 manufacture_request->smp_frame_type = 0x40;
377 manufacture_request->function = 1;
378 manufacture_request->reserved = 0;
379 manufacture_request->request_length = 0;
380
381 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
382 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
383 mpi_request->PhysicalPort = 0xFF;
384 mpi_request->SASAddress = cpu_to_le64(sas_address);
385 mpi_request->RequestDataLength = cpu_to_le16(data_out_sz);
386 psge = &mpi_request->SGL;
387
388 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
389 data_in_sz);
390
391 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
392 "report_manufacture - send to sas_addr(0x%016llx)\n",
393 ioc->name, (unsigned long long)sas_address));
394 init_completion(&ioc->transport_cmds.done);
395 mpt3sas_base_put_smid_default(ioc, smid);
396 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
397 10*HZ);
398
399 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
400 pr_err(MPT3SAS_FMT "%s: timeout\n",
401 ioc->name, __func__);
402 _debug_dump_mf(mpi_request,
403 sizeof(Mpi2SmpPassthroughRequest_t)/4);
404 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
405 issue_reset = 1;
406 goto issue_host_reset;
407 }
408
409 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
410 "report_manufacture - complete\n", ioc->name));
411
412 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
413 u8 *tmp;
414
415 mpi_reply = ioc->transport_cmds.reply;
416
417 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
418 "report_manufacture - reply data transfer size(%d)\n",
419 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
420
421 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
422 sizeof(struct rep_manu_reply))
423 goto out;
424
425 manufacture_reply = data_out + sizeof(struct rep_manu_request);
426 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
427 SAS_EXPANDER_VENDOR_ID_LEN);
428 strncpy(edev->product_id, manufacture_reply->product_id,
429 SAS_EXPANDER_PRODUCT_ID_LEN);
430 strncpy(edev->product_rev, manufacture_reply->product_rev,
431 SAS_EXPANDER_PRODUCT_REV_LEN);
432 edev->level = manufacture_reply->sas_format & 1;
433 if (edev->level) {
434 strncpy(edev->component_vendor_id,
435 manufacture_reply->component_vendor_id,
436 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
437 tmp = (u8 *)&manufacture_reply->component_id;
438 edev->component_id = tmp[0] << 8 | tmp[1];
439 edev->component_revision_id =
440 manufacture_reply->component_revision_id;
441 }
442 } else
443 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
444 "report_manufacture - no reply\n", ioc->name));
445
446 issue_host_reset:
447 if (issue_reset)
448 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
449 FORCE_BIG_HAMMER);
450 out:
451 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
452 if (data_out)
453 pci_free_consistent(ioc->pdev, data_out_sz + data_in_sz,
454 data_out, data_out_dma);
455
456 mutex_unlock(&ioc->transport_cmds.mutex);
457 return rc;
458}
459
460
461/**
462 * _transport_delete_port - helper function to removing a port
463 * @ioc: per adapter object
464 * @mpt3sas_port: mpt3sas per port object
465 *
466 * Returns nothing.
467 */
468static void
469_transport_delete_port(struct MPT3SAS_ADAPTER *ioc,
470 struct _sas_port *mpt3sas_port)
471{
472 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
473 enum sas_device_type device_type =
474 mpt3sas_port->remote_identify.device_type;
475
476 dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
477 "remove: sas_addr(0x%016llx)\n",
478 (unsigned long long) sas_address);
479
480 ioc->logging_level |= MPT_DEBUG_TRANSPORT;
481 if (device_type == SAS_END_DEVICE)
482 mpt3sas_device_remove_by_sas_address(ioc, sas_address);
483 else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
484 device_type == SAS_FANOUT_EXPANDER_DEVICE)
485 mpt3sas_expander_remove(ioc, sas_address);
486 ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
487}
488
489/**
490 * _transport_delete_phy - helper function to removing single phy from port
491 * @ioc: per adapter object
492 * @mpt3sas_port: mpt3sas per port object
493 * @mpt3sas_phy: mpt3sas per phy object
494 *
495 * Returns nothing.
496 */
497static void
498_transport_delete_phy(struct MPT3SAS_ADAPTER *ioc,
499 struct _sas_port *mpt3sas_port, struct _sas_phy *mpt3sas_phy)
500{
501 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
502
503 dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
504 "remove: sas_addr(0x%016llx), phy(%d)\n",
505 (unsigned long long) sas_address, mpt3sas_phy->phy_id);
506
507 list_del(&mpt3sas_phy->port_siblings);
508 mpt3sas_port->num_phys--;
509 sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
510 mpt3sas_phy->phy_belongs_to_port = 0;
511}
512
513/**
514 * _transport_add_phy - helper function to adding single phy to port
515 * @ioc: per adapter object
516 * @mpt3sas_port: mpt3sas per port object
517 * @mpt3sas_phy: mpt3sas per phy object
518 *
519 * Returns nothing.
520 */
521static void
522_transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port,
523 struct _sas_phy *mpt3sas_phy)
524{
525 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
526
527 dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
528 "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
529 sas_address, mpt3sas_phy->phy_id);
530
531 list_add_tail(&mpt3sas_phy->port_siblings, &mpt3sas_port->phy_list);
532 mpt3sas_port->num_phys++;
533 sas_port_add_phy(mpt3sas_port->port, mpt3sas_phy->phy);
534 mpt3sas_phy->phy_belongs_to_port = 1;
535}
536
537/**
538 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
539 * @ioc: per adapter object
540 * @sas_node: sas node object (either expander or sas host)
541 * @mpt3sas_phy: mpt3sas per phy object
542 * @sas_address: sas address of device/expander were phy needs to be added to
543 *
544 * Returns nothing.
545 */
546static void
547_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
548 struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy,
549 u64 sas_address)
550{
551 struct _sas_port *mpt3sas_port;
552 struct _sas_phy *phy_srch;
553
554 if (mpt3sas_phy->phy_belongs_to_port == 1)
555 return;
556
557 list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list,
558 port_list) {
559 if (mpt3sas_port->remote_identify.sas_address !=
560 sas_address)
561 continue;
562 list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
563 port_siblings) {
564 if (phy_srch == mpt3sas_phy)
565 return;
566 }
567 _transport_add_phy(ioc, mpt3sas_port, mpt3sas_phy);
568 return;
569 }
570
571}
572
573/**
574 * _transport_del_phy_from_an_existing_port - delete phy from existing port
575 * @ioc: per adapter object
576 * @sas_node: sas node object (either expander or sas host)
577 * @mpt3sas_phy: mpt3sas per phy object
578 *
579 * Returns nothing.
580 */
581static void
582_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
583 struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy)
584{
585 struct _sas_port *mpt3sas_port, *next;
586 struct _sas_phy *phy_srch;
587
588 if (mpt3sas_phy->phy_belongs_to_port == 0)
589 return;
590
591 list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
592 port_list) {
593 list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
594 port_siblings) {
595 if (phy_srch != mpt3sas_phy)
596 continue;
597
598 if (mpt3sas_port->num_phys == 1)
599 _transport_delete_port(ioc, mpt3sas_port);
600 else
601 _transport_delete_phy(ioc, mpt3sas_port,
602 mpt3sas_phy);
603 return;
604 }
605 }
606}
607
608/**
609 * _transport_sanity_check - sanity check when adding a new port
610 * @ioc: per adapter object
611 * @sas_node: sas node object (either expander or sas host)
612 * @sas_address: sas address of device being added
613 *
614 * See the explanation above from _transport_delete_duplicate_port
615 */
616static void
617_transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
618 u64 sas_address)
619{
620 int i;
621
622 for (i = 0; i < sas_node->num_phys; i++) {
623 if (sas_node->phy[i].remote_identify.sas_address != sas_address)
624 continue;
625 if (sas_node->phy[i].phy_belongs_to_port == 1)
626 _transport_del_phy_from_an_existing_port(ioc, sas_node,
627 &sas_node->phy[i]);
628 }
629}
630
631/**
632 * mpt3sas_transport_port_add - insert port to the list
633 * @ioc: per adapter object
634 * @handle: handle of attached device
635 * @sas_address: sas address of parent expander or sas host
636 * Context: This function will acquire ioc->sas_node_lock.
637 *
638 * Adding new port object to the sas_node->sas_port_list.
639 *
640 * Returns mpt3sas_port.
641 */
642struct _sas_port *
643mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
644 u64 sas_address)
645{
646 struct _sas_phy *mpt3sas_phy, *next;
647 struct _sas_port *mpt3sas_port;
648 unsigned long flags;
649 struct _sas_node *sas_node;
650 struct sas_rphy *rphy;
651 int i;
652 struct sas_port *port;
653
654 mpt3sas_port = kzalloc(sizeof(struct _sas_port),
655 GFP_KERNEL);
656 if (!mpt3sas_port) {
657 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
658 ioc->name, __FILE__, __LINE__, __func__);
659 return NULL;
660 }
661
662 INIT_LIST_HEAD(&mpt3sas_port->port_list);
663 INIT_LIST_HEAD(&mpt3sas_port->phy_list);
664 spin_lock_irqsave(&ioc->sas_node_lock, flags);
665 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
666 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
667
668 if (!sas_node) {
669 pr_err(MPT3SAS_FMT
670 "%s: Could not find parent sas_address(0x%016llx)!\n",
671 ioc->name, __func__, (unsigned long long)sas_address);
672 goto out_fail;
673 }
674
675 if ((_transport_set_identify(ioc, handle,
676 &mpt3sas_port->remote_identify))) {
677 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
678 ioc->name, __FILE__, __LINE__, __func__);
679 goto out_fail;
680 }
681
682 if (mpt3sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
683 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
684 ioc->name, __FILE__, __LINE__, __func__);
685 goto out_fail;
686 }
687
688 _transport_sanity_check(ioc, sas_node,
689 mpt3sas_port->remote_identify.sas_address);
690
691 for (i = 0; i < sas_node->num_phys; i++) {
692 if (sas_node->phy[i].remote_identify.sas_address !=
693 mpt3sas_port->remote_identify.sas_address)
694 continue;
695 list_add_tail(&sas_node->phy[i].port_siblings,
696 &mpt3sas_port->phy_list);
697 mpt3sas_port->num_phys++;
698 }
699
700 if (!mpt3sas_port->num_phys) {
701 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
702 ioc->name, __FILE__, __LINE__, __func__);
703 goto out_fail;
704 }
705
706 port = sas_port_alloc_num(sas_node->parent_dev);
707 if ((sas_port_add(port))) {
708 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
709 ioc->name, __FILE__, __LINE__, __func__);
710 goto out_fail;
711 }
712
713 list_for_each_entry(mpt3sas_phy, &mpt3sas_port->phy_list,
714 port_siblings) {
715 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
716 dev_printk(KERN_INFO, &port->dev,
717 "add: handle(0x%04x), sas_addr(0x%016llx), phy(%d)\n",
718 handle, (unsigned long long)
719 mpt3sas_port->remote_identify.sas_address,
720 mpt3sas_phy->phy_id);
721 sas_port_add_phy(port, mpt3sas_phy->phy);
722 mpt3sas_phy->phy_belongs_to_port = 1;
723 }
724
725 mpt3sas_port->port = port;
726 if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE)
727 rphy = sas_end_device_alloc(port);
728 else
729 rphy = sas_expander_alloc(port,
730 mpt3sas_port->remote_identify.device_type);
731
732 rphy->identify = mpt3sas_port->remote_identify;
733 if ((sas_rphy_add(rphy))) {
734 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
735 ioc->name, __FILE__, __LINE__, __func__);
736 }
737 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
738 dev_printk(KERN_INFO, &rphy->dev,
739 "add: handle(0x%04x), sas_addr(0x%016llx)\n",
740 handle, (unsigned long long)
741 mpt3sas_port->remote_identify.sas_address);
742 mpt3sas_port->rphy = rphy;
743 spin_lock_irqsave(&ioc->sas_node_lock, flags);
744 list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list);
745 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
746
747 /* fill in report manufacture */
748 if (mpt3sas_port->remote_identify.device_type ==
749 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
750 mpt3sas_port->remote_identify.device_type ==
751 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
752 _transport_expander_report_manufacture(ioc,
753 mpt3sas_port->remote_identify.sas_address,
754 rphy_to_expander_device(rphy));
755 return mpt3sas_port;
756
757 out_fail:
758 list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list,
759 port_siblings)
760 list_del(&mpt3sas_phy->port_siblings);
761 kfree(mpt3sas_port);
762 return NULL;
763}
764
765/**
766 * mpt3sas_transport_port_remove - remove port from the list
767 * @ioc: per adapter object
768 * @sas_address: sas address of attached device
769 * @sas_address_parent: sas address of parent expander or sas host
770 * Context: This function will acquire ioc->sas_node_lock.
771 *
772 * Removing object and freeing associated memory from the
773 * ioc->sas_port_list.
774 *
775 * Return nothing.
776 */
777void
778mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
779 u64 sas_address_parent)
780{
781 int i;
782 unsigned long flags;
783 struct _sas_port *mpt3sas_port, *next;
784 struct _sas_node *sas_node;
785 u8 found = 0;
786 struct _sas_phy *mpt3sas_phy, *next_phy;
787
788 spin_lock_irqsave(&ioc->sas_node_lock, flags);
789 sas_node = _transport_sas_node_find_by_sas_address(ioc,
790 sas_address_parent);
791 if (!sas_node) {
792 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
793 return;
794 }
795 list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
796 port_list) {
797 if (mpt3sas_port->remote_identify.sas_address != sas_address)
798 continue;
799 found = 1;
800 list_del(&mpt3sas_port->port_list);
801 goto out;
802 }
803 out:
804 if (!found) {
805 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
806 return;
807 }
808
809 for (i = 0; i < sas_node->num_phys; i++) {
810 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
811 memset(&sas_node->phy[i].remote_identify, 0 ,
812 sizeof(struct sas_identify));
813 }
814
815 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
816
817 list_for_each_entry_safe(mpt3sas_phy, next_phy,
818 &mpt3sas_port->phy_list, port_siblings) {
819 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
820 dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
821 "remove: sas_addr(0x%016llx), phy(%d)\n",
822 (unsigned long long)
823 mpt3sas_port->remote_identify.sas_address,
824 mpt3sas_phy->phy_id);
825 mpt3sas_phy->phy_belongs_to_port = 0;
826 sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
827 list_del(&mpt3sas_phy->port_siblings);
828 }
829 sas_port_delete(mpt3sas_port->port);
830 kfree(mpt3sas_port);
831}
832
833/**
834 * mpt3sas_transport_add_host_phy - report sas_host phy to transport
835 * @ioc: per adapter object
836 * @mpt3sas_phy: mpt3sas per phy object
837 * @phy_pg0: sas phy page 0
838 * @parent_dev: parent device class object
839 *
840 * Returns 0 for success, non-zero for failure.
841 */
842int
843mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
844 *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
845{
846 struct sas_phy *phy;
847 int phy_index = mpt3sas_phy->phy_id;
848
849
850 INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
851 phy = sas_phy_alloc(parent_dev, phy_index);
852 if (!phy) {
853 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
854 ioc->name, __FILE__, __LINE__, __func__);
855 return -1;
856 }
857 if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
858 &mpt3sas_phy->identify))) {
859 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
860 ioc->name, __FILE__, __LINE__, __func__);
861 sas_phy_free(phy);
862 return -1;
863 }
864 phy->identify = mpt3sas_phy->identify;
865 mpt3sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
866 if (mpt3sas_phy->attached_handle)
867 _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
868 &mpt3sas_phy->remote_identify);
869 phy->identify.phy_identifier = mpt3sas_phy->phy_id;
870 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
871 phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
872 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
873 phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
874 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
875 phy_pg0.HwLinkRate >> 4);
876 phy->minimum_linkrate = _transport_convert_phy_link_rate(
877 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
878 phy->maximum_linkrate = _transport_convert_phy_link_rate(
879 phy_pg0.ProgrammedLinkRate >> 4);
880
881 if ((sas_phy_add(phy))) {
882 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
883 ioc->name, __FILE__, __LINE__, __func__);
884 sas_phy_free(phy);
885 return -1;
886 }
887 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
888 dev_printk(KERN_INFO, &phy->dev,
889 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
890 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
891 mpt3sas_phy->handle, (unsigned long long)
892 mpt3sas_phy->identify.sas_address,
893 mpt3sas_phy->attached_handle,
894 (unsigned long long)
895 mpt3sas_phy->remote_identify.sas_address);
896 mpt3sas_phy->phy = phy;
897 return 0;
898}
899
900
901/**
902 * mpt3sas_transport_add_expander_phy - report expander phy to transport
903 * @ioc: per adapter object
904 * @mpt3sas_phy: mpt3sas per phy object
905 * @expander_pg1: expander page 1
906 * @parent_dev: parent device class object
907 *
908 * Returns 0 for success, non-zero for failure.
909 */
910int
911mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
912 *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
913 struct device *parent_dev)
914{
915 struct sas_phy *phy;
916 int phy_index = mpt3sas_phy->phy_id;
917
918 INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
919 phy = sas_phy_alloc(parent_dev, phy_index);
920 if (!phy) {
921 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
922 ioc->name, __FILE__, __LINE__, __func__);
923 return -1;
924 }
925 if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
926 &mpt3sas_phy->identify))) {
927 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
928 ioc->name, __FILE__, __LINE__, __func__);
929 sas_phy_free(phy);
930 return -1;
931 }
932 phy->identify = mpt3sas_phy->identify;
933 mpt3sas_phy->attached_handle =
934 le16_to_cpu(expander_pg1.AttachedDevHandle);
935 if (mpt3sas_phy->attached_handle)
936 _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
937 &mpt3sas_phy->remote_identify);
938 phy->identify.phy_identifier = mpt3sas_phy->phy_id;
939 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
940 expander_pg1.NegotiatedLinkRate &
941 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
942 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
943 expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
944 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
945 expander_pg1.HwLinkRate >> 4);
946 phy->minimum_linkrate = _transport_convert_phy_link_rate(
947 expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
948 phy->maximum_linkrate = _transport_convert_phy_link_rate(
949 expander_pg1.ProgrammedLinkRate >> 4);
950
951 if ((sas_phy_add(phy))) {
952 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
953 ioc->name, __FILE__, __LINE__, __func__);
954 sas_phy_free(phy);
955 return -1;
956 }
957 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
958 dev_printk(KERN_INFO, &phy->dev,
959 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
960 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
961 mpt3sas_phy->handle, (unsigned long long)
962 mpt3sas_phy->identify.sas_address,
963 mpt3sas_phy->attached_handle,
964 (unsigned long long)
965 mpt3sas_phy->remote_identify.sas_address);
966 mpt3sas_phy->phy = phy;
967 return 0;
968}
969
970/**
971 * mpt3sas_transport_update_links - refreshing phy link changes
972 * @ioc: per adapter object
973 * @sas_address: sas address of parent expander or sas host
974 * @handle: attached device handle
975 * @phy_numberv: phy number
976 * @link_rate: new link rate
977 *
978 * Returns nothing.
979 */
980void
981mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
982 u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
983{
984 unsigned long flags;
985 struct _sas_node *sas_node;
986 struct _sas_phy *mpt3sas_phy;
987
988 if (ioc->shost_recovery || ioc->pci_error_recovery)
989 return;
990
991 spin_lock_irqsave(&ioc->sas_node_lock, flags);
992 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
993 if (!sas_node) {
994 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
995 return;
996 }
997
998 mpt3sas_phy = &sas_node->phy[phy_number];
999 mpt3sas_phy->attached_handle = handle;
1000 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1001 if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
1002 _transport_set_identify(ioc, handle,
1003 &mpt3sas_phy->remote_identify);
1004 _transport_add_phy_to_an_existing_port(ioc, sas_node,
1005 mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address);
1006 } else
1007 memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct
1008 sas_identify));
1009
1010 if (mpt3sas_phy->phy)
1011 mpt3sas_phy->phy->negotiated_linkrate =
1012 _transport_convert_phy_link_rate(link_rate);
1013
1014 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1015 dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
1016 "refresh: parent sas_addr(0x%016llx),\n"
1017 "\tlink_rate(0x%02x), phy(%d)\n"
1018 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1019 (unsigned long long)sas_address,
1020 link_rate, phy_number, handle, (unsigned long long)
1021 mpt3sas_phy->remote_identify.sas_address);
1022}
1023
1024static inline void *
1025phy_to_ioc(struct sas_phy *phy)
1026{
1027 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1028 return shost_priv(shost);
1029}
1030
1031static inline void *
1032rphy_to_ioc(struct sas_rphy *rphy)
1033{
1034 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1035 return shost_priv(shost);
1036}
1037
1038/* report phy error log structure */
1039struct phy_error_log_request {
1040 u8 smp_frame_type; /* 0x40 */
1041 u8 function; /* 0x11 */
1042 u8 allocated_response_length;
1043 u8 request_length; /* 02 */
1044 u8 reserved_1[5];
1045 u8 phy_identifier;
1046 u8 reserved_2[2];
1047};
1048
1049/* report phy error log reply structure */
1050struct phy_error_log_reply {
1051 u8 smp_frame_type; /* 0x41 */
1052 u8 function; /* 0x11 */
1053 u8 function_result;
1054 u8 response_length;
1055 __be16 expander_change_count;
1056 u8 reserved_1[3];
1057 u8 phy_identifier;
1058 u8 reserved_2[2];
1059 __be32 invalid_dword;
1060 __be32 running_disparity_error;
1061 __be32 loss_of_dword_sync;
1062 __be32 phy_reset_problem;
1063};
1064
1065/**
1066 * _transport_get_expander_phy_error_log - return expander counters
1067 * @ioc: per adapter object
1068 * @phy: The sas phy object
1069 *
1070 * Returns 0 for success, non-zero for failure.
1071 *
1072 */
1073static int
1074_transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
1075 struct sas_phy *phy)
1076{
1077 Mpi2SmpPassthroughRequest_t *mpi_request;
1078 Mpi2SmpPassthroughReply_t *mpi_reply;
1079 struct phy_error_log_request *phy_error_log_request;
1080 struct phy_error_log_reply *phy_error_log_reply;
1081 int rc;
1082 u16 smid;
1083 u32 ioc_state;
1084 unsigned long timeleft;
1085 void *psge;
1086 u8 issue_reset = 0;
1087 void *data_out = NULL;
1088 dma_addr_t data_out_dma;
1089 u32 sz;
1090 u16 wait_state_count;
1091
1092 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1093 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1094 __func__, ioc->name);
1095 return -EFAULT;
1096 }
1097
1098 mutex_lock(&ioc->transport_cmds.mutex);
1099
1100 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1101 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
1102 ioc->name, __func__);
1103 rc = -EAGAIN;
1104 goto out;
1105 }
1106 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1107
1108 wait_state_count = 0;
1109 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1110 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1111 if (wait_state_count++ == 10) {
1112 pr_err(MPT3SAS_FMT
1113 "%s: failed due to ioc not operational\n",
1114 ioc->name, __func__);
1115 rc = -EFAULT;
1116 goto out;
1117 }
1118 ssleep(1);
1119 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1120 pr_info(MPT3SAS_FMT
1121 "%s: waiting for operational state(count=%d)\n",
1122 ioc->name, __func__, wait_state_count);
1123 }
1124 if (wait_state_count)
1125 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1126 ioc->name, __func__);
1127
1128 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1129 if (!smid) {
1130 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1131 ioc->name, __func__);
1132 rc = -EAGAIN;
1133 goto out;
1134 }
1135
1136 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1137 ioc->transport_cmds.smid = smid;
1138
1139 sz = sizeof(struct phy_error_log_request) +
1140 sizeof(struct phy_error_log_reply);
1141 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1142 if (!data_out) {
1143 pr_err("failure at %s:%d/%s()!\n", __FILE__,
1144 __LINE__, __func__);
1145 rc = -ENOMEM;
1146 mpt3sas_base_free_smid(ioc, smid);
1147 goto out;
1148 }
1149
1150 rc = -EINVAL;
1151 memset(data_out, 0, sz);
1152 phy_error_log_request = data_out;
1153 phy_error_log_request->smp_frame_type = 0x40;
1154 phy_error_log_request->function = 0x11;
1155 phy_error_log_request->request_length = 2;
1156 phy_error_log_request->allocated_response_length = 0;
1157 phy_error_log_request->phy_identifier = phy->number;
1158
1159 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1160 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1161 mpi_request->PhysicalPort = 0xFF;
1162 mpi_request->VF_ID = 0; /* TODO */
1163 mpi_request->VP_ID = 0;
1164 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1165 mpi_request->RequestDataLength =
1166 cpu_to_le16(sizeof(struct phy_error_log_request));
1167 psge = &mpi_request->SGL;
1168
1169 ioc->build_sg(ioc, psge, data_out_dma,
1170 sizeof(struct phy_error_log_request),
1171 data_out_dma + sizeof(struct phy_error_log_request),
1172 sizeof(struct phy_error_log_reply));
1173
1174 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1175 "phy_error_log - send to sas_addr(0x%016llx), phy(%d)\n",
1176 ioc->name, (unsigned long long)phy->identify.sas_address,
1177 phy->number));
1178 init_completion(&ioc->transport_cmds.done);
1179 mpt3sas_base_put_smid_default(ioc, smid);
1180 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1181 10*HZ);
1182
1183 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1184 pr_err(MPT3SAS_FMT "%s: timeout\n",
1185 ioc->name, __func__);
1186 _debug_dump_mf(mpi_request,
1187 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1188 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1189 issue_reset = 1;
1190 goto issue_host_reset;
1191 }
1192
1193 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1194 "phy_error_log - complete\n", ioc->name));
1195
1196 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1197
1198 mpi_reply = ioc->transport_cmds.reply;
1199
1200 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1201 "phy_error_log - reply data transfer size(%d)\n",
1202 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1203
1204 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1205 sizeof(struct phy_error_log_reply))
1206 goto out;
1207
1208 phy_error_log_reply = data_out +
1209 sizeof(struct phy_error_log_request);
1210
1211 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1212 "phy_error_log - function_result(%d)\n",
1213 ioc->name, phy_error_log_reply->function_result));
1214
1215 phy->invalid_dword_count =
1216 be32_to_cpu(phy_error_log_reply->invalid_dword);
1217 phy->running_disparity_error_count =
1218 be32_to_cpu(phy_error_log_reply->running_disparity_error);
1219 phy->loss_of_dword_sync_count =
1220 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1221 phy->phy_reset_problem_count =
1222 be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1223 rc = 0;
1224 } else
1225 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1226 "phy_error_log - no reply\n", ioc->name));
1227
1228 issue_host_reset:
1229 if (issue_reset)
1230 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1231 FORCE_BIG_HAMMER);
1232 out:
1233 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1234 if (data_out)
1235 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1236
1237 mutex_unlock(&ioc->transport_cmds.mutex);
1238 return rc;
1239}
1240
1241/**
1242 * _transport_get_linkerrors - return phy counters for both hba and expanders
1243 * @phy: The sas phy object
1244 *
1245 * Returns 0 for success, non-zero for failure.
1246 *
1247 */
1248static int
1249_transport_get_linkerrors(struct sas_phy *phy)
1250{
1251 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1252 unsigned long flags;
1253 Mpi2ConfigReply_t mpi_reply;
1254 Mpi2SasPhyPage1_t phy_pg1;
1255
1256 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1257 if (_transport_sas_node_find_by_sas_address(ioc,
1258 phy->identify.sas_address) == NULL) {
1259 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1260 return -EINVAL;
1261 }
1262 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1263
1264 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1265 return _transport_get_expander_phy_error_log(ioc, phy);
1266
1267 /* get hba phy error logs */
1268 if ((mpt3sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1269 phy->number))) {
1270 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1271 ioc->name, __FILE__, __LINE__, __func__);
1272 return -ENXIO;
1273 }
1274
1275 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1276 pr_info(MPT3SAS_FMT
1277 "phy(%d), ioc_status (0x%04x), loginfo(0x%08x)\n",
1278 ioc->name, phy->number,
1279 le16_to_cpu(mpi_reply.IOCStatus),
1280 le32_to_cpu(mpi_reply.IOCLogInfo));
1281
1282 phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1283 phy->running_disparity_error_count =
1284 le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1285 phy->loss_of_dword_sync_count =
1286 le32_to_cpu(phy_pg1.LossDwordSynchCount);
1287 phy->phy_reset_problem_count =
1288 le32_to_cpu(phy_pg1.PhyResetProblemCount);
1289 return 0;
1290}
1291
1292/**
1293 * _transport_get_enclosure_identifier -
1294 * @phy: The sas phy object
1295 *
1296 * Obtain the enclosure logical id for an expander.
1297 * Returns 0 for success, non-zero for failure.
1298 */
1299static int
1300_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1301{
1302 struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1303 struct _sas_device *sas_device;
1304 unsigned long flags;
1305 int rc;
1306
1307 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1308 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1309 rphy->identify.sas_address);
1310 if (sas_device) {
1311 *identifier = sas_device->enclosure_logical_id;
1312 rc = 0;
1313 } else {
1314 *identifier = 0;
1315 rc = -ENXIO;
1316 }
1317 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1318 return rc;
1319}
1320
1321/**
1322 * _transport_get_bay_identifier -
1323 * @phy: The sas phy object
1324 *
1325 * Returns the slot id for a device that resides inside an enclosure.
1326 */
1327static int
1328_transport_get_bay_identifier(struct sas_rphy *rphy)
1329{
1330 struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1331 struct _sas_device *sas_device;
1332 unsigned long flags;
1333 int rc;
1334
1335 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1336 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1337 rphy->identify.sas_address);
1338 if (sas_device)
1339 rc = sas_device->slot;
1340 else
1341 rc = -ENXIO;
1342 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1343 return rc;
1344}
1345
1346/* phy control request structure */
1347struct phy_control_request {
1348 u8 smp_frame_type; /* 0x40 */
1349 u8 function; /* 0x91 */
1350 u8 allocated_response_length;
1351 u8 request_length; /* 0x09 */
1352 u16 expander_change_count;
1353 u8 reserved_1[3];
1354 u8 phy_identifier;
1355 u8 phy_operation;
1356 u8 reserved_2[13];
1357 u64 attached_device_name;
1358 u8 programmed_min_physical_link_rate;
1359 u8 programmed_max_physical_link_rate;
1360 u8 reserved_3[6];
1361};
1362
1363/* phy control reply structure */
1364struct phy_control_reply {
1365 u8 smp_frame_type; /* 0x41 */
1366 u8 function; /* 0x11 */
1367 u8 function_result;
1368 u8 response_length;
1369};
1370
1371#define SMP_PHY_CONTROL_LINK_RESET (0x01)
1372#define SMP_PHY_CONTROL_HARD_RESET (0x02)
1373#define SMP_PHY_CONTROL_DISABLE (0x03)
1374
1375/**
1376 * _transport_expander_phy_control - expander phy control
1377 * @ioc: per adapter object
1378 * @phy: The sas phy object
1379 *
1380 * Returns 0 for success, non-zero for failure.
1381 *
1382 */
1383static int
1384_transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
1385 struct sas_phy *phy, u8 phy_operation)
1386{
1387 Mpi2SmpPassthroughRequest_t *mpi_request;
1388 Mpi2SmpPassthroughReply_t *mpi_reply;
1389 struct phy_control_request *phy_control_request;
1390 struct phy_control_reply *phy_control_reply;
1391 int rc;
1392 u16 smid;
1393 u32 ioc_state;
1394 unsigned long timeleft;
1395 void *psge;
1396 u32 sgl_flags;
1397 u8 issue_reset = 0;
1398 void *data_out = NULL;
1399 dma_addr_t data_out_dma;
1400 u32 sz;
1401 u16 wait_state_count;
1402
1403 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1404 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1405 __func__, ioc->name);
1406 return -EFAULT;
1407 }
1408
1409 mutex_lock(&ioc->transport_cmds.mutex);
1410
1411 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1412 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
1413 ioc->name, __func__);
1414 rc = -EAGAIN;
1415 goto out;
1416 }
1417 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1418
1419 wait_state_count = 0;
1420 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1421 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1422 if (wait_state_count++ == 10) {
1423 pr_err(MPT3SAS_FMT
1424 "%s: failed due to ioc not operational\n",
1425 ioc->name, __func__);
1426 rc = -EFAULT;
1427 goto out;
1428 }
1429 ssleep(1);
1430 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1431 pr_info(MPT3SAS_FMT
1432 "%s: waiting for operational state(count=%d)\n",
1433 ioc->name, __func__, wait_state_count);
1434 }
1435 if (wait_state_count)
1436 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1437 ioc->name, __func__);
1438
1439 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1440 if (!smid) {
1441 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1442 ioc->name, __func__);
1443 rc = -EAGAIN;
1444 goto out;
1445 }
1446
1447 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1448 ioc->transport_cmds.smid = smid;
1449
1450 sz = sizeof(struct phy_control_request) +
1451 sizeof(struct phy_control_reply);
1452 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1453 if (!data_out) {
1454 pr_err("failure at %s:%d/%s()!\n", __FILE__,
1455 __LINE__, __func__);
1456 rc = -ENOMEM;
1457 mpt3sas_base_free_smid(ioc, smid);
1458 goto out;
1459 }
1460
1461 rc = -EINVAL;
1462 memset(data_out, 0, sz);
1463 phy_control_request = data_out;
1464 phy_control_request->smp_frame_type = 0x40;
1465 phy_control_request->function = 0x91;
1466 phy_control_request->request_length = 9;
1467 phy_control_request->allocated_response_length = 0;
1468 phy_control_request->phy_identifier = phy->number;
1469 phy_control_request->phy_operation = phy_operation;
1470 phy_control_request->programmed_min_physical_link_rate =
1471 phy->minimum_linkrate << 4;
1472 phy_control_request->programmed_max_physical_link_rate =
1473 phy->maximum_linkrate << 4;
1474
1475 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1476 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1477 mpi_request->PhysicalPort = 0xFF;
1478 mpi_request->VF_ID = 0; /* TODO */
1479 mpi_request->VP_ID = 0;
1480 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1481 mpi_request->RequestDataLength =
1482 cpu_to_le16(sizeof(struct phy_error_log_request));
1483 psge = &mpi_request->SGL;
1484
1485 /* WRITE sgel first */
1486 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1487 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1488 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1489 ioc->base_add_sg_single(psge, sgl_flags |
1490 sizeof(struct phy_control_request), data_out_dma);
1491
1492 /* incr sgel */
1493 psge += ioc->sge_size;
1494
1495 /* READ sgel last */
1496 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1497 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1498 MPI2_SGE_FLAGS_END_OF_LIST);
1499 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1500 ioc->base_add_sg_single(psge, sgl_flags |
1501 sizeof(struct phy_control_reply), data_out_dma +
1502 sizeof(struct phy_control_request));
1503
1504 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1505 "phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n",
1506 ioc->name, (unsigned long long)phy->identify.sas_address,
1507 phy->number, phy_operation));
1508 init_completion(&ioc->transport_cmds.done);
1509 mpt3sas_base_put_smid_default(ioc, smid);
1510 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1511 10*HZ);
1512
1513 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1514 pr_err(MPT3SAS_FMT "%s: timeout\n",
1515 ioc->name, __func__);
1516 _debug_dump_mf(mpi_request,
1517 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1518 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1519 issue_reset = 1;
1520 goto issue_host_reset;
1521 }
1522
1523 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1524 "phy_control - complete\n", ioc->name));
1525
1526 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1527
1528 mpi_reply = ioc->transport_cmds.reply;
1529
1530 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1531 "phy_control - reply data transfer size(%d)\n",
1532 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1533
1534 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1535 sizeof(struct phy_control_reply))
1536 goto out;
1537
1538 phy_control_reply = data_out +
1539 sizeof(struct phy_control_request);
1540
1541 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1542 "phy_control - function_result(%d)\n",
1543 ioc->name, phy_control_reply->function_result));
1544
1545 rc = 0;
1546 } else
1547 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1548 "phy_control - no reply\n", ioc->name));
1549
1550 issue_host_reset:
1551 if (issue_reset)
1552 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1553 FORCE_BIG_HAMMER);
1554 out:
1555 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1556 if (data_out)
1557 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1558
1559 mutex_unlock(&ioc->transport_cmds.mutex);
1560 return rc;
1561}
1562
1563/**
1564 * _transport_phy_reset -
1565 * @phy: The sas phy object
1566 * @hard_reset:
1567 *
1568 * Returns 0 for success, non-zero for failure.
1569 */
1570static int
1571_transport_phy_reset(struct sas_phy *phy, int hard_reset)
1572{
1573 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1574 Mpi2SasIoUnitControlReply_t mpi_reply;
1575 Mpi2SasIoUnitControlRequest_t mpi_request;
1576 unsigned long flags;
1577
1578 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1579 if (_transport_sas_node_find_by_sas_address(ioc,
1580 phy->identify.sas_address) == NULL) {
1581 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1582 return -EINVAL;
1583 }
1584 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1585
1586 /* handle expander phys */
1587 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1588 return _transport_expander_phy_control(ioc, phy,
1589 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1590 SMP_PHY_CONTROL_LINK_RESET);
1591
1592 /* handle hba phys */
1593 memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1594 mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1595 mpi_request.Operation = hard_reset ?
1596 MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1597 mpi_request.PhyNum = phy->number;
1598
1599 if ((mpt3sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1600 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1601 ioc->name, __FILE__, __LINE__, __func__);
1602 return -ENXIO;
1603 }
1604
1605 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1606 pr_info(MPT3SAS_FMT
1607 "phy(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
1608 ioc->name, phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1609 le32_to_cpu(mpi_reply.IOCLogInfo));
1610
1611 return 0;
1612}
1613
1614/**
1615 * _transport_phy_enable - enable/disable phys
1616 * @phy: The sas phy object
1617 * @enable: enable phy when true
1618 *
1619 * Only support sas_host direct attached phys.
1620 * Returns 0 for success, non-zero for failure.
1621 */
1622static int
1623_transport_phy_enable(struct sas_phy *phy, int enable)
1624{
1625 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1626 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1627 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
1628 Mpi2ConfigReply_t mpi_reply;
1629 u16 ioc_status;
1630 u16 sz;
1631 int rc = 0;
1632 unsigned long flags;
1633 int i, discovery_active;
1634
1635 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1636 if (_transport_sas_node_find_by_sas_address(ioc,
1637 phy->identify.sas_address) == NULL) {
1638 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1639 return -EINVAL;
1640 }
1641 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1642
1643 /* handle expander phys */
1644 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1645 return _transport_expander_phy_control(ioc, phy,
1646 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1647 SMP_PHY_CONTROL_DISABLE);
1648
1649 /* handle hba phys */
1650
1651 /* read sas_iounit page 0 */
1652 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
1653 sizeof(Mpi2SasIOUnit0PhyData_t));
1654 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
1655 if (!sas_iounit_pg0) {
1656 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1657 ioc->name, __FILE__, __LINE__, __func__);
1658 rc = -ENOMEM;
1659 goto out;
1660 }
1661 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
1662 sas_iounit_pg0, sz))) {
1663 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1664 ioc->name, __FILE__, __LINE__, __func__);
1665 rc = -ENXIO;
1666 goto out;
1667 }
1668 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1669 MPI2_IOCSTATUS_MASK;
1670 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1671 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1672 ioc->name, __FILE__, __LINE__, __func__);
1673 rc = -EIO;
1674 goto out;
1675 }
1676
1677 /* unable to enable/disable phys when when discovery is active */
1678 for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
1679 if (sas_iounit_pg0->PhyData[i].PortFlags &
1680 MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
1681 pr_err(MPT3SAS_FMT "discovery is active on " \
1682 "port = %d, phy = %d: unable to enable/disable "
1683 "phys, try again later!\n", ioc->name,
1684 sas_iounit_pg0->PhyData[i].Port, i);
1685 discovery_active = 1;
1686 }
1687 }
1688
1689 if (discovery_active) {
1690 rc = -EAGAIN;
1691 goto out;
1692 }
1693
1694 /* read sas_iounit page 1 */
1695 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1696 sizeof(Mpi2SasIOUnit1PhyData_t));
1697 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1698 if (!sas_iounit_pg1) {
1699 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1700 ioc->name, __FILE__, __LINE__, __func__);
1701 rc = -ENOMEM;
1702 goto out;
1703 }
1704 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1705 sas_iounit_pg1, sz))) {
1706 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1707 ioc->name, __FILE__, __LINE__, __func__);
1708 rc = -ENXIO;
1709 goto out;
1710 }
1711 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1712 MPI2_IOCSTATUS_MASK;
1713 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1714 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1715 ioc->name, __FILE__, __LINE__, __func__);
1716 rc = -EIO;
1717 goto out;
1718 }
1719
1720 /* copy Port/PortFlags/PhyFlags from page 0 */
1721 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
1722 sas_iounit_pg1->PhyData[i].Port =
1723 sas_iounit_pg0->PhyData[i].Port;
1724 sas_iounit_pg1->PhyData[i].PortFlags =
1725 (sas_iounit_pg0->PhyData[i].PortFlags &
1726 MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
1727 sas_iounit_pg1->PhyData[i].PhyFlags =
1728 (sas_iounit_pg0->PhyData[i].PhyFlags &
1729 (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
1730 MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
1731 }
1732
1733 if (enable)
1734 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1735 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1736 else
1737 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1738 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1739
1740 mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1741
1742 /* link reset */
1743 if (enable)
1744 _transport_phy_reset(phy, 0);
1745
1746 out:
1747 kfree(sas_iounit_pg1);
1748 kfree(sas_iounit_pg0);
1749 return rc;
1750}
1751
1752/**
1753 * _transport_phy_speed - set phy min/max link rates
1754 * @phy: The sas phy object
1755 * @rates: rates defined in sas_phy_linkrates
1756 *
1757 * Only support sas_host direct attached phys.
1758 * Returns 0 for success, non-zero for failure.
1759 */
1760static int
1761_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1762{
1763 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1764 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1765 Mpi2SasPhyPage0_t phy_pg0;
1766 Mpi2ConfigReply_t mpi_reply;
1767 u16 ioc_status;
1768 u16 sz;
1769 int i;
1770 int rc = 0;
1771 unsigned long flags;
1772
1773 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1774 if (_transport_sas_node_find_by_sas_address(ioc,
1775 phy->identify.sas_address) == NULL) {
1776 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1777 return -EINVAL;
1778 }
1779 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1780
1781 if (!rates->minimum_linkrate)
1782 rates->minimum_linkrate = phy->minimum_linkrate;
1783 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1784 rates->minimum_linkrate = phy->minimum_linkrate_hw;
1785
1786 if (!rates->maximum_linkrate)
1787 rates->maximum_linkrate = phy->maximum_linkrate;
1788 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1789 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1790
1791 /* handle expander phys */
1792 if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1793 phy->minimum_linkrate = rates->minimum_linkrate;
1794 phy->maximum_linkrate = rates->maximum_linkrate;
1795 return _transport_expander_phy_control(ioc, phy,
1796 SMP_PHY_CONTROL_LINK_RESET);
1797 }
1798
1799 /* handle hba phys */
1800
1801 /* sas_iounit page 1 */
1802 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1803 sizeof(Mpi2SasIOUnit1PhyData_t));
1804 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1805 if (!sas_iounit_pg1) {
1806 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1807 ioc->name, __FILE__, __LINE__, __func__);
1808 rc = -ENOMEM;
1809 goto out;
1810 }
1811 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1812 sas_iounit_pg1, sz))) {
1813 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1814 ioc->name, __FILE__, __LINE__, __func__);
1815 rc = -ENXIO;
1816 goto out;
1817 }
1818 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1819 MPI2_IOCSTATUS_MASK;
1820 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1821 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1822 ioc->name, __FILE__, __LINE__, __func__);
1823 rc = -EIO;
1824 goto out;
1825 }
1826
1827 for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1828 if (phy->number != i) {
1829 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1830 (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1831 (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1832 } else {
1833 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1834 (rates->minimum_linkrate +
1835 (rates->maximum_linkrate << 4));
1836 }
1837 }
1838
1839 if (mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1840 sz)) {
1841 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1842 ioc->name, __FILE__, __LINE__, __func__);
1843 rc = -ENXIO;
1844 goto out;
1845 }
1846
1847 /* link reset */
1848 _transport_phy_reset(phy, 0);
1849
1850 /* read phy page 0, then update the rates in the sas transport phy */
1851 if (!mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1852 phy->number)) {
1853 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1854 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1855 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1856 phy_pg0.ProgrammedLinkRate >> 4);
1857 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1858 phy_pg0.NegotiatedLinkRate &
1859 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1860 }
1861
1862 out:
1863 kfree(sas_iounit_pg1);
1864 return rc;
1865}
1866
1867/**
1868 * _transport_smp_handler - transport portal for smp passthru
1869 * @shost: shost object
1870 * @rphy: sas transport rphy object
1871 * @req:
1872 *
1873 * This used primarily for smp_utils.
1874 * Example:
1875 * smp_rep_general /sys/class/bsg/expander-5:0
1876 */
1877static int
1878_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1879 struct request *req)
1880{
1881 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1882 Mpi2SmpPassthroughRequest_t *mpi_request;
1883 Mpi2SmpPassthroughReply_t *mpi_reply;
1884 int rc, i;
1885 u16 smid;
1886 u32 ioc_state;
1887 unsigned long timeleft;
1888 void *psge;
1889 u8 issue_reset = 0;
1890 dma_addr_t dma_addr_in = 0;
1891 dma_addr_t dma_addr_out = 0;
1892 dma_addr_t pci_dma_in = 0;
1893 dma_addr_t pci_dma_out = 0;
1894 void *pci_addr_in = NULL;
1895 void *pci_addr_out = NULL;
1896 u16 wait_state_count;
1897 struct request *rsp = req->next_rq;
1898 struct bio_vec *bvec = NULL;
1899
1900 if (!rsp) {
1901 pr_err(MPT3SAS_FMT "%s: the smp response space is missing\n",
1902 ioc->name, __func__);
1903 return -EINVAL;
1904 }
1905
1906 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1907 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1908 __func__, ioc->name);
1909 return -EFAULT;
1910 }
1911
1912 rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1913 if (rc)
1914 return rc;
1915
1916 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1917 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name,
1918 __func__);
1919 rc = -EAGAIN;
1920 goto out;
1921 }
1922 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1923
1924 /* Check if the request is split across multiple segments */
1925 if (req->bio->bi_vcnt > 1) {
1926 u32 offset = 0;
1927
1928 /* Allocate memory and copy the request */
1929 pci_addr_out = pci_alloc_consistent(ioc->pdev,
1930 blk_rq_bytes(req), &pci_dma_out);
1931 if (!pci_addr_out) {
1932 pr_info(MPT3SAS_FMT "%s(): PCI Addr out = NULL\n",
1933 ioc->name, __func__);
1934 rc = -ENOMEM;
1935 goto out;
1936 }
1937
1938 bio_for_each_segment(bvec, req->bio, i) {
1939 memcpy(pci_addr_out + offset,
1940 page_address(bvec->bv_page) + bvec->bv_offset,
1941 bvec->bv_len);
1942 offset += bvec->bv_len;
1943 }
1944 } else {
1945 dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1946 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1947 if (!dma_addr_out) {
1948 pr_info(MPT3SAS_FMT "%s(): DMA Addr out = NULL\n",
1949 ioc->name, __func__);
1950 rc = -ENOMEM;
1951 goto free_pci;
1952 }
1953 }
1954
1955 /* Check if the response needs to be populated across
1956 * multiple segments */
1957 if (rsp->bio->bi_vcnt > 1) {
1958 pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
1959 &pci_dma_in);
1960 if (!pci_addr_in) {
1961 pr_info(MPT3SAS_FMT "%s(): PCI Addr in = NULL\n",
1962 ioc->name, __func__);
1963 rc = -ENOMEM;
1964 goto unmap;
1965 }
1966 } else {
1967 dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1968 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1969 if (!dma_addr_in) {
1970 pr_info(MPT3SAS_FMT "%s(): DMA Addr in = NULL\n",
1971 ioc->name, __func__);
1972 rc = -ENOMEM;
1973 goto unmap;
1974 }
1975 }
1976
1977 wait_state_count = 0;
1978 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1979 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1980 if (wait_state_count++ == 10) {
1981 pr_err(MPT3SAS_FMT
1982 "%s: failed due to ioc not operational\n",
1983 ioc->name, __func__);
1984 rc = -EFAULT;
1985 goto unmap;
1986 }
1987 ssleep(1);
1988 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1989 pr_info(MPT3SAS_FMT
1990 "%s: waiting for operational state(count=%d)\n",
1991 ioc->name, __func__, wait_state_count);
1992 }
1993 if (wait_state_count)
1994 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1995 ioc->name, __func__);
1996
1997 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1998 if (!smid) {
1999 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2000 ioc->name, __func__);
2001 rc = -EAGAIN;
2002 goto unmap;
2003 }
2004
2005 rc = 0;
2006 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2007 ioc->transport_cmds.smid = smid;
2008
2009 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
2010 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
2011 mpi_request->PhysicalPort = 0xFF;
2012 mpi_request->SASAddress = (rphy) ?
2013 cpu_to_le64(rphy->identify.sas_address) :
2014 cpu_to_le64(ioc->sas_hba.sas_address);
2015 mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
2016 psge = &mpi_request->SGL;
2017
2018 if (req->bio->bi_vcnt > 1)
2019 ioc->build_sg(ioc, psge, pci_dma_out, (blk_rq_bytes(req) - 4),
2020 pci_dma_in, (blk_rq_bytes(rsp) + 4));
2021 else
2022 ioc->build_sg(ioc, psge, dma_addr_out, (blk_rq_bytes(req) - 4),
2023 dma_addr_in, (blk_rq_bytes(rsp) + 4));
2024
2025 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2026 "%s - sending smp request\n", ioc->name, __func__));
2027
2028 init_completion(&ioc->transport_cmds.done);
2029 mpt3sas_base_put_smid_default(ioc, smid);
2030 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
2031 10*HZ);
2032
2033 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
2034 pr_err(MPT3SAS_FMT "%s : timeout\n",
2035 __func__, ioc->name);
2036 _debug_dump_mf(mpi_request,
2037 sizeof(Mpi2SmpPassthroughRequest_t)/4);
2038 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
2039 issue_reset = 1;
2040 goto issue_host_reset;
2041 }
2042
2043 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2044 "%s - complete\n", ioc->name, __func__));
2045
2046 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
2047
2048 mpi_reply = ioc->transport_cmds.reply;
2049
2050 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2051 "%s - reply data transfer size(%d)\n",
2052 ioc->name, __func__,
2053 le16_to_cpu(mpi_reply->ResponseDataLength)));
2054
2055 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
2056 req->sense_len = sizeof(*mpi_reply);
2057 req->resid_len = 0;
2058 rsp->resid_len -=
2059 le16_to_cpu(mpi_reply->ResponseDataLength);
2060
2061 /* check if the resp needs to be copied from the allocated
2062 * pci mem */
2063 if (rsp->bio->bi_vcnt > 1) {
2064 u32 offset = 0;
2065 u32 bytes_to_copy =
2066 le16_to_cpu(mpi_reply->ResponseDataLength);
2067 bio_for_each_segment(bvec, rsp->bio, i) {
2068 if (bytes_to_copy <= bvec->bv_len) {
2069 memcpy(page_address(bvec->bv_page) +
2070 bvec->bv_offset, pci_addr_in +
2071 offset, bytes_to_copy);
2072 break;
2073 } else {
2074 memcpy(page_address(bvec->bv_page) +
2075 bvec->bv_offset, pci_addr_in +
2076 offset, bvec->bv_len);
2077 bytes_to_copy -= bvec->bv_len;
2078 }
2079 offset += bvec->bv_len;
2080 }
2081 }
2082 } else {
2083 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2084 "%s - no reply\n", ioc->name, __func__));
2085 rc = -ENXIO;
2086 }
2087
2088 issue_host_reset:
2089 if (issue_reset) {
2090 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2091 FORCE_BIG_HAMMER);
2092 rc = -ETIMEDOUT;
2093 }
2094
2095 unmap:
2096 if (dma_addr_out)
2097 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
2098 PCI_DMA_BIDIRECTIONAL);
2099 if (dma_addr_in)
2100 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
2101 PCI_DMA_BIDIRECTIONAL);
2102
2103 free_pci:
2104 if (pci_addr_out)
2105 pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out,
2106 pci_dma_out);
2107
2108 if (pci_addr_in)
2109 pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in,
2110 pci_dma_in);
2111
2112 out:
2113 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
2114 mutex_unlock(&ioc->transport_cmds.mutex);
2115 return rc;
2116}
2117
2118struct sas_function_template mpt3sas_transport_functions = {
2119 .get_linkerrors = _transport_get_linkerrors,
2120 .get_enclosure_identifier = _transport_get_enclosure_identifier,
2121 .get_bay_identifier = _transport_get_bay_identifier,
2122 .phy_reset = _transport_phy_reset,
2123 .phy_enable = _transport_phy_enable,
2124 .set_phy_speed = _transport_phy_speed,
2125 .smp_handler = _transport_smp_handler,
2126};
2127
2128struct scsi_transport_template *mpt3sas_transport_template;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
new file mode 100644
index 000000000000..da6c5f25749c
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
@@ -0,0 +1,434 @@
1/*
2 * This module provides common API to set Diagnostic trigger for MPT
3 * (Message Passing Technology) based controllers
4 *
5 * This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
6 * Copyright (C) 2012 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/compat.h>
55#include <linux/poll.h>
56
57#include <linux/io.h>
58#include <linux/uaccess.h>
59
60#include "mpt3sas_base.h"
61
62/**
63 * _mpt3sas_raise_sigio - notifiy app
64 * @ioc: per adapter object
65 * @event_data:
66 */
67static void
68_mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc,
69 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
70{
71 Mpi2EventNotificationReply_t *mpi_reply;
72 u16 sz, event_data_sz;
73 unsigned long flags;
74
75 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n",
76 ioc->name, __func__));
77
78 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
79 sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4;
80 mpi_reply = kzalloc(sz, GFP_KERNEL);
81 if (!mpi_reply)
82 goto out;
83 mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED);
84 event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4;
85 mpi_reply->EventDataLength = cpu_to_le16(event_data_sz);
86 memcpy(&mpi_reply->EventData, event_data,
87 sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
88 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
89 "%s: add to driver event log\n",
90 ioc->name, __func__));
91 mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
92 kfree(mpi_reply);
93 out:
94
95 /* clearing the diag_trigger_active flag */
96 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
97 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
98 "%s: clearing diag_trigger_active flag\n",
99 ioc->name, __func__));
100 ioc->diag_trigger_active = 0;
101 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
102
103 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
104 __func__));
105}
106
107/**
108 * mpt3sas_process_trigger_data - process the event data for the trigger
109 * @ioc: per adapter object
110 * @event_data:
111 */
112void
113mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
114 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
115{
116 u8 issue_reset = 0;
117
118 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n",
119 ioc->name, __func__));
120
121 /* release the diag buffer trace */
122 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
123 MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
124 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
125 "%s: release trace diag buffer\n", ioc->name, __func__));
126 mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
127 &issue_reset);
128 }
129
130 _mpt3sas_raise_sigio(ioc, event_data);
131
132 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
133 __func__));
134}
135
136/**
137 * mpt3sas_trigger_master - Master trigger handler
138 * @ioc: per adapter object
139 * @trigger_bitmask:
140 *
141 */
142void
143mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask)
144{
145 struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
146 unsigned long flags;
147 u8 found_match = 0;
148
149 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
150
151 if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
152 trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
153 goto by_pass_checks;
154
155 /* check to see if trace buffers are currently registered */
156 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
157 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
158 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
159 return;
160 }
161
162 /* check to see if trace buffers are currently released */
163 if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
164 MPT3_DIAG_BUFFER_IS_RELEASED) {
165 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
166 return;
167 }
168
169 by_pass_checks:
170
171 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
172 "%s: enter - trigger_bitmask = 0x%08x\n",
173 ioc->name, __func__, trigger_bitmask));
174
175 /* don't send trigger if an trigger is currently active */
176 if (ioc->diag_trigger_active) {
177 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
178 goto out;
179 }
180
181 /* check for the trigger condition */
182 if (ioc->diag_trigger_master.MasterData & trigger_bitmask) {
183 found_match = 1;
184 ioc->diag_trigger_active = 1;
185 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
186 "%s: setting diag_trigger_active flag\n",
187 ioc->name, __func__));
188 }
189 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
190
191 if (!found_match)
192 goto out;
193
194 memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
195 event_data.trigger_type = MPT3SAS_TRIGGER_MASTER;
196 event_data.u.master.MasterData = trigger_bitmask;
197
198 if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT ||
199 trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET)
200 _mpt3sas_raise_sigio(ioc, &event_data);
201 else
202 mpt3sas_send_trigger_data_event(ioc, &event_data);
203
204 out:
205 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
206 __func__));
207}
208
209/**
210 * mpt3sas_trigger_event - Event trigger handler
211 * @ioc: per adapter object
212 * @event:
213 * @log_entry_qualifier:
214 *
215 */
216void
217mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event,
218 u16 log_entry_qualifier)
219{
220 struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
221 struct SL_WH_EVENT_TRIGGER_T *event_trigger;
222 int i;
223 unsigned long flags;
224 u8 found_match;
225
226 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
227
228 /* check to see if trace buffers are currently registered */
229 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
230 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
231 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
232 return;
233 }
234
235 /* check to see if trace buffers are currently released */
236 if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
237 MPT3_DIAG_BUFFER_IS_RELEASED) {
238 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
239 return;
240 }
241
242 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
243 "%s: enter - event = 0x%04x, log_entry_qualifier = 0x%04x\n",
244 ioc->name, __func__, event, log_entry_qualifier));
245
246 /* don't send trigger if an trigger is currently active */
247 if (ioc->diag_trigger_active) {
248 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
249 goto out;
250 }
251
252 /* check for the trigger condition */
253 event_trigger = ioc->diag_trigger_event.EventTriggerEntry;
254 for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries
255 && !found_match; i++, event_trigger++) {
256 if (event_trigger->EventValue != event)
257 continue;
258 if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
259 if (event_trigger->LogEntryQualifier ==
260 log_entry_qualifier)
261 found_match = 1;
262 continue;
263 }
264 found_match = 1;
265 ioc->diag_trigger_active = 1;
266 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
267 "%s: setting diag_trigger_active flag\n",
268 ioc->name, __func__));
269 }
270 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
271
272 if (!found_match)
273 goto out;
274
275 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
276 "%s: setting diag_trigger_active flag\n",
277 ioc->name, __func__));
278 memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
279 event_data.trigger_type = MPT3SAS_TRIGGER_EVENT;
280 event_data.u.event.EventValue = event;
281 event_data.u.event.LogEntryQualifier = log_entry_qualifier;
282 mpt3sas_send_trigger_data_event(ioc, &event_data);
283 out:
284 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
285 __func__));
286}
287
288/**
289 * mpt3sas_trigger_scsi - SCSI trigger handler
290 * @ioc: per adapter object
291 * @sense_key:
292 * @asc:
293 * @ascq:
294 *
295 */
296void
297mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc,
298 u8 ascq)
299{
300 struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
301 struct SL_WH_SCSI_TRIGGER_T *scsi_trigger;
302 int i;
303 unsigned long flags;
304 u8 found_match;
305
306 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
307
308 /* check to see if trace buffers are currently registered */
309 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
310 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
311 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
312 return;
313 }
314
315 /* check to see if trace buffers are currently released */
316 if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
317 MPT3_DIAG_BUFFER_IS_RELEASED) {
318 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
319 return;
320 }
321
322 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
323 "%s: enter - sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n",
324 ioc->name, __func__, sense_key, asc, ascq));
325
326 /* don't send trigger if an trigger is currently active */
327 if (ioc->diag_trigger_active) {
328 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
329 goto out;
330 }
331
332 /* check for the trigger condition */
333 scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry;
334 for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries
335 && !found_match; i++, scsi_trigger++) {
336 if (scsi_trigger->SenseKey != sense_key)
337 continue;
338 if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc))
339 continue;
340 if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq))
341 continue;
342 found_match = 1;
343 ioc->diag_trigger_active = 1;
344 }
345 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
346
347 if (!found_match)
348 goto out;
349
350 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
351 "%s: setting diag_trigger_active flag\n",
352 ioc->name, __func__));
353 memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
354 event_data.trigger_type = MPT3SAS_TRIGGER_SCSI;
355 event_data.u.scsi.SenseKey = sense_key;
356 event_data.u.scsi.ASC = asc;
357 event_data.u.scsi.ASCQ = ascq;
358 mpt3sas_send_trigger_data_event(ioc, &event_data);
359 out:
360 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
361 __func__));
362}
363
364/**
365 * mpt3sas_trigger_mpi - MPI trigger handler
366 * @ioc: per adapter object
367 * @ioc_status:
368 * @loginfo:
369 *
370 */
371void
372mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo)
373{
374 struct SL_WH_TRIGGERS_EVENT_DATA_T event_data;
375 struct SL_WH_MPI_TRIGGER_T *mpi_trigger;
376 int i;
377 unsigned long flags;
378 u8 found_match;
379
380 spin_lock_irqsave(&ioc->diag_trigger_lock, flags);
381
382 /* check to see if trace buffers are currently registered */
383 if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
384 MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
385 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
386 return;
387 }
388
389 /* check to see if trace buffers are currently released */
390 if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
391 MPT3_DIAG_BUFFER_IS_RELEASED) {
392 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
393 return;
394 }
395
396 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
397 "%s: enter - ioc_status = 0x%04x, loginfo = 0x%08x\n",
398 ioc->name, __func__, ioc_status, loginfo));
399
400 /* don't send trigger if an trigger is currently active */
401 if (ioc->diag_trigger_active) {
402 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
403 goto out;
404 }
405
406 /* check for the trigger condition */
407 mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry;
408 for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries
409 && !found_match; i++, mpi_trigger++) {
410 if (mpi_trigger->IOCStatus != ioc_status)
411 continue;
412 if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF ||
413 mpi_trigger->IocLogInfo == loginfo))
414 continue;
415 found_match = 1;
416 ioc->diag_trigger_active = 1;
417 }
418 spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags);
419
420 if (!found_match)
421 goto out;
422
423 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT
424 "%s: setting diag_trigger_active flag\n",
425 ioc->name, __func__));
426 memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T));
427 event_data.trigger_type = MPT3SAS_TRIGGER_MPI;
428 event_data.u.mpi.IOCStatus = ioc_status;
429 event_data.u.mpi.IocLogInfo = loginfo;
430 mpt3sas_send_trigger_data_event(ioc, &event_data);
431 out:
432 dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name,
433 __func__));
434}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
new file mode 100644
index 000000000000..a10c30907394
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
@@ -0,0 +1,193 @@
1/*
2 * This is the Fusion MPT base driver providing common API layer interface
3 * to set Diagnostic triggers for MPT (Message Passing Technology) based
4 * controllers
5 *
6 * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h
7 * Copyright (C) 2012 LSI Corporation
8 * (mailto:DL-MPTFusionLinux@lsi.com)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * NO WARRANTY
21 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 * solely responsible for determining the appropriateness of using and
26 * distributing the Program and assumes all risks associated with its
27 * exercise of rights under this Agreement, including but not limited to
28 * the risks and costs of program errors, damage to or loss of data,
29 * programs or equipment, and unavailability or interruption of operations.
30
31 * DISCLAIMER OF LIABILITY
32 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
43 * USA.
44 */
45 /* Diagnostic Trigger Configuration Data Structures */
46
47#ifndef MPT3SAS_TRIGGER_DIAG_H_INCLUDED
48#define MPT3SAS_TRIGGER_DIAG_H_INCLUDED
49
50/* limitation on number of entries */
51#define NUM_VALID_ENTRIES (20)
52
53/* trigger types */
54#define MPT3SAS_TRIGGER_MASTER (1)
55#define MPT3SAS_TRIGGER_EVENT (2)
56#define MPT3SAS_TRIGGER_SCSI (3)
57#define MPT3SAS_TRIGGER_MPI (4)
58
59/* trigger names */
60#define MASTER_TRIGGER_FILE_NAME "diag_trigger_master"
61#define EVENT_TRIGGERS_FILE_NAME "diag_trigger_event"
62#define SCSI_TRIGGERS_FILE_NAME "diag_trigger_scsi"
63#define MPI_TRIGGER_FILE_NAME "diag_trigger_mpi"
64
65/* master trigger bitmask */
66#define MASTER_TRIGGER_FW_FAULT (0x00000001)
67#define MASTER_TRIGGER_ADAPTER_RESET (0x00000002)
68#define MASTER_TRIGGER_TASK_MANAGMENT (0x00000004)
69#define MASTER_TRIGGER_DEVICE_REMOVAL (0x00000008)
70
71/* fake firmware event for tigger */
72#define MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED (0x6E)
73
74/**
75 * MasterTrigger is a single U32 passed to/from sysfs.
76 *
77 * Bit Flags (enables) include:
78 * 1. FW Faults
79 * 2. Adapter Reset issued by driver
80 * 3. TMs
81 * 4. Device Remove Event sent by FW
82 */
83
84struct SL_WH_MASTER_TRIGGER_T {
85 uint32_t MasterData;
86};
87
88/**
89 * struct SL_WH_EVENT_TRIGGER_T - Definition of an event trigger element
90 * @EventValue: Event Code to trigger on
91 * @LogEntryQualifier: Type of FW event that logged (Log Entry Added Event only)
92 *
93 * Defines an event that should induce a DIAG_TRIGGER driver event if observed.
94 */
95struct SL_WH_EVENT_TRIGGER_T {
96 uint16_t EventValue;
97 uint16_t LogEntryQualifier;
98};
99
100/**
101 * struct SL_WH_EVENT_TRIGGERS_T - Structure passed to/from sysfs containing a
102 * list of Event Triggers to be monitored for.
103 * @ValidEntries: Number of _SL_WH_EVENT_TRIGGER_T structures contained in this
104 * structure.
105 * @EventTriggerEntry: List of Event trigger elements.
106 *
107 * This binary structure is transferred via sysfs to get/set Event Triggers
108 * in the Linux Driver.
109 */
110
111struct SL_WH_EVENT_TRIGGERS_T {
112 uint32_t ValidEntries;
113 struct SL_WH_EVENT_TRIGGER_T EventTriggerEntry[NUM_VALID_ENTRIES];
114};
115
116/**
117 * struct SL_WH_SCSI_TRIGGER_T - Definition of a SCSI trigger element
118 * @ASCQ: Additional Sense Code Qualifier. Can be specific or 0xFF for
119 * wildcard.
120 * @ASC: Additional Sense Code. Can be specific or 0xFF for wildcard
121 * @SenseKey: SCSI Sense Key
122 *
123 * Defines a sense key (single or many variants) that should induce a
124 * DIAG_TRIGGER driver event if observed.
125 */
126struct SL_WH_SCSI_TRIGGER_T {
127 U8 ASCQ;
128 U8 ASC;
129 U8 SenseKey;
130 U8 Reserved;
131};
132
133/**
134 * struct SL_WH_SCSI_TRIGGERS_T - Structure passed to/from sysfs containing a
135 * list of SCSI sense codes that should trigger a DIAG_SERVICE event when
136 * observed.
137 * @ValidEntries: Number of _SL_WH_SCSI_TRIGGER_T structures contained in this
138 * structure.
139 * @SCSITriggerEntry: List of SCSI Sense Code trigger elements.
140 *
141 * This binary structure is transferred via sysfs to get/set SCSI Sense Code
142 * Triggers in the Linux Driver.
143 */
144struct SL_WH_SCSI_TRIGGERS_T {
145 uint32_t ValidEntries;
146 struct SL_WH_SCSI_TRIGGER_T SCSITriggerEntry[NUM_VALID_ENTRIES];
147};
148
149/**
150 * struct SL_WH_MPI_TRIGGER_T - Definition of an MPI trigger element
151 * @IOCStatus: MPI IOCStatus
152 * @IocLogInfo: MPI IocLogInfo. Can be specific or 0xFFFFFFFF for wildcard
153 *
154 * Defines a MPI IOCStatus/IocLogInfo pair that should induce a DIAG_TRIGGER
155 * driver event if observed.
156 */
157struct SL_WH_MPI_TRIGGER_T {
158 uint16_t IOCStatus;
159 uint16_t Reserved;
160 uint32_t IocLogInfo;
161};
162
163/**
164 * struct SL_WH_MPI_TRIGGERS_T - Structure passed to/from sysfs containing a
165 * list of MPI IOCStatus/IocLogInfo pairs that should trigger a DIAG_SERVICE
166 * event when observed.
167 * @ValidEntries: Number of _SL_WH_MPI_TRIGGER_T structures contained in this
168 * structure.
169 * @MPITriggerEntry: List of MPI IOCStatus/IocLogInfo trigger elements.
170 *
171 * This binary structure is transferred via sysfs to get/set MPI Error Triggers
172 * in the Linux Driver.
173 */
174struct SL_WH_MPI_TRIGGERS_T {
175 uint32_t ValidEntries;
176 struct SL_WH_MPI_TRIGGER_T MPITriggerEntry[NUM_VALID_ENTRIES];
177};
178
179/**
180 * struct SL_WH_TRIGGERS_EVENT_DATA_T - event data for trigger
181 * @trigger_type: trigger type (see MPT3SAS_TRIGGER_XXXX)
182 * @u: trigger condition that caused trigger to be sent
183 */
184struct SL_WH_TRIGGERS_EVENT_DATA_T {
185 uint32_t trigger_type;
186 union {
187 struct SL_WH_MASTER_TRIGGER_T master;
188 struct SL_WH_EVENT_TRIGGER_T event;
189 struct SL_WH_SCSI_TRIGGER_T scsi;
190 struct SL_WH_MPI_TRIGGER_T mpi;
191 } u;
192};
193#endif /* MPT3SAS_TRIGGER_DIAG_H_INCLUDED */