aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorSreekanth Reddy <Sreekanth.Reddy@lsi.com>2012-11-29 21:14:21 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-12-01 05:09:17 -0500
commitf92363d12359498f9a9960511de1a550f0ec41c2 (patch)
treec7f34e33b085b5da0b36e8d830cd98fc74d5ab58 /drivers/scsi
parentd84fd392bd61524c4d81367969424e6c17086c8c (diff)
[SCSI] mpt3sas: add new driver supporting 12GB SAS
These driver files are initially, substantially similar to mpt2sas but, because mpt2sas is going into maintenance mode and mp3sas will become heavily developed, we elected to keep the code bases separate. Signed-off-by: Sreekanth Reddy <Sreekanth.Reddy@lsi.com> Reviewed-by: Nagalakshmi Nandigama <Nagalakshmi.Nandigama@lsi.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
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 */